2007-07-19 12:40:28 +02:00
|
|
|
<?php
|
|
|
|
/**
|
|
|
|
* Provides introspection information about the class tree.
|
|
|
|
* It's a cached wrapper around the built-in class functions. Sapphire uses class introspection heavily
|
|
|
|
* and without the caching it creates an unfortunate performance hit.
|
2008-02-25 03:10:37 +01:00
|
|
|
*
|
|
|
|
* @package sapphire
|
|
|
|
* @subpackage core
|
2007-07-19 12:40:28 +02:00
|
|
|
*/
|
|
|
|
class ClassInfo {
|
2008-11-06 05:51:25 +01:00
|
|
|
/**
|
2008-03-03 00:24:10 +01:00
|
|
|
* @todo Improve documentation
|
|
|
|
*/
|
2007-07-19 12:40:28 +02:00
|
|
|
static function allClasses() {
|
|
|
|
global $_ALL_CLASSES;
|
|
|
|
return $_ALL_CLASSES['exists'];
|
|
|
|
}
|
2008-03-03 00:24:10 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @todo Improve documentation
|
|
|
|
*/
|
2007-07-19 12:40:28 +02:00
|
|
|
static function exists($class) {
|
|
|
|
global $_ALL_CLASSES;
|
|
|
|
return isset($_ALL_CLASSES['exists'][$class]) ? $_ALL_CLASSES['exists'][$class] : null;
|
|
|
|
}
|
2008-03-03 00:24:10 +01:00
|
|
|
|
2009-03-04 04:44:11 +01:00
|
|
|
/**
|
|
|
|
* Cache for {@link hasTable()}
|
|
|
|
*/
|
|
|
|
private static $_cache_all_tables = null;
|
|
|
|
|
2008-03-03 00:24:10 +01:00
|
|
|
/**
|
2008-11-06 05:51:25 +01:00
|
|
|
* @todo Move this to Database or DB
|
2008-03-03 00:24:10 +01:00
|
|
|
*/
|
2007-07-19 12:40:28 +02:00
|
|
|
static function hasTable($class) {
|
2008-11-09 23:11:25 +01:00
|
|
|
if(DB::isActive()) {
|
2009-03-04 04:44:11 +01:00
|
|
|
// Cache the list of all table names to reduce on DB traffic
|
|
|
|
if(self::$_cache_all_tables === null) {
|
|
|
|
self::$_cache_all_tables = array();
|
|
|
|
$tables = DB::query("SHOW TABLES")->column();
|
|
|
|
foreach($tables as $table) self::$_cache_all_tables[strtolower($table)] = true;
|
|
|
|
}
|
|
|
|
return isset(self::$_cache_all_tables[strtolower($class)]);
|
2008-11-09 23:11:25 +01:00
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
2007-07-19 12:40:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the manifest of all classes which are present in the database.
|
|
|
|
*/
|
|
|
|
static function getValidSubClasses(){
|
2008-11-24 00:20:02 +01:00
|
|
|
return DB::getConn()->enumValuesForField("SiteTree", "ClassName");
|
2007-07-19 12:40:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return the database tables linked to this class.
|
|
|
|
* Gets an array of the current class, it subclasses and its ancestors. It then filters that list
|
|
|
|
* to those with DB tables
|
2008-04-14 06:49:08 +02:00
|
|
|
*
|
|
|
|
* @param mixed $class string of the classname or instance of the class
|
2008-11-06 05:51:25 +01:00
|
|
|
* @todo Move this into data object
|
2008-04-14 06:49:08 +02:00
|
|
|
* @return array
|
2007-07-19 12:40:28 +02:00
|
|
|
*/
|
|
|
|
static function dataClassesFor($class) {
|
|
|
|
global $_ALL_CLASSES;
|
2008-04-14 06:49:08 +02:00
|
|
|
if (is_object($class)) $class = get_class($class);
|
|
|
|
|
2008-07-16 05:29:20 +02:00
|
|
|
$dataClasses = array();
|
|
|
|
|
2007-07-19 12:40:28 +02:00
|
|
|
if(!$_ALL_CLASSES['parents'][$class]) user_error("ClassInfo::dataClassesFor() no parents for $class", E_USER_WARNING);
|
|
|
|
foreach($_ALL_CLASSES['parents'][$class] as $subclass) {
|
2008-11-06 05:51:25 +01:00
|
|
|
if(DataObject::has_own_table($subclass)) $dataClasses[] = $subclass;
|
2007-07-19 12:40:28 +02:00
|
|
|
}
|
|
|
|
|
2008-11-06 05:51:25 +01:00
|
|
|
if(DataObject::has_own_table($class)) $dataClasses[] = $class;
|
2007-07-19 12:40:28 +02:00
|
|
|
|
|
|
|
if(isset($_ALL_CLASSES['children'][$class]))
|
|
|
|
foreach($_ALL_CLASSES['children'][$class] as $subclass)
|
|
|
|
{
|
2008-11-06 05:51:25 +01:00
|
|
|
if(DataObject::has_own_table($subclass)) $dataClasses[] = $subclass;
|
2007-07-19 12:40:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return $dataClasses;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return the root data class for that class.
|
|
|
|
* This root table has a lot of special use in the DataObject system.
|
2008-04-14 06:49:08 +02:00
|
|
|
*
|
|
|
|
* @param mixed $class string of the classname or instance of the class
|
|
|
|
* @return array
|
2007-07-19 12:40:28 +02:00
|
|
|
*/
|
|
|
|
static function baseDataClass($class) {
|
|
|
|
global $_ALL_CLASSES;
|
2008-04-14 06:49:08 +02:00
|
|
|
if (is_object($class)) $class = get_class($class);
|
2007-07-19 12:40:28 +02:00
|
|
|
reset($_ALL_CLASSES['parents'][$class]);
|
|
|
|
while($val = next($_ALL_CLASSES['parents'][$class])) {
|
|
|
|
if($val == 'DataObject') break;
|
|
|
|
}
|
|
|
|
$baseDataClass = next($_ALL_CLASSES['parents'][$class]);
|
|
|
|
return $baseDataClass ? $baseDataClass : $class;
|
|
|
|
}
|
|
|
|
|
2008-03-03 00:24:10 +01:00
|
|
|
/**
|
2008-04-14 06:49:08 +02:00
|
|
|
* Returns a list of classes that inherit from the given class.
|
2009-02-02 00:49:53 +01:00
|
|
|
* The resulting array includes the base class passed
|
|
|
|
* through the $class parameter as the first array value.
|
|
|
|
*
|
|
|
|
* Example usage:
|
|
|
|
* <example>
|
|
|
|
* ClassInfo::subclassesFor('BaseClass');
|
|
|
|
* array(
|
|
|
|
* 0 => 'BaseClass',
|
|
|
|
* 'ChildClass' => 'ChildClass',
|
|
|
|
* 'GrandChildClass' => 'GrandChildClass'
|
|
|
|
* )
|
|
|
|
* </example>
|
2008-04-14 06:49:08 +02:00
|
|
|
*
|
|
|
|
* @param mixed $class string of the classname or instance of the class
|
2009-02-02 00:49:53 +01:00
|
|
|
* @return array Names of all subclasses as an associative array.
|
2008-03-03 00:24:10 +01:00
|
|
|
*/
|
2007-07-19 12:40:28 +02:00
|
|
|
static function subclassesFor($class){
|
|
|
|
global $_ALL_CLASSES;
|
2008-04-14 06:49:08 +02:00
|
|
|
if (is_object($class)) $class = get_class($class);
|
2009-02-02 00:49:53 +01:00
|
|
|
|
|
|
|
// get all classes from the manifest
|
2007-07-19 12:40:28 +02:00
|
|
|
$subclasses = isset($_ALL_CLASSES['children'][$class]) ? $_ALL_CLASSES['children'][$class] : null;
|
2009-02-02 00:49:53 +01:00
|
|
|
|
|
|
|
// add the base class to the array
|
|
|
|
if(isset($subclasses)) {
|
|
|
|
array_unshift($subclasses, $class);
|
|
|
|
} else {
|
|
|
|
$subclasses[$class] = $class;
|
|
|
|
}
|
|
|
|
|
2007-07-19 12:40:28 +02:00
|
|
|
return $subclasses;
|
|
|
|
}
|
|
|
|
|
2008-03-03 00:24:10 +01:00
|
|
|
/**
|
|
|
|
* @todo Improve documentation
|
|
|
|
*/
|
2007-07-19 12:40:28 +02:00
|
|
|
static function ancestry($class, $onlyWithTables = false) {
|
|
|
|
global $_ALL_CLASSES;
|
2008-08-12 04:51:33 +02:00
|
|
|
|
|
|
|
if(is_object($class)) $class = $class->class;
|
|
|
|
else if(!is_string($class)) user_error("Bad class value " . var_export($class, true) . " passed to ClassInfo::ancestry()", E_USER_WARNING);
|
|
|
|
|
2007-07-19 12:40:28 +02:00
|
|
|
$items = $_ALL_CLASSES['parents'][$class];
|
|
|
|
$items[$class] = $class;
|
|
|
|
if($onlyWithTables) foreach($items as $item) {
|
2008-11-06 05:51:25 +01:00
|
|
|
if(!DataObject::has_own_table($item)) unset($items[$item]);
|
2007-07-19 12:40:28 +02:00
|
|
|
}
|
|
|
|
return $items;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2008-02-25 03:10:37 +01:00
|
|
|
* @return array A self-keyed array of class names. Note that this is only available with Silverstripe
|
|
|
|
* classes and not built-in PHP classes.
|
2007-07-19 12:40:28 +02:00
|
|
|
*/
|
|
|
|
static function implementorsOf($interfaceName) {
|
2008-02-25 03:10:37 +01:00
|
|
|
global $_ALL_CLASSES;
|
|
|
|
return (isset($_ALL_CLASSES['implementors'][$interfaceName])) ? $_ALL_CLASSES['implementors'][$interfaceName] : false;
|
2007-07-19 12:40:28 +02:00
|
|
|
}
|
2008-08-09 04:16:46 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns true if the given class implements the given interface
|
|
|
|
*/
|
|
|
|
static function classImplements($className, $interfaceName) {
|
|
|
|
global $_ALL_CLASSES;
|
|
|
|
return isset($_ALL_CLASSES['implementors'][$interfaceName]) ? in_array($className, $_ALL_CLASSES['implementors'][$interfaceName]) : false;
|
|
|
|
}
|
2008-10-17 17:18:26 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Get all classes contained in a file.
|
|
|
|
* @uses ManifestBuilder
|
|
|
|
*
|
|
|
|
* @param string $filePath Path to a PHP file (absolute or relative to webroot)
|
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
static function classes_for_file($filePath) {
|
|
|
|
$absFilePath = Director::getAbsFile($filePath);
|
|
|
|
global $_CLASS_MANIFEST;
|
|
|
|
|
|
|
|
$matchedClasses = array();
|
|
|
|
foreach($_CLASS_MANIFEST as $class => $compareFilePath) {
|
|
|
|
if($absFilePath == $compareFilePath) $matchedClasses[] = $class;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $matchedClasses;
|
|
|
|
}
|
2008-11-06 05:51:25 +01:00
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// DEPRECATED
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @deprecated Use Security::database_is_ready() instead.
|
|
|
|
*/
|
|
|
|
static function ready() {
|
|
|
|
user_error("ClassInfo::ready() deprectaed - use Security::database_is_ready()", E_USER_NOTICE);
|
|
|
|
return Security::database_is_ready();
|
|
|
|
}
|
|
|
|
|
2007-07-19 12:40:28 +02:00
|
|
|
}
|
2009-03-04 04:44:11 +01:00
|
|
|
?>
|