ConLite/conlite/classes/class.autoload.php

289 Zeilen
9.2 KiB
PHP

<?php
/**
* Project:
* CONTENIDO Content Management System
*
* Description:
* Implements autoload feature for a CONTENIDO project.
*
* Autoloading for CONTENIDO is provided via a generated class map configuration
* file, which is available inside data/config/{environment}/ folder.
* - data/config/{environment}/config.autoloader.php
*
* Autoloading is extendable by adding a additional class map file inside the same
* folder, which could contain further class map settings or could overwrite
* settings of main class map file.
* - data/config/{environment}/contenido/includes/config.autoloader.local.php
*
* You can also add additional class map configuration by using function following
* functions:
* - cAutoload::addClassmapConfig(array $config)
* - cAutoload::addClassmapConfigFile($configFile)
*
* Read also docs/techref/backend/backend.autoloader.html to get involved in
* CONTENIDO autoloader mechanism.
*
*
* Requirements:
* @con_php_req 5.0
*
* @package CONTENIDO Autoloader
* @version 0.1.0
* @author Murat Purc <murat@purc.de>
* @copyright four for business AG <www.4fb.de>
* @license http://www.contenido.org/license/LIZENZ.txt
* @link http://www.4fb.de
* @link http://www.contenido.org
* @since file available since CONTENIDO release 4.9.0
*
* {@internal
* created 2010-12-27
* $Id$:
* }}
*/
if (!defined('CON_FRAMEWORK')) {
die('Illegal call');
}
class cAutoload {
const ERROR_FILE_NOT_FOUND = 'file_not_found';
const ERROR_CLASS_EXISTS = 'class_exists';
/**
* CONTENIDO root path. Path to the folder which contains the CONTENIDO installation.
*
* @var string
*/
private static $_conRootPath = null;
/**
* Array of interface/class names with related files to include
*
* @var array
*/
private static $_includeFiles = null;
/**
* Flag containing initialized status
*
* @var bool
*/
private static $_initialized = null;
/**
* Array to store loaded classnames and the paths to the class files.
* $_loadedClasses['classname'] = '/path/to/the/class.php';
*
* @var array
*/
private static $_loadedClasses = array();
/**
* Array to store invalid classnames and the paths to the class files.
* $_errors[pos] = array('class' => classname, 'file' => file, 'error' => errorType);
*
* @var array
*/
private static $_errors = array();
/**
* Initialization of CONTENIDO autoloader, is to call at least once.
*
* Registers itself as a __autoload implementation, includes the class map file,
* and if exists, the user defined class map file, containing the includes.
*
* @param array $cfg The CONTENIDO cfg array
* @return void
*/
public static function initialize(array $cfg) {
if (self::$_initialized == true) {
return;
}
self::$_initialized = true;
self::$_conRootPath = str_replace('\\', '/', realpath($cfg['path']['contenido'] . '/../')) . '/';
spl_autoload_register(array(__CLASS__, 'autoload'));
// load n' store autoloader class map file
$file = $cfg['path']['config'] . 'config.autoloader.php';
if ($arr = include_once($file)) {
self::$_includeFiles = $arr;
}
// load n' store additional autoloader class map file, if exists
$file = $cfg['path']['config'] . 'config.autoloader.local.php';
if (is_file($file)) {
self::addClassmapConfigFile($file);
}
}
/**
* Adding additional autoloader class map configuration.
* NOTE:
* Since this autoloader is implemented for CONTENIDO, it doesn't support to
* load classfiles being located outside of the CONTENIDO installation folder.
*
* @param array $config Assoziative class map array as follows:
* <pre>
* // Structure is: "Classname" => "Path to classfile from CONTENIDO installation folder"
* $config = array(
* 'myPluginsClass' => 'contenido/plugins/myplugin/classes/class.myPluginClass.php',
* 'myPluginsOtherClass' => 'contenido/plugins/myplugin/classes/class.myPluginsOtherClass.php',
* );
* </pre>
* @return void
*/
public static function addClassmapConfig(array $config) {
self::$_includeFiles = array_merge(self::$_includeFiles, $config);
}
/**
* Adding additional autoloader class map configuration file.
* NOTE:
* Since this autoloader is implemented for CONTENIDO, it doesn't support to
* load classfiles being located outside of the CONTENIDO installation folder.
*
* @param string $configFile Full path to class map configuration file.
* The provided file must return a class map configuration array as follows:
* <pre>
* // Structure is: "Classname" => "Path to classfile from CONTENIDO installation folder"
* return array(
* 'myPluginsClass' => 'contenido/plugins/myplugin/classes/class.myPluginClass.php',
* 'myPluginsOtherClass' => 'contenido/plugins/myplugin/classes/class.myPluginsOtherClass.php',
* 'myCmsClass' => 'cms/includes/class.myCmsClass.php',
* );
* </pre>
* @return void
*/
public static function addClassmapConfigFile($configFile) {
if (is_file($configFile)) {
if ($arr = include_once($configFile)) {
if(is_array($arr)) {
self::addClassmapConfig($arr);
}
}
}
}
/**
* The main __autoload() implementation.
* Tries to include the file of passed classname.
*
* @param string $className The classname
* @return void
* @throws Exception If autoloader wasn't initialized before
*/
public static function autoload($className) {
if (self::$_initialized !== true) {
throw new Exception("Autoloader has to be initialized by calling method initialize()");
}
if (isset(self::$_loadedClasses[$className])) {
return;
}
$file = '';
if ($file = self::_getContenidoClassFile($className)) {
// load class file from class map
self::_loadFile($file);
}
self::$_loadedClasses[$className] = str_replace(self::$_conRootPath, '', $file);
}
/**
* Checks, if passed filename is a file, which will be included by the autoloader.
*
* @param string $file Filename or Filename with a part of the path, e. g.
* - class.foobar.php
* - classes/class.foobar.php
* - contenido/classes/class.foobar.php
* @return bool
*/
public static function isAutoloadable($file) {
foreach (self::$_includeFiles as $className => $includeFile) {
if (strpos($includeFile, $file) !== false) {
return true;
}
}
return false;
}
/**
* Returns the loaded classes (@see cAutoload::$_loadedClasses)
*
* @return array
*/
public static function getLoadedClasses() {
return self::$_loadedClasses;
}
/**
* Returns the errorlist containing invalid classes (@see cAutoload::$_errors)
*
* @return array
*/
public static function getErrors() {
return self::$_errors;
}
/**
* Returns the path to a CONTENIDO class file by processing the given classname
*
* @param string $className
* @return (string|null) Path and filename or null
*/
private static function _getContenidoClassFile($className) {
$file = isset(self::$_includeFiles[$className]) ? self::$_conRootPath . self::$_includeFiles[$className] : null;
return self::_validateClassAndFile($className, $file);
}
/**
* Validates the given class and the file
*
* @param string $className
* @param string $filePathName
* @return (string|null) The file if validation was successfull, otherwhise null
*/
private static function _validateClassAndFile($className, $filePathName) {
if (class_exists($className)) {
self::$_errors[] = array(
'class' => $className,
'file' => str_replace(self::$_conRootPath, '', $filePathName),
'error' => self::ERROR_CLASS_EXISTS
);
return null;
} elseif (!is_file($filePathName)) {
self::$_errors[] = array(
'class' => $className,
'file' => str_replace(self::$_conRootPath, '', $filePathName),
'error' => self::ERROR_FILE_NOT_FOUND
);
return null;
}
return $filePathName;
}
/**
* Loads the desired file by invoking require_once method
*
* @param string $filePathName
* @param bool $beQuiet Flag to prevent thrown warnings/errors by using
* the error control operator @
* @return void
*/
private static function _loadFile($filePathName, $beQuiet = false) {
if ($beQuiet) {
@require_once($filePathName);
} else {
require_once($filePathName);
}
}
}