Browse Source

Improve autoloader to handle loading common files. After profiling module_manager make some changes to improve performance in modules loading. Improve loading index.php by inlining init_js.php instead of requesting it.

tags/v1.5.5
Adam Bukowski 9 years ago
parent
commit
c95717a511
4 changed files with 229 additions and 54 deletions
  1. +185
    -30
      include/autoloader.php
  2. +35
    -19
      include/module_manager.php
  3. +2
    -2
      index.php
  4. +7
    -3
      init_js.php

+ 185
- 30
include/autoloader.php View File

@@ -18,64 +18,219 @@
* EPESI_ADDRESS/include/autoloader.php
*/
//define('DEBUG_AUTOLOADS', 'count');
//define('DEBUG_AUTOLOADS', 'backtrace');
define('DEBUG_AUTOLOADS', 'place');

if (defined('DEBUG_AUTOLOADS') && DEBUG_AUTOLOADS
&& !defined("_VALID_ACCESS")) {
define('CID', false);
require_once '../include.php';

print("<pre>");
if (isset($_GET['clear'])) {
unset($_SESSION['debug_autoloads']);
print "Memory cleared";
print "Memory cleared\n";
print "<a href=\"autoloader.php\">Back</a>";
return;
}
print("<pre>");
print("click <a href=\"?clear=1\">here</a> to clear stored data\n\n");
ob_start();
if (isset($_SESSION['debug_autoloads'])) {
if (DEBUG_AUTOLOADS == 'count') {
var_dump($_SESSION['debug_autoloads']);
} elseif (DEBUG_AUTOLOADS == 'backtrace') {
foreach ($_SESSION['debug_autoloads'] as $class => $bt) {
} elseif (DEBUG_AUTOLOADS == 'place') {
foreach ($_SESSION['debug_autoloads'] as $class => $places) {
print($class . "\n");
foreach ($bt as $btx) {
var_dump($btx);
print("<hr>");
foreach ($places as $place) {
print "\t$place\n";
}
print("<hr><hr>");
print("<hr>");
}
}
}
$data = ob_get_clean();
if (!$data)
$data = "No data stored. Refresh EPESI.";
print($data);
print("</pre>");
return;
}

defined("_VALID_ACCESS") || die('Direct access forbidden');
defined("_VALID_ACCESS") || die("Direct access forbidden<br>Define DEBUG_AUTOLOADS and come back here.");

spl_autoload_register('epesi_classes_autoloader');
class ModulesAutoloader {

function epesi_classes_autoloader($class_name) {
if (defined('DEBUG_AUTOLOADS') && DEBUG_AUTOLOADS) {
if (!isset($_SESSION['debug_autoloads']))
$_SESSION['debug_autoloads'] = array();
if (DEBUG_AUTOLOADS == 'count') {
if (!isset($_SESSION['debug_autoloads'][$class_name])
|| !is_numeric($_SESSION['debug_autoloads'][$class_name]))
$_SESSION['debug_autoloads'][$class_name] = 0;
$_SESSION['debug_autoloads'][$class_name] += 1;
} elseif (DEBUG_AUTOLOADS == 'backtrace') {
if (!isset($_SESSION['debug_autoloads'][$class_name])
|| !is_array($_SESSION['debug_autoloads'][$class_name]))
$_SESSION['debug_autoloads'][$class_name] = array();
$_SESSION['debug_autoloads'][$class_name][] = debug_backtrace();
private static $instance = null;

public static function enable($with_hooks = true) {
if (self::$instance === null) {
self::$instance = new ModulesAutoloader();
if ($with_hooks)
self::$instance->hooks();
}
}

$file = 'modules' . DIRECTORY_SEPARATOR;
$file .= str_replace('_', DIRECTORY_SEPARATOR, $class_name);
$file .= '.php';
if (file_exists($file)) {
require_once $file;
public static function disable() {
if (self::$instance)
unset(self::$instance);
}

private function __construct() {
spl_autoload_register(array($this, 'autoload'));
}

public function __destruct() {
spl_autoload_unregister(array($this, 'autoload'));
}

private function hooks() {
$this->autoload_hook('Base_LangCommon');
$this->autoload_hook('Libs_QuickFormCommon');
$this->autoload_hook('Utils_GenericBrowserCommon');
$this->autoload_hook('Libs_ScriptAculoUsCommon');
$this->autoload_hook('Base_BoxCommon');
$this->autoload_hook('Base_HomePageCommon');
$this->autoload_hook('Develop_MiscUtilsCommon');
}

private function autoload_hook($class_name) {
if (!class_exists($class_name, false))
$this->autoload($class_name);
}

private function get_calling_place() {
$db = debug_backtrace();
$autoload_called = false;
foreach ($db as $entry) {
if (isset($entry['function']) &&
($entry['function'] == 'spl_autoload_call' || $entry['function'] == 'autoload'))
$autoload_called = true;
if ($autoload_called && isset($entry['file']) && $entry['file'] && isset($entry['line'])) {
return $entry['file'] . ':' . $entry['line'];
}
}
return 'not found';
}

private function autoload($class_name) {
if (defined('DEBUG_AUTOLOADS') && DEBUG_AUTOLOADS) {
if (!isset($_SESSION['debug_autoloads']))
$_SESSION['debug_autoloads'] = array();
if (DEBUG_AUTOLOADS == 'count') {
if (!isset($_SESSION['debug_autoloads'][$class_name])
|| !is_numeric($_SESSION['debug_autoloads'][$class_name]))
$_SESSION['debug_autoloads'][$class_name] = 0;
$_SESSION['debug_autoloads'][$class_name] += 1;
} elseif (DEBUG_AUTOLOADS == 'place') {
if (!isset($_SESSION['debug_autoloads'][$class_name])
|| !is_array($_SESSION['debug_autoloads'][$class_name]))
$_SESSION['debug_autoloads'][$class_name] = array();
$_SESSION['debug_autoloads'][$class_name][] = $this->get_calling_place();
}
}

if ($this->module_common($class_name))
return true;

if ($this->module_main($class_name))
return true;

if ($this->class_from_modules($class_name))
return true;

if (isset($this->autoload_hooks[$class_name])) {
require_once $this->autoload_hooks[$class_name];
return 'hooked';
}
return false;
}

private function class_from_modules($class_name) {
$file = 'modules' . DIRECTORY_SEPARATOR;
$file .= str_replace('_', DIRECTORY_SEPARATOR, $class_name);
$file .= '.php';
if (file_exists($file)) {
require_once $file;
return true;
}
return false;
}

private function module_common($class_name) {
if (substr($class_name, -6) != 'Common')
return false;

$module_name = substr($class_name, 0, -6);
if (isset(ModuleManager::$modules[$module_name])) {
ModuleManager::include_common($module_name, ModuleManager::$modules[$module_name]);
// here return true to prevent further file searching.
// it should exists such file in module but it doesn't
return true;
}
return false;
}

private function module_main($class_name) {
if (isset(ModuleManager::$modules[$class_name])) {
return ModuleManager::include_main($class_name, ModuleManager::$modules[$class_name]);
}
return false;
}

/*
* Below are class names with files where they are defined.
* This is used to locate file and load it if it is in strange place.
*/
private $autoload_hooks =
array(
'Acl' => 'modules/Base/Acl/AclCommon_0.php',
'Base_AdminModuleCommon' => 'modules/Base/Admin/AdminCommon_0.php',
'CommentZipArchive' => 'modules/Custom/ESS/ModulesManagement/CommentZipArchive.php',
'HTML_Common' => 'modules/Libs/QuickForm/3.2.11/HTML/Common.php',
'HTML_QuickForm' => 'modules/Libs/QuickForm/3.2.11/HTML/QuickForm.php',
'HTML_QuickForm_Error' => 'modules/Libs/QuickForm/3.2.11/HTML/QuickForm.php',
'HTML_QuickForm_Renderer' => 'modules/Libs/QuickForm/3.2.11/HTML/QuickForm/Renderer.php',
'HTML_QuickForm_Renderer_TCMSArray' => 'modules/Libs/QuickForm/Renderer/TCMSArray.php',
'HTML_QuickForm_Renderer_TCMSArraySmarty' => 'modules/Libs/QuickForm/Renderer/TCMSArraySmarty.php',
'HTML_QuickForm_Renderer_TCMSDefault' => 'modules/Libs/QuickForm/Renderer/TCMSDefault.php',
'HTML_QuickForm_autocomplete' => 'modules/Libs/QuickForm/FieldTypes/autocomplete/autocomplete.php',
'HTML_QuickForm_automulti' => 'modules/Libs/QuickForm/FieldTypes/automulti/automulti.php',
'HTML_QuickForm_autoselect' => 'modules/Libs/QuickForm/FieldTypes/autoselect/autoselect.php',
'HTML_QuickForm_element' => 'modules/Libs/QuickForm/3.2.11/HTML/QuickForm/element.php',
'HTML_QuickForm_input' => 'modules/Libs/QuickForm/3.2.11/HTML/QuickForm/input.php',
'HTML_QuickForm_select' => 'modules/Libs/QuickForm/3.2.11/HTML/QuickForm/select.php',
'HTML_QuickForm_text' => 'modules/Libs/QuickForm/3.2.11/HTML/QuickForm/text.php',
'PEAR' => 'PEAR.php',
'PEAR5' => 'PEAR.php',
'PEAR_Error' => 'PEAR.php',
'PHPMailer' => 'modules/Base/Mail/class.phpmailer.php',
'PackageCreator' => 'modules/Custom/ESS/ModulesManagement/PackageCreator.php',
'RBO_FieldDefinition' => 'modules/Utils/RecordBrowser/object_wrapper/FieldDefinition.php',
'RBO_Field_Calculated' => 'modules/Utils/RecordBrowser/object_wrapper/fields.php',
'RBO_Field_Checkbox' => 'modules/Utils/RecordBrowser/object_wrapper/fields.php',
'RBO_Field_CommonData' => 'modules/Utils/RecordBrowser/object_wrapper/fields.php',
'RBO_Field_Currency' => 'modules/Utils/RecordBrowser/object_wrapper/fields.php',
'RBO_Field_Date' => 'modules/Utils/RecordBrowser/object_wrapper/fields.php',
'RBO_Field_Float' => 'modules/Utils/RecordBrowser/object_wrapper/fields.php',
'RBO_Field_Integer' => 'modules/Utils/RecordBrowser/object_wrapper/fields.php',
'RBO_Field_LongText' => 'modules/Utils/RecordBrowser/object_wrapper/fields.php',
'RBO_Field_MultiSelect' => 'modules/Utils/RecordBrowser/object_wrapper/fields.php',
'RBO_Field_PageSplit' => 'modules/Utils/RecordBrowser/object_wrapper/fields.php',
'RBO_Field_Select' => 'modules/Utils/RecordBrowser/object_wrapper/fields.php',
'RBO_Field_Text' => 'modules/Utils/RecordBrowser/object_wrapper/fields.php',
'RBO_Field_Timestamp' => 'modules/Utils/RecordBrowser/object_wrapper/fields.php',
'RBO_Record' => 'modules/Utils/RecordBrowser/object_wrapper/Record.php',
'RBO_Recordset' => 'modules/Utils/RecordBrowser/object_wrapper/Recordset.php',
'RBO_RecordsetAccessor' => 'modules/Utils/RecordBrowser/object_wrapper/RecordsetAccessor.php',
'RandomGenerator' => 'modules/Custom/ESS/ModulesManagement/RandomGenerator.php',
'RepoManager' => 'modules/Custom/ESS/ModulesManagement/RepoManager.php',
'Repository' => 'modules/Custom/ESS/ModulesManagement/Repository.php',
'Smarty' => 'modules/Base/Theme/smarty/Smarty.class.php',
'SvnRepository' => 'modules/Custom/ESS/ModulesManagement/SvnRepository.php',
'Utils_GenericBrowser_Row_Object' => 'modules/Utils/GenericBrowser/GenericBrowser_0.php',
'Utils_RecordBrowserMobile' => 'modules/Utils/RecordBrowser/RecordBrowserCommon_0.php',
'phpmailerException' => 'modules/Base/Mail/class.phpmailer.php',
);

}

?>

+ 35
- 19
include/module_manager.php View File

@@ -40,7 +40,7 @@ class ModuleManager {
$ret = require_once($full_path);
ob_end_clean();
$x = $module_class_name.'Install';
if(!(class_exists($x, false) && in_array($x, get_declared_classes())) || !array_key_exists('ModuleInstall',class_parents($x)))
if(!(class_exists($x, false)) || !is_a($x, 'ModuleInstall', true))
trigger_error('Module '.$path.': Invalid install file',E_USER_ERROR);
self::$modules_install[$module_class_name] = new $x($module_class_name);
return true;
@@ -54,20 +54,26 @@ class ModuleManager {
* @param string module name
*/
public static final function include_common($class_name,$version) {
$path = self::get_module_dir_path($class_name);
$file = self::get_module_file_name($class_name);
// here was function calls:
// self::get_module_dir_path($class_name);
// self::get_module_file_name($class_name);
// but function calls slows down too much
$path = str_replace('_', '/',$class_name);
$pos = strrpos($class_name, '_');
$file = ($pos !== false) ? substr($class_name, $pos+1):$class_name;
$file_url = 'modules/' . $path . '/' . $file . 'Common_'.$version.'.php';
//
if(file_exists($file_url)) {
ob_start();
require_once ($file_url);
ob_end_clean();
$x = $class_name.'Common';
if(class_exists($x, false)) {
if(!array_key_exists('ModuleCommon',class_parents($x)))
if(!is_a($x, 'ModuleCommon', true))
trigger_error('Module '.$path.': Common class should extend ModuleCommon class.',E_USER_ERROR);
call_user_func(array($class_name.'Common','Instance'),$class_name);
call_user_func(array($x, 'Instance'), $class_name);
return true;
}
return true;
}
return false;
}
@@ -81,16 +87,24 @@ class ModuleManager {
*/
public static final function include_main($class_name, $version) {
if(class_exists($class_name, false)) return;
$path = self::get_module_dir_path($class_name);
$file = self::get_module_file_name($class_name);
// here was function calls:
// self::get_module_dir_path($class_name);
// self::get_module_file_name($class_name);
// but function calls slows down too much
$path = str_replace('_', '/',$class_name);
$pos = strrpos($class_name, '_');
$file = ($pos !== false) ? substr($class_name, $pos+1):$class_name;
$file_url = 'modules/' . $path . '/' . $file . '_'.$version.'.php';
if( file_exists($file_url) ) {
//
if (file_exists($file_url) ) {
ob_start();
require_once ($file_url);
ob_end_clean();
if(!class_exists($class_name, false) || !array_key_exists('Module',class_parents($class_name)))
trigger_error('Module '.$path.': Invalid main file',E_USER_ERROR);
return true;
if(class_exists($class_name, false)) {
if (!is_a($class_name, 'Module', true))
trigger_error('Module '.$path.': Invalid main file',E_USER_ERROR);
return true;
}
}
return false;
}
@@ -239,8 +253,8 @@ class ModuleManager {
*/
public static final function get_module_file_name($module) {
$module_class_name = self::get_module_class_name($module);
$ret = strrchr($module_class_name,'_');
return ($ret)? substr($ret,1):$module_class_name;
$pos = strrpos($module_class_name, '_');
return ($pos !== false)? substr($module_class_name, $pos+1):$module_class_name;
}
/**
@@ -790,9 +804,9 @@ class ModuleManager {
$installed_modules = ModuleManager::get_load_priority_array(true);
self::$not_loaded_modules = $installed_modules;
self::$loaded_modules = array();
$cache_file = DATA_DIR.'/cache/common.php';
$cached = false;
if(CACHE_COMMON_FILES) {
$cache_file = DATA_DIR.'/cache/common.php';
if(!file_exists($cache_file))
self::create_common_cache();
ob_start();
@@ -807,6 +821,8 @@ class ModuleManager {
ModuleManager :: include_common($module, $version);
ModuleManager :: register($module, $version, self::$modules);
}
ModulesAutoloader::enable();
}
public static final function create_common_cache() {
@@ -822,7 +838,7 @@ class ModuleManager {
$ret .= file_get_contents ($file_url);
$ret .= '<?php $x = \''.$module.'Common\';'.
'if(class_exists($x, false)){ '.
'if(!array_key_exists(\'ModuleCommon\',class_parents($x)))'.
'if(!is_a($x, \'ModuleCommon\', true))'.
'trigger_error(\'Module '.$path.': Common class should extend ModuleCommon class.\',E_USER_ERROR);'.
'call_user_func(array($x,\'Instance\'),\''.$module.'\');'.
'} ?>';
@@ -870,7 +886,7 @@ class ModuleManager {
*/
public static final function check_access($mod, $m) {
$comm = $mod.'Common';
if(class_exists($comm, false)) {
if(class_exists($comm)) {
$sing = call_user_func(array($comm,'Instance'));
if (method_exists($sing, $m . '_access') &&
!call_user_func(array($sing, $m . '_access')))
@@ -886,7 +902,7 @@ class ModuleManager {
$ret = array();
ob_start();
foreach(self::$modules as $name=>$version)
if(class_exists($name.'Common', false) && method_exists($name.'Common', $method)) {
if(class_exists($name.'Common') && method_exists($name.'Common', $method)) {
$ret[$name] = call_user_func_array(array($name.'Common',$method),$args);
}
ob_end_clean();
@@ -901,7 +917,7 @@ class ModuleManager {
if(!isset($cache[$cache_id]) || !$cached) {
$ret = array();
foreach(self::$modules as $name=>$version)
if(class_exists($name.'Common', false) && method_exists($name.'Common', $method)) {
if(class_exists($name.'Common') && method_exists($name.'Common', $method)) {
$ret[] = $name;
}
$cache[$cache_id]=&$ret;


+ 2
- 2
index.php View File

@@ -219,9 +219,9 @@ Please choose EPESI version:<ul>
</table>
</div>
</div>
<script type="text/javascript" src="init_js.php?<?php print(http_build_query($_GET));?>"></script>
<script type="text/javascript"><?php require_once 'init_js.php'; ?></script>
<?php if(IPHONE) { ?>
<script type="text/javascript">iphone=true</script>
<script type="text/javascript">var iphone=true;</script>
<?php } ?>
</body>
</html>


+ 7
- 3
init_js.php View File

@@ -1,5 +1,6 @@
<?php
define('_VALID_ACCESS',1);
if (!defined('_VALID_ACCESS'))
define('_VALID_ACCESS',1);
require_once('include/data_dir.php');
if(!file_exists(DATA_DIR.'/config.php'))
die();
@@ -18,7 +19,10 @@ if(defined('CID')) {

require_once('include/session.php');

header("Content-type: text/javascript");
// if it's direct request to this file return content-type: text/javascript
// otherwise it's include and do not send header.
if (isset($_SERVER['SCRIPT_FILENAME']) && $_SERVER['SCRIPT_FILENAME'] == __FILE__)
header("Content-type: text/javascript");

$client_id = isset($_SESSION['num_of_clients'])?$_SESSION['num_of_clients']:0;
$client_id_next = $client_id+1;
@@ -27,4 +31,4 @@ $_SESSION['num_of_clients'] = $client_id_next;
session_commit();
DBSession::destroy_client(session_id(),$client_id);

?>Epesi.init(<?php print($client_id); ?>,'<?php print(rtrim(str_replace('\\','/',dirname($_SERVER['PHP_SELF'])),'/').'/process.php'); ?>','<?php print(http_build_query($_GET));?>');
?>Epesi.init(<?php print($client_id); ?>,'<?php print(rtrim(str_replace('\\','/',dirname($_SERVER['PHP_SELF'])),'/').'/process.php'); ?>','<?php print(http_build_query($_GET));?>');

Loading…
Cancel
Save