mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 12:05:37 +00:00
wakeless: #1823 - Improve memory usage of ManifestBuilder
git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@46730 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
parent
5dac73b21e
commit
0235aee5df
@ -10,7 +10,7 @@ class ClassInfo {
|
|||||||
*/
|
*/
|
||||||
static function ready() {
|
static function ready() {
|
||||||
global $_ALL_CLASSES;
|
global $_ALL_CLASSES;
|
||||||
return $_ALL_CLASSES && isset($_ALL_CLASSES['hastable']) && $_ALL_CLASSES['hastable'];
|
return $_ALL_CLASSES && $_ALL_CLASSES['hastable'];
|
||||||
}
|
}
|
||||||
static function allClasses() {
|
static function allClasses() {
|
||||||
global $_ALL_CLASSES;
|
global $_ALL_CLASSES;
|
||||||
@ -102,30 +102,12 @@ class ClassInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return all the class names implementing the given interface.
|
* @return array A self-keyed array of class names. Note that this is only available with Silverstripe
|
||||||
* Note: this method is slow; if that becomes a problem you may need to reimplement this to cache results in
|
* classes and not built-in PHP classes.
|
||||||
* the manifest.
|
|
||||||
* @return array A self-keyed array of class names
|
|
||||||
*/
|
*/
|
||||||
protected static $implementors_of = array();
|
|
||||||
static function implementorsOf($interfaceName) {
|
static function implementorsOf($interfaceName) {
|
||||||
if(array_key_exists($interfaceName, self::$implementors_of)) return self::$implementors_of[$interfaceName];
|
global $_ALL_CLASSES;
|
||||||
|
return $_ALL_CLASSES['implementors'][$interfaceName];
|
||||||
$matchingClasses = array();
|
|
||||||
|
|
||||||
$classes = self::allClasses();
|
|
||||||
foreach($classes as $potentialClass) {
|
|
||||||
if(class_exists($potentialClass)) {
|
|
||||||
$refl = new ReflectionClass($potentialClass);
|
|
||||||
if($refl->implementsInterface($interfaceName)) {
|
|
||||||
$matchingClasses[$potentialClass] = $potentialClass;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self::$implementors_of[$interfaceName] = $matchingClasses;
|
|
||||||
|
|
||||||
return $matchingClasses;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
?>
|
?>
|
@ -31,6 +31,9 @@ define("MANIFEST_FILE", TEMP_FOLDER . "/manifest" . str_replace(array("/",":", "
|
|||||||
class ManifestBuilder {
|
class ManifestBuilder {
|
||||||
|
|
||||||
static $restrict_to_modules = array();
|
static $restrict_to_modules = array();
|
||||||
|
static $extendsArray = array();
|
||||||
|
static $classArray = array();
|
||||||
|
static $implementsArray = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array $ignore_files Full filenames (without directory-path) which
|
* @var array $ignore_files Full filenames (without directory-path) which
|
||||||
@ -90,7 +93,7 @@ class ManifestBuilder {
|
|||||||
foreach($topLevel as $file) {
|
foreach($topLevel as $file) {
|
||||||
$fullPath = $baseDir . '/' . $file;
|
$fullPath = $baseDir . '/' . $file;
|
||||||
|
|
||||||
if(is_dir($fullPath . '/') && file_exists($fullPath . '/_exclude.php'))
|
if(@is_dir($fullPath . '/') && file_exists($fullPath . '/_exclude.php'))
|
||||||
require_once($fullPath . '/_exclude.php');
|
require_once($fullPath . '/_exclude.php');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,7 +111,7 @@ class ManifestBuilder {
|
|||||||
// have an _manifest_exclude file
|
// have an _manifest_exclude file
|
||||||
$topLevel = scandir($baseDir);
|
$topLevel = scandir($baseDir);
|
||||||
foreach($topLevel as $filename) {
|
foreach($topLevel as $filename) {
|
||||||
if(is_dir("$baseDir/$filename") &&
|
if(@is_dir("$baseDir/$filename") &&
|
||||||
file_exists("$baseDir/$filename/_config.php") &&
|
file_exists("$baseDir/$filename/_config.php") &&
|
||||||
!file_exists("$baseDir/$filename/_manifest_exclude")) {
|
!file_exists("$baseDir/$filename/_manifest_exclude")) {
|
||||||
ManifestBuilder::getClassManifest("$baseDir/$filename",
|
ManifestBuilder::getClassManifest("$baseDir/$filename",
|
||||||
@ -130,7 +133,7 @@ class ManifestBuilder {
|
|||||||
global $databaseConfig;
|
global $databaseConfig;
|
||||||
$topLevel = scandir($baseDir);
|
$topLevel = scandir($baseDir);
|
||||||
foreach($topLevel as $filename) {
|
foreach($topLevel as $filename) {
|
||||||
if(is_dir("$baseDir/$filename/") &&
|
if(@is_dir("$baseDir/$filename/") &&
|
||||||
file_exists("$baseDir/$filename/_config.php") &&
|
file_exists("$baseDir/$filename/_config.php") &&
|
||||||
!file_exists("$baseDir/$filename/_manifest_exclude")) {
|
!file_exists("$baseDir/$filename/_manifest_exclude")) {
|
||||||
$manifest .= "require_once(\"$baseDir/$filename/_config.php\");\n";
|
$manifest .= "require_once(\"$baseDir/$filename/_config.php\");\n";
|
||||||
@ -151,7 +154,7 @@ class ManifestBuilder {
|
|||||||
$topLevel = scandir($baseDir);
|
$topLevel = scandir($baseDir);
|
||||||
foreach($topLevel as $filename) {
|
foreach($topLevel as $filename) {
|
||||||
if(substr($filename,0,1) == '.') continue;
|
if(substr($filename,0,1) == '.') continue;
|
||||||
if($filename != 'themes' && is_dir("$baseDir/$filename") && file_exists("$baseDir/$filename/_config.php")) {
|
if($filename != 'themes' && @is_dir("$baseDir/$filename") && file_exists("$baseDir/$filename/_config.php")) {
|
||||||
ManifestBuilder::getTemplateManifest($baseDir, $filename, $templateManifest, $cssManifest);
|
ManifestBuilder::getTemplateManifest($baseDir, $filename, $templateManifest, $cssManifest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -212,21 +215,21 @@ class ManifestBuilder {
|
|||||||
if(substr($item,0,1) == '.') continue;
|
if(substr($item,0,1) == '.') continue;
|
||||||
|
|
||||||
// ignore files without php-extension
|
// ignore files without php-extension
|
||||||
if(substr($item,-4) != '.php' && !is_dir("$folder/$item")) continue;
|
if(substr($item,-4) != '.php' && !@is_dir("$folder/$item")) continue;
|
||||||
|
|
||||||
// ignore files and folders with underscore-prefix
|
// ignore files and folders with underscore-prefix
|
||||||
if(substr($item,0,1) == '_') continue;
|
if(substr($item,0,1) == '_') continue;
|
||||||
|
|
||||||
// ignore certain directories
|
// ignore certain directories
|
||||||
if(is_dir("$folder/$item") && in_array($item, self::$ignore_folders)) continue;
|
if(@is_dir("$folder/$item") && in_array($item, self::$ignore_folders)) continue;
|
||||||
|
|
||||||
// ignore directories with _manifest_exlude file
|
// ignore directories with _manifest_exlude file
|
||||||
if(is_dir("$folder/$item") && file_exists("$folder/$item/_manifest_exclude")) continue;
|
if(@is_dir("$folder/$item") && file_exists("$folder/$item/_manifest_exclude")) continue;
|
||||||
|
|
||||||
// i18n: ignore language files (loaded on demand)
|
// i18n: ignore language files (loaded on demand)
|
||||||
if($item == 'lang' && is_dir("$folder/$item") && ereg_replace("/[^/]+/\\.\\.","",$folder.'/..') == Director::baseFolder()) continue;
|
if($item == 'lang' && @is_dir("$folder/$item") && ereg_replace("/[^/]+/\\.\\.","",$folder.'/..') == Director::baseFolder()) continue;
|
||||||
|
|
||||||
if(is_dir("$folder/$item")) {
|
if(@is_dir("$folder/$item")) {
|
||||||
// recurse into directories (if not in $ignore_folders)
|
// recurse into directories (if not in $ignore_folders)
|
||||||
ManifestBuilder::getClassManifest("$folder/$item", $classMap);
|
ManifestBuilder::getClassManifest("$folder/$item", $classMap);
|
||||||
} else {
|
} else {
|
||||||
@ -284,7 +287,7 @@ class ManifestBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} else if(is_dir("$baseDir/$folder/$item")) {
|
} else if(@is_dir("$baseDir/$folder/$item")) {
|
||||||
ManifestBuilder::getTemplateManifest($baseDir, "$folder/$item", $templateManifest, $cssManifest, $themeName);
|
ManifestBuilder::getTemplateManifest($baseDir, "$folder/$item", $templateManifest, $cssManifest, $themeName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -305,51 +308,148 @@ class ManifestBuilder {
|
|||||||
foreach($classManifest as $file) {
|
foreach($classManifest as $file) {
|
||||||
$b = basename($file);
|
$b = basename($file);
|
||||||
if($b != 'cli-script.php' && $b != 'main.php')
|
if($b != 'cli-script.php' && $b != 'main.php')
|
||||||
include_once($file);
|
self::parse_file($file);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(DB::isActive()) {
|
|
||||||
$tables = DB::getConn()->tableList();
|
$tables = DB::getConn()->tableList();
|
||||||
} else {
|
|
||||||
$tables = array();
|
|
||||||
}
|
|
||||||
|
|
||||||
$allClasses['hastable'] = array();
|
$allClasses["parents"] = self::find_parents();
|
||||||
|
$allClasses["children"] = self::find_children();
|
||||||
|
$allClasses["implementors"] = self::$implementsArray;
|
||||||
|
|
||||||
|
foreach(self::$classArray as $class => $info) {
|
||||||
|
$allClasses['exists'][$class] = $class;
|
||||||
|
if(isset($tables[strtolower($class)])) $allClasses['hastable'][$class] = $class;
|
||||||
|
}
|
||||||
|
|
||||||
// Build a map of classes and their subclasses
|
// Build a map of classes and their subclasses
|
||||||
$_classes = get_declared_classes();
|
$_classes = get_declared_classes();
|
||||||
|
|
||||||
foreach($_classes as $class) {
|
foreach($_classes as $class) {
|
||||||
$allClasses['exists'][$class] = $class;
|
$allClasses['exists'][$class] = $class;
|
||||||
|
if(isset($tables[strtolower($class)])) $allClasses['hastable'][$class] = $class;
|
||||||
if(isset($tables[strtolower($class)]))
|
|
||||||
$allClasses['hastable'][$class] = $class;
|
|
||||||
|
|
||||||
foreach($_classes as $subclass) {
|
foreach($_classes as $subclass) {
|
||||||
if(is_subclass_of($class, $subclass))
|
if(is_subclass_of($class, $subclass)) $allClasses['parents'][$class][$subclass] = $subclass;
|
||||||
$allClasses['parents'][$class][$subclass] = $subclass;
|
if(is_subclass_of($subclass, $class)) $allClasses['children'][$class][$subclass] = $subclass;
|
||||||
|
|
||||||
if(is_subclass_of($subclass, $class))
|
|
||||||
$allClasses['children'][$class][$subclass] = $subclass;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $allClasses;
|
return $allClasses;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses a php file and adds any class or interface information into self::$classArray
|
||||||
|
*
|
||||||
|
* @param string $filename
|
||||||
|
*/
|
||||||
|
private static function parse_file($filename) {
|
||||||
|
$file = file_get_contents($filename);
|
||||||
|
|
||||||
|
$implements = "";
|
||||||
|
$extends = "";
|
||||||
|
$class="";
|
||||||
|
|
||||||
|
if(!$file) die("Couldn't open $filename<br />");
|
||||||
|
|
||||||
|
$classes = array();
|
||||||
|
$size = preg_match_all('/class (.*){/', $file, $classes);
|
||||||
|
|
||||||
|
for($i=0; $i < $size; $i++) {
|
||||||
|
//we have a class
|
||||||
|
$args = split("implements", $classes[1][$i]);
|
||||||
|
$implements = isset($args[1]) ? $args[1] : null;
|
||||||
|
|
||||||
|
$interfaces = explode(",", $implements);
|
||||||
|
$args = split("extends", $args[0]);
|
||||||
|
$extends = trim(isset($args[1]) ? $args[1] : null);
|
||||||
|
$class = trim($args[0]);
|
||||||
|
if($extends) self::$extendsArray[$extends][$class] = $class;
|
||||||
|
|
||||||
|
foreach($interfaces as $interface) {
|
||||||
|
self::$implementsArray[$interface][$class] = $class;
|
||||||
|
}
|
||||||
|
|
||||||
|
self::$classArray[$class] = array(
|
||||||
|
"interfaces" => $interfaces,
|
||||||
|
"extends" => $extends,
|
||||||
|
"file" => $filename
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$interfaces = array();
|
||||||
|
$size = preg_match_all('/interface (.*){/', $file, $interfaces);
|
||||||
|
|
||||||
|
for($i=0;$i<$size;$i++) {
|
||||||
|
$class = trim($interfaces[1][$i]);
|
||||||
|
self::$classArray[$class] = array(
|
||||||
|
"interfaces"=>array(),
|
||||||
|
"extends" => "",
|
||||||
|
"isinterface"=>true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Include all files of the class manifest so that that actually *all*
|
* Moves through self::$classArray and creates an array containing parent data
|
||||||
* classes are available
|
*
|
||||||
|
* @return array
|
||||||
*/
|
*/
|
||||||
static function includeEverything() {
|
private static function find_parents() {
|
||||||
global $_CLASS_MANIFEST;
|
$parentArray = array();
|
||||||
|
foreach(self::$classArray as $class => $info) {
|
||||||
|
$extendArray = array();
|
||||||
|
|
||||||
foreach($_CLASS_MANIFEST as $filename) {
|
$parent = $info["extends"];
|
||||||
if(preg_match('/.*cli-script\.php$/', $filename))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
require_once($filename);
|
while($parent) {
|
||||||
|
$extendArray[$parent] = $parent;
|
||||||
|
$parent = isset(self::$classArray[$parent]["extends"]) ? self::$classArray[$parent]["extends"] : null;
|
||||||
}
|
}
|
||||||
|
$parentArray[$class] = array_reverse($extendArray);
|
||||||
|
}
|
||||||
|
return $parentArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterates through self::$classArray and returns an array with any descendant data
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private static function find_children() {
|
||||||
|
$childrenArray = array();
|
||||||
|
foreach(self::$extendsArray as $class => $children) {
|
||||||
|
$allChildren = $children;
|
||||||
|
foreach($children as $childName) {
|
||||||
|
$allChildren = array_merge($allChildren, self::up_children($childName));
|
||||||
|
}
|
||||||
|
$childrenArray[$class] = $allChildren;
|
||||||
|
}
|
||||||
|
return $childrenArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function to find all children of give class
|
||||||
|
*
|
||||||
|
* @param string $class
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private static function get_children($class) {
|
||||||
|
return isset(self::$extendsArray[$class]) ? self::$extendsArray[$class] : array();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a flat array with all children of a given class
|
||||||
|
*
|
||||||
|
* @param string $class
|
||||||
|
* @param array $results
|
||||||
|
*/
|
||||||
|
function up_children($class) {
|
||||||
|
$children = self::get_Children($class);
|
||||||
|
$results = $children;
|
||||||
|
foreach($children as $className) {
|
||||||
|
$results = array_merge($results, self::up_children($className));
|
||||||
|
}
|
||||||
|
return $results;;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -384,7 +484,7 @@ class ManifestBuilder {
|
|||||||
$topLevel = scandir($baseDir);
|
$topLevel = scandir($baseDir);
|
||||||
|
|
||||||
foreach($topLevel as $filename) {
|
foreach($topLevel as $filename) {
|
||||||
if(is_dir("$baseDir/$filename/") && file_exists("$baseDir/$filename/_config.php")) {
|
if(@is_dir("$baseDir/$filename/") && file_exists("$baseDir/$filename/_config.php")) {
|
||||||
$manifest .= "require_once(\"$baseDir/$filename/_config.php\");\n";
|
$manifest .= "require_once(\"$baseDir/$filename/_config.php\");\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user