Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 237 lines (205 sloc) 6.574 kb
4a5d9b0 Hayden Moved Sapphire module to open source path
Hayden authored
1 <?php
2 /**
3 * Provides introspection information about the class tree.
3a6341a Simon Welsh API-CHANGE sapphire folder can now be renamed.
simonwelsh authored
4 * It's a cached wrapper around the built-in class functions. SilverStripe uses class introspection heavily
4a5d9b0 Hayden Moved Sapphire module to open source path
Hayden authored
5 * and without the caching it creates an unfortunate performance hit.
7d13ba7 madmatt Reverted geoffm's accidental commit to /open
madmatt authored
6 *
f07258f Simon Welsh MINOR Update @package values to match renaming sapphire
simonwelsh authored
7 * @package framework
7d13ba7 madmatt Reverted geoffm's accidental commit to /open
madmatt authored
8 * @subpackage core
4a5d9b0 Hayden Moved Sapphire module to open source path
Hayden authored
9 */
10 class ClassInfo {
705a29d Mateusz U BUGFIX: fix the ClassInfo::allClasses to fetch manifest data directly
mateusz authored
11 /**
12 * Wrapper for classes getter.
59d8a1c Sam Minnée Improving API documentation
sminnee authored
13 */
4a5d9b0 Hayden Moved Sapphire module to open source path
Hayden authored
14 static function allClasses() {
705a29d Mateusz U BUGFIX: fix the ClassInfo::allClasses to fetch manifest data directly
mateusz authored
15 return SS_ClassLoader::instance()->getManifest()->getClasses();
4a5d9b0 Hayden Moved Sapphire module to open source path
Hayden authored
16 }
59d8a1c Sam Minnée Improving API documentation
sminnee authored
17
18 /**
19 * @todo Improve documentation
20 */
4a5d9b0 Hayden Moved Sapphire module to open source path
Hayden authored
21 static function exists($class) {
bc0a1b7 Andrew Short MINOR: Updated various methods to use new manifest methods rather than M...
ajshort authored
22 return SS_ClassLoader::instance()->classExists($class);
4a5d9b0 Hayden Moved Sapphire module to open source path
Hayden authored
23 }
59d8a1c Sam Minnée Improving API documentation
sminnee authored
24
25 /**
635e2c3 Andrew O'Neil Merged from 2.3
ajoneil authored
26 * Cache for {@link hasTable()}
27 */
28 private static $_cache_all_tables = null;
4056b94 Ingo Schommer BUGFIX Improved ClassInfo::ancestry() performance through in-memory cach...
chillu authored
29
30 /**
31 * @var Array Cache for {@link ancestry()}.
32 */
33 private static $_cache_ancestry = array();
635e2c3 Andrew O'Neil Merged from 2.3
ajoneil authored
34
35 /**
7977304 Andrew Short API CHANGE: Renamed conflicting classes to have an "SS_" namespace, and ...
ajshort authored
36 * @todo Move this to SS_Database or DB
59d8a1c Sam Minnée Improving API documentation
sminnee authored
37 */
4a5d9b0 Hayden Moved Sapphire module to open source path
Hayden authored
38 static function hasTable($class) {
4f6170c Sam Minnée BUGFIX: Better initial-site-setup boundary condition checking needed aft...
sminnee authored
39 if(DB::isActive()) {
635e2c3 Andrew O'Neil Merged from 2.3
ajoneil authored
40 // Cache the list of all table names to reduce on DB traffic
297b006 Sam Minnée MINOR: recache tables if cache is empty (from r103606)
sminnee authored
41 if(empty(self::$_cache_all_tables)) {
635e2c3 Andrew O'Neil Merged from 2.3
ajoneil authored
42 self::$_cache_all_tables = array();
8182a01 gmunn API CHANGE: "SHOW TABLES" replaced with DB-specific version
geoff-silverstripe authored
43 $tables = DB::query(DB::getConn()->allTablesSQL())->column();
635e2c3 Andrew O'Neil Merged from 2.3
ajoneil authored
44 foreach($tables as $table) self::$_cache_all_tables[strtolower($table)] = true;
45 }
46 return isset(self::$_cache_all_tables[strtolower($class)]);
4f6170c Sam Minnée BUGFIX: Better initial-site-setup boundary condition checking needed aft...
sminnee authored
47 } else {
48 return false;
49 }
4a5d9b0 Hayden Moved Sapphire module to open source path
Hayden authored
50 }
51
e921b37 Ingo Schommer API CHANGE: Don't generate TestOnly DataObjects in the database immediat...
chillu authored
52 static function reset_db_cache() {
53 self::$_cache_all_tables = null;
4056b94 Ingo Schommer BUGFIX Improved ClassInfo::ancestry() performance through in-memory cach...
chillu authored
54 self::$_cache_ancestry = array();
e921b37 Ingo Schommer API CHANGE: Don't generate TestOnly DataObjects in the database immediat...
chillu authored
55 }
56
4a5d9b0 Hayden Moved Sapphire module to open source path
Hayden authored
57 /**
58 * Returns the manifest of all classes which are present in the database.
6f8baaa Sam Minnée ENHANCEMENT #5977 Added optional argument to ClassInfo::getValidSubClass...
sminnee authored
59 * @param string $class Class name to check enum values for ClassName field
4a5d9b0 Hayden Moved Sapphire module to open source path
Hayden authored
60 */
6f8baaa Sam Minnée ENHANCEMENT #5977 Added optional argument to ClassInfo::getValidSubClass...
sminnee authored
61 static function getValidSubClasses($class = 'SiteTree') {
62 return DB::getConn()->enumValuesForField($class, 'ClassName');
4a5d9b0 Hayden Moved Sapphire module to open source path
Hayden authored
63 }
64
65 /**
f55cc7e Andrew Short MINOR: Refactored ClassInfo::dataClassesFor() to use existing methods ra...
ajshort authored
66 * Returns an array of the current class and all its ancestors and children
67 * which have a DB table.
e12f87a Mark Rickerby When ClassInfo::dataClassesFor is passed an instance of the class, the m...
maetl authored
68 *
f55cc7e Andrew Short MINOR: Refactored ClassInfo::dataClassesFor() to use existing methods ra...
ajshort authored
69 * @param string|object $class
c1d6e82 Sam Minnée API CHANGE: Removed manifest's dependency on database, by removing hasta...
sminnee authored
70 * @todo Move this into data object
e12f87a Mark Rickerby When ClassInfo::dataClassesFor is passed an instance of the class, the m...
maetl authored
71 * @return array
4a5d9b0 Hayden Moved Sapphire module to open source path
Hayden authored
72 */
f55cc7e Andrew Short MINOR: Refactored ClassInfo::dataClassesFor() to use existing methods ra...
ajshort authored
73 public static function dataClassesFor($class) {
74 $result = array();
75
76 if (is_object($class)) {
77 $class = get_class($class);
4a5d9b0 Hayden Moved Sapphire module to open source path
Hayden authored
78 }
79
f55cc7e Andrew Short MINOR: Refactored ClassInfo::dataClassesFor() to use existing methods ra...
ajshort authored
80 $classes = array_merge(
81 self::ancestry($class),
82 self::subclassesFor($class));
83
84 foreach ($classes as $class) {
85 if (self::hasTable($class)) $result[$class] = $class;
4a5d9b0 Hayden Moved Sapphire module to open source path
Hayden authored
86 }
f55cc7e Andrew Short MINOR: Refactored ClassInfo::dataClassesFor() to use existing methods ra...
ajshort authored
87
88 return $result;
4a5d9b0 Hayden Moved Sapphire module to open source path
Hayden authored
89 }
0d03348 Andrew Short API CHANGE: Refactored ClassInfo::baseDataClass() to use inbuilt PHP met...
ajshort authored
90
4a5d9b0 Hayden Moved Sapphire module to open source path
Hayden authored
91 /**
0d03348 Andrew Short API CHANGE: Refactored ClassInfo::baseDataClass() to use inbuilt PHP met...
ajshort authored
92 * Returns the root class (the first to extend from DataObject) for the
93 * passed class.
94 *
95 * @param string|object $class
96 * @return string
4a5d9b0 Hayden Moved Sapphire module to open source path
Hayden authored
97 */
0d03348 Andrew Short API CHANGE: Refactored ClassInfo::baseDataClass() to use inbuilt PHP met...
ajshort authored
98 public static function baseDataClass($class) {
e12f87a Mark Rickerby When ClassInfo::dataClassesFor is passed an instance of the class, the m...
maetl authored
99 if (is_object($class)) $class = get_class($class);
0d03348 Andrew Short API CHANGE: Refactored ClassInfo::baseDataClass() to use inbuilt PHP met...
ajshort authored
100
da64123 Sam Minnée MINOR: Removed use of deprecated ClassInfo::is_subclass_of
sminnee authored
101 if (!is_subclass_of($class, 'DataObject')) {
70d40cf Sam Minnée BUGFIX: Removed use of base "Exception" class in order to avoid failures...
sminnee authored
102 throw new InvalidArgumentException("$class is not a subclass of DataObject");
0d03348 Andrew Short API CHANGE: Refactored ClassInfo::baseDataClass() to use inbuilt PHP met...
ajshort authored
103 }
104
105 while ($next = get_parent_class($class)) {
106 if ($next == 'DataObject') {
107 return $class;
108 }
109
110 $class = $next;
4a5d9b0 Hayden Moved Sapphire module to open source path
Hayden authored
111 }
112 }
0d03348 Andrew Short API CHANGE: Refactored ClassInfo::baseDataClass() to use inbuilt PHP met...
ajshort authored
113
59d8a1c Sam Minnée Improving API documentation
sminnee authored
114 /**
e12f87a Mark Rickerby When ClassInfo::dataClassesFor is passed an instance of the class, the m...
maetl authored
115 * Returns a list of classes that inherit from the given class.
60f75c5 Andrew O'Neil Merged changes from 2.3 branch
ajoneil authored
116 * The resulting array includes the base class passed
117 * through the $class parameter as the first array value.
118 *
119 * Example usage:
b12a00c Ingo Schommer MINOR phpdoc documentation
chillu authored
120 * <code>
60f75c5 Andrew O'Neil Merged changes from 2.3 branch
ajoneil authored
121 * ClassInfo::subclassesFor('BaseClass');
122 * array(
123 * 0 => 'BaseClass',
124 * 'ChildClass' => 'ChildClass',
125 * 'GrandChildClass' => 'GrandChildClass'
126 * )
b12a00c Ingo Schommer MINOR phpdoc documentation
chillu authored
127 * </code>
e12f87a Mark Rickerby When ClassInfo::dataClassesFor is passed an instance of the class, the m...
maetl authored
128 *
129 * @param mixed $class string of the classname or instance of the class
60f75c5 Andrew O'Neil Merged changes from 2.3 branch
ajoneil authored
130 * @return array Names of all subclasses as an associative array.
59d8a1c Sam Minnée Improving API documentation
sminnee authored
131 */
803e67b Andrew Short API CHANGE: Refactored ClassInfo::subclassesFor() to traverse the child ...
ajshort authored
132 public static function subclassesFor($class) {
bc0a1b7 Andrew Short MINOR: Updated various methods to use new manifest methods rather than M...
ajshort authored
133 $descendants = SS_ClassLoader::instance()->getManifest()->getDescendantsOf($class);
134 $result = array($class => $class);
60f75c5 Andrew O'Neil Merged changes from 2.3 branch
ajoneil authored
135
bc0a1b7 Andrew Short MINOR: Updated various methods to use new manifest methods rather than M...
ajshort authored
136 if ($descendants) {
137 return $result + ArrayLib::valuekey($descendants);
138 } else {
139 return $result;
60f75c5 Andrew O'Neil Merged changes from 2.3 branch
ajoneil authored
140 }
4a5d9b0 Hayden Moved Sapphire module to open source path
Hayden authored
141 }
bc0a1b7 Andrew Short MINOR: Updated various methods to use new manifest methods rather than M...
ajshort authored
142
59d8a1c Sam Minnée Improving API documentation
sminnee authored
143 /**
eba1a85 Andrew Short MINOR: Refactored ClassInfo::ancestry() to use inbuilt PHP methods rathe...
ajshort authored
144 * Returns the passed class name along with all its parent class names in an
145 * array, sorted with the root class first.
146 *
147 * @param string $class
148 * @param bool $tablesOnly Only return classes that have a table in the db.
149 * @return array
59d8a1c Sam Minnée Improving API documentation
sminnee authored
150 */
eba1a85 Andrew Short MINOR: Refactored ClassInfo::ancestry() to use inbuilt PHP methods rathe...
ajshort authored
151 public static function ancestry($class, $tablesOnly = false) {
4056b94 Ingo Schommer BUGFIX Improved ClassInfo::ancestry() performance through in-memory cach...
chillu authored
152 if (!is_string($class)) $class = get_class($class);
153
154 $cacheKey = $class . '_' . (string)$tablesOnly;
155 $parent = $class;
156 if(!isset(self::$_cache_ancestry[$cacheKey])) {
157 $ancestry = array();
158 do {
159 if (!$tablesOnly || DataObject::has_own_table($parent)) {
160 $ancestry[$parent] = $parent;
161 }
162 } while ($parent = get_parent_class($parent));
163 self::$_cache_ancestry[$cacheKey] = array_reverse($ancestry);
4a5d9b0 Hayden Moved Sapphire module to open source path
Hayden authored
164 }
eba1a85 Andrew Short MINOR: Refactored ClassInfo::ancestry() to use inbuilt PHP methods rathe...
ajshort authored
165
4056b94 Ingo Schommer BUGFIX Improved ClassInfo::ancestry() performance through in-memory cach...
chillu authored
166 return self::$_cache_ancestry[$cacheKey];
4a5d9b0 Hayden Moved Sapphire module to open source path
Hayden authored
167 }
168
169 /**
7d13ba7 madmatt Reverted geoffm's accidental commit to /open
madmatt authored
170 * @return array A self-keyed array of class names. Note that this is only available with Silverstripe
171 * classes and not built-in PHP classes.
4a5d9b0 Hayden Moved Sapphire module to open source path
Hayden authored
172 */
173 static function implementorsOf($interfaceName) {
bc0a1b7 Andrew Short MINOR: Updated various methods to use new manifest methods rather than M...
ajshort authored
174 return SS_ClassLoader::instance()->getManifest()->getImplementorsOf($interfaceName);
4a5d9b0 Hayden Moved Sapphire module to open source path
Hayden authored
175 }
9ac464c Ingo Schommer (merged from branches/roa. use "svn log -c <changeset> -g <module-svn-pa...
chillu authored
176
177 /**
178 * Returns true if the given class implements the given interface
179 */
180 static function classImplements($className, $interfaceName) {
bc0a1b7 Andrew Short MINOR: Updated various methods to use new manifest methods rather than M...
ajshort authored
181 return in_array($className, SS_ClassLoader::instance()->getManifest()->getImplementorsOf($interfaceName));
9ac464c Ingo Schommer (merged from branches/roa. use "svn log -c <changeset> -g <module-svn-pa...
chillu authored
182 }
a72f7b2 Sam Minnée ENHANCEMENT: Added ClassInfo::is_subclass_of() for better performance
sminnee authored
183
184 /**
d187718 Andrew Short API CHANGE: Deprecated ClassInfo::is_subclass_of() in favour of is_subcl...
ajshort authored
185 * @deprecated 3.0 Please use is_subclass_of.
a72f7b2 Sam Minnée ENHANCEMENT: Added ClassInfo::is_subclass_of() for better performance
sminnee authored
186 */
d187718 Andrew Short API CHANGE: Deprecated ClassInfo::is_subclass_of() in favour of is_subcl...
ajshort authored
187 public static function is_subclass_of($class, $parent) {
e5afa25 Sam Minnée MINOR: Use Deprecation class to indicate deprecated methods in core.
sminnee authored
188 Deprecation::notice('3.0', 'Use is_subclass_of() instead.');
d187718 Andrew Short API CHANGE: Deprecated ClassInfo::is_subclass_of() in favour of is_subcl...
ajshort authored
189 return is_subclass_of($class, $parent);
a72f7b2 Sam Minnée ENHANCEMENT: Added ClassInfo::is_subclass_of() for better performance
sminnee authored
190 }
d187718 Andrew Short API CHANGE: Deprecated ClassInfo::is_subclass_of() in favour of is_subcl...
ajshort authored
191
23aa23f Ingo Schommer ENHANCEMENT Added ClassInfo::classes_for_file()
chillu authored
192 /**
193 * Get all classes contained in a file.
194 * @uses ManifestBuilder
195 *
8ae9db1 Ingo Schommer ENHANCEMENT Added ClassInfo::classes_for_folder()
chillu authored
196 * @todo Doesn't return additional classes that only begin
197 * with the filename, and have additional naming separated through underscores.
198 *
23aa23f Ingo Schommer ENHANCEMENT Added ClassInfo::classes_for_file()
chillu authored
199 * @param string $filePath Path to a PHP file (absolute or relative to webroot)
200 * @return array
201 */
202 static function classes_for_file($filePath) {
bc0a1b7 Andrew Short MINOR: Updated various methods to use new manifest methods rather than M...
ajshort authored
203 $absFilePath = Director::getAbsFile($filePath);
23aa23f Ingo Schommer ENHANCEMENT Added ClassInfo::classes_for_file()
chillu authored
204 $matchedClasses = array();
bc0a1b7 Andrew Short MINOR: Updated various methods to use new manifest methods rather than M...
ajshort authored
205 $manifest = SS_ClassLoader::instance()->getManifest()->getClasses();
206
207 foreach($manifest as $class => $compareFilePath) {
23aa23f Ingo Schommer ENHANCEMENT Added ClassInfo::classes_for_file()
chillu authored
208 if($absFilePath == $compareFilePath) $matchedClasses[] = $class;
209 }
210
211 return $matchedClasses;
212 }
c1d6e82 Sam Minnée API CHANGE: Removed manifest's dependency on database, by removing hasta...
sminnee authored
213
8ae9db1 Ingo Schommer ENHANCEMENT Added ClassInfo::classes_for_folder()
chillu authored
214 /**
215 * Returns all classes contained in a certain folder.
216 *
217 * @todo Doesn't return additional classes that only begin
218 * with the filename, and have additional naming separated through underscores.
219 *
220 * @param string $folderPath Relative or absolute folder path
221 * @return array Array of class names
222 */
223 static function classes_for_folder($folderPath) {
bc0a1b7 Andrew Short MINOR: Updated various methods to use new manifest methods rather than M...
ajshort authored
224 $absFolderPath = Director::getAbsFile($folderPath);
8ae9db1 Ingo Schommer ENHANCEMENT Added ClassInfo::classes_for_folder()
chillu authored
225 $matchedClasses = array();
bc0a1b7 Andrew Short MINOR: Updated various methods to use new manifest methods rather than M...
ajshort authored
226 $manifest = SS_ClassLoader::instance()->getManifest()->getClasses();
227
228 foreach($manifest as $class => $compareFilePath) {
8ae9db1 Ingo Schommer ENHANCEMENT Added ClassInfo::classes_for_folder()
chillu authored
229 if(stripos($compareFilePath, $absFolderPath) === 0) $matchedClasses[] = $class;
230 }
231
232 return $matchedClasses;
233 }
234
4a5d9b0 Hayden Moved Sapphire module to open source path
Hayden authored
235 }
d370423 Clean up trailing ?> per coding standard
Fred Condo authored
236
Something went wrong with that request. Please try again.