xautoload.module in X Autoload 7.2
Same filename and directory in other branches
File
xautoload.moduleView source
<?php
/*
* When the module has just been installed,
* Drupal does not know yet this is a boot-level module.
*
* We can not rely on hook_boot() to fire, and instead register the autoloader
* on inclusion of this *.module file.
*/
_xautoload_register();
// Hook implementations
// -----------------------------------------------------------------------------
/**
* Implements hook_boot()
*
* This is only to let Drupal know we want this module to load in bootstrap.
*/
function xautoload_boot() {
$finder = xautoload_get_finder();
$api = new xautoload_InjectedAPI_hookXautoload($finder);
_simpletest_xautoload($api);
}
/**
* Implements hook_xautoload() on behalf of simpletest
*/
function _simpletest_xautoload($api) {
if (version_compare(PHP_VERSION, '5.3') < 0) {
// Namespaces only exist since PHP 5.3.
return;
}
// Register a plugin that can find classes within disabled modules.
// The plugin will only load classes of the format "Drupal\(module)\Tests\.."
$api
->namespacePlugin('Drupal', new xautoload_Plugin_DrupalSimpletest());
}
/**
* Implements hook_custom_theme()
* We only do this because that's the first hook to fire after bootstrap.
*/
function xautoload_custom_theme() {
// Make sure this only runs once.
// (we run this from hook_init also, to avoid upgrade issues)
static $first_run = TRUE;
if (!$first_run) {
return;
}
$first_run = FALSE;
// Tell the "extension system" that the "main phase" has started, and thus
// all Drupal modules are now available.
xautoload('drupalExtensionSystem')
->mainPhase();
// Let other modules register stuff to the finder.
$api = new xautoload_InjectedAPI_hookXautoload(xautoload_get_finder());
foreach (module_implements('xautoload') as $module) {
$api
->setModule($module);
$f = $module . '_xautoload';
$f($api);
}
}
/**
* Implements hook_init()
*
* Note:
* This is a first step to allow modules to register foreign namespaces.
* We will probably change this, to allow bootstrap modules to register their
* namespaces earlier in the request.
* We might also find a solution to cache the result of this hook between
* requests. This would require a different implementation of the InjectedAPI,
* which would no longer have a direct reference to the finder object.
*/
function xautoload_init() {
// If hook_custom_theme() hasn't been triggered, we call it now.
xautoload_custom_theme();
}
/**
* Implements hook_modules_enabled()
*/
function xautoload_modules_enabled($modules) {
xautoload('drupalExtensionSystem')
->addModules($modules);
}
/**
* Implements hook_modules_installed()
*/
function xautoload_modules_installed($modules) {
xautoload('drupalExtensionSystem')
->addModules($modules);
}
/**
* Implements hook_simpletest_alter().
*/
function xautoload_simpletest_alter(&$groups) {
if (version_compare(PHP_VERSION, '5.3') < 0) {
// Namespaces only exist since PHP 5.3.
return;
}
// Select all PSR-0 classes in the Tests namespace of all modules.
// This does include disabled modules.
$system_list = db_query("SELECT name, filename FROM {system}")
->fetchAllKeyed();
foreach ($system_list as $name => $filename) {
// Build directory in which the test files would reside.
$tests_dir = DRUPAL_ROOT . '/' . dirname($filename) . '/lib/Drupal/' . $name . '/Tests';
// Scan it for test files if it exists.
if (is_dir($tests_dir)) {
$files = file_scan_directory($tests_dir, '/.*\\.php/');
if (!empty($files)) {
$basedir = DRUPAL_ROOT . '/' . dirname($filename) . '/lib/';
foreach ($files as $file) {
// Convert the file name into the namespaced class name.
$replacements = array(
'/' => '\\',
$basedir => '',
'.php' => '',
);
$classes[] = strtr($file->uri, $replacements);
}
}
}
}
// Check that each class has a getInfo() method and store the information
// in an array keyed with the group specified in the test information.
foreach ($classes as $class) {
// Test classes need to implement getInfo() to be valid.
if (class_exists($class) && method_exists($class, 'getInfo')) {
$info = call_user_func(array(
$class,
'getInfo',
));
// If this test class requires a non-existing module, skip it.
if (!empty($info['dependencies'])) {
foreach ($info['dependencies'] as $module) {
if (!drupal_get_filename('module', $module)) {
continue 2;
}
}
}
$groups[$info['group']][$class] = $info;
}
}
// Sort the groups and tests within the groups by name.
uksort($groups, 'strnatcasecmp');
foreach ($groups as $group => &$tests) {
uksort($tests, 'strnatcasecmp');
}
}
/**
* Implements hook_registry_files_alter()
*
* Support wildcard syntax in the files[] setting in your module's info file.
*/
function xautoload_registry_files_alter(&$files, $modules) {
$orig = $files;
// The class file is loaded using the regular uncached xautoload autoload.
$rec_scan = new xautoload_RegistryWildcard_RecursiveScan($files);
foreach ($files as $path => $file) {
$rec_scan
->check($path, $file);
}
}
/**
* Implements hook_module_implements_alter()
*/
function xautoload_module_implements_alter(&$implementations, $hook) {
if ($hook === 'init' || $hook === 'custom_theme') {
// Move xautoload_$hook() to the start.
$implementations = array(
'xautoload' => FALSE,
) + $implementations;
}
}
// Hooks on behalf of other modules
// -----------------------------------------------------------------------------
/**
* Implements hook_xautoload on behalf of libraries module
*/
function libraries_xautoload($api) {
if (!function_exists('libraries_info')) {
// Libraries is at a lower version, which does not have this function.
return;
}
foreach (libraries_info() as $name => $info) {
if (isset($info['xautoload'])) {
$xinfo = $info['xautoload'];
$api
->setLibrary($name);
if (is_callable($xinfo)) {
call_user_func($xinfo, $api);
}
}
}
}
// Public API functions.
// -----------------------------------------------------------------------------
/**
* Get the class finder object.
* This is the public version of _xautoload_finder().
*/
function xautoload_get_finder() {
// Get it from the registry.
return xautoload('classFinder');
}
/**
* Get a service object from the registry.
* Services are lazy-created first time you need them.
*
* @param string $key
* Identifier of the service within the registry.
* The xautoload_ServiceFactory should have a method with the same name.
*/
function xautoload($key) {
static $service_registry;
if (!isset($service_registry)) {
$service_factory = new xautoload_ServiceFactory();
$service_registry = new xautoload_ServiceRegistry($service_factory);
}
return $service_registry
->get($key);
}
// "Private" functions.
// -----------------------------------------------------------------------------
/**
* Build and register the xautoload loader.
*/
function _xautoload_register() {
// Check that this runs only once.
static $_first_run = TRUE;
if (!$_first_run) {
return;
}
$_first_run = FALSE;
// Register a temporary solution.
spl_autoload_register('_xautoload_autoload_temp');
// This one class needs to be loaded manually.
// Just believe me on that one.
_xautoload_autoload_temp('xautoload_InjectedAPI_findFile');
// Register the "real" class loader.
xautoload('classLoader')
->register(TRUE);
// The "extension system" needs some babysitting.
// Let's start by filling it with the boot-level modules.
xautoload('drupalExtensionSystem')
->bootstrapPhase();
// Unregister our temporary solution.
spl_autoload_unregister('_xautoload_autoload_temp');
// if xautoload has just been enabled, it won't be listed as a boot-level
// module. To be sure, we register its namespace explicitly.
if (!module_exists('xautoload') && function_exists('drupal_get_path')) {
$lib_dir = drupal_get_path('module', 'xautoload') . '/lib';
xautoload('classFinder')
->registerPrefixDeep('xautoload', $lib_dir);
}
// Let's crash right here if it doesn't work.
new xautoload_InjectedAPI_hookXautoload(xautoload('classFinder'));
}
/**
* Temporary loader callback, to avoid any module_load_include()
* while building the real autoloader.
*
* @param string $name
* Name of the class or interface we want to load.
*/
function _xautoload_autoload_temp($name) {
if (preg_match('#^xautoload_(.*)$#', $name, $m)) {
// This is boot time, drupal_get_path() is not available yet.
$file = dirname(__FILE__) . '/lib/' . strtr($m[1], '_', '/') . '.php';
require_once $file;
if (!class_exists($name, FALSE) && !interface_exists($name, FALSE)) {
throw new Exception("Class {$name} not found in {$file}.");
}
}
}
Functions
Name | Description |
---|---|
libraries_xautoload | Implements hook_xautoload on behalf of libraries module |
xautoload | Get a service object from the registry. Services are lazy-created first time you need them. |
xautoload_boot | Implements hook_boot() |
xautoload_custom_theme | Implements hook_custom_theme() We only do this because that's the first hook to fire after bootstrap. |
xautoload_get_finder | Get the class finder object. This is the public version of _xautoload_finder(). |
xautoload_init | Implements hook_init() |
xautoload_modules_enabled | Implements hook_modules_enabled() |
xautoload_modules_installed | Implements hook_modules_installed() |
xautoload_module_implements_alter | Implements hook_module_implements_alter() |
xautoload_registry_files_alter | Implements hook_registry_files_alter() |
xautoload_simpletest_alter | Implements hook_simpletest_alter(). |
_simpletest_xautoload | Implements hook_xautoload() on behalf of simpletest |
_xautoload_autoload_temp | Temporary loader callback, to avoid any module_load_include() while building the real autoloader. |
_xautoload_register | Build and register the xautoload loader. |