diff --git a/core/authorize.php b/core/authorize.php index 8a76fe4..3507f7f 100644 --- a/core/authorize.php +++ b/core/authorize.php @@ -23,7 +23,7 @@ // Change the directory to the Drupal root. chdir('..'); -require_once __DIR__ . '/vendor/autoload.php'; +require_once __DIR__ . '/autoload.php'; /** * Global flag to identify update.php and authorize.php runs. diff --git a/core/autoload.php b/core/autoload.php new file mode 100644 index 0000000..79b7fd3 --- /dev/null +++ b/core/autoload.php @@ -0,0 +1,15 @@ +add('Drupal\\' . $name, DRUPAL_ROOT . '/' . $path . '/lib'); + $loader->addPsr4('Drupal\\' . $name . '\\', array( + DRUPAL_ROOT . '/' . $path . '/lib/Drupal/' . $name, + DRUPAL_ROOT . '/' . $path . '/lib', + )); } /** diff --git a/core/install.php b/core/install.php index 7152fd8..e2900a2 100644 --- a/core/install.php +++ b/core/install.php @@ -8,7 +8,7 @@ // Change the directory to the Drupal root. chdir('..'); -require_once __DIR__ . '/vendor/autoload.php'; +require_once __DIR__ . '/autoload.php'; /** * Global flag to indicate the site is in installation mode. diff --git a/core/lib/Drupal/Component/Plugin/Discovery/AnnotatedClassDiscovery.php b/core/lib/Drupal/Component/Plugin/Discovery/AnnotatedClassDiscovery.php index 6110bd1..5264f5e 100644 --- a/core/lib/Drupal/Component/Plugin/Discovery/AnnotatedClassDiscovery.php +++ b/core/lib/Drupal/Component/Plugin/Discovery/AnnotatedClassDiscovery.php @@ -52,7 +52,7 @@ function __construct($plugin_namespaces = array(), $plugin_definition_annotation } /** - * Implements Drupal\Component\Plugin\Discovery\DiscoveryInterface::getDefinition(). + * {@inheritdoc} */ public function getDefinition($plugin_id) { $plugins = $this->getDefinitions(); @@ -60,7 +60,7 @@ public function getDefinition($plugin_id) { } /** - * Implements Drupal\Component\Plugin\Discovery\DiscoveryInterface::getDefinitions(). + * {@inheritdoc} */ public function getDefinitions() { $definitions = array(); @@ -77,7 +77,6 @@ public function getDefinitions() { // Search for classes within all PSR-0 namespace locations. foreach ($this->getPluginNamespaces() as $namespace => $dirs) { foreach ($dirs as $dir) { - $dir .= DIRECTORY_SEPARATOR . str_replace('\\', DIRECTORY_SEPARATOR, $namespace); if (file_exists($dir)) { foreach (new DirectoryIterator($dir) as $fileinfo) { // @todo Once core requires 5.3.6, use $fileinfo->getExtension(). diff --git a/core/lib/Drupal/Core/Autoload/ClassLoader.php b/core/lib/Drupal/Core/Autoload/ClassLoader.php new file mode 100644 index 0000000..ef78b58 --- /dev/null +++ b/core/lib/Drupal/Core/Autoload/ClassLoader.php @@ -0,0 +1,377 @@ +add('Symfony\Component', __DIR__.'/component'); + * $loader->add('Symfony', __DIR__.'/framework'); + * + * // activate the autoloader + * $loader->register(); + * + * // to enable searching the include path (eg. for PEAR packages) + * $loader->setUseIncludePath(true); + * + * In this example, if you try to use a class in the Symfony\Component + * namespace or one of its children (Symfony\Component\Console for instance), + * the autoloader will first look for the class under the component/ + * directory, and it will then fallback to the framework/ directory if not + * found before giving up. + * + * This class is loosely based on the Symfony UniversalClassLoader. + * + * @author Fabien Potencier + * @author Jordi Boggiano + */ +class ClassLoader { + + // PSR-4 + private $prefixLengthsPsr4 = array(); + private $prefixDirsPsr4 = array(); + private $fallbackDirsPsr4 = array(); + + // PSR-0 + private $prefixesPsr0 = array(); + private $fallbackDirsPsr0 = array(); + + private $useIncludePath = false; + private $classMap = array(); + + const PREDICTOR_INDEX = 9; + + public function getPrefixes() { + return call_user_func_array('array_merge', $this->prefixesPsr0); + } + + public function getPrefixesPsr4() { + return $this->prefixDirsPsr4; + } + + public function getFallbackDirs() { + return $this->fallbackDirsPsr0; + } + + public function getFallbackDirsPsr4() { + return $this->fallbackDirsPsr4; + } + + public function getClassMap() { + return $this->classMap; + } + + /** + * @param array $classMap Class to filename map + */ + public function addClassMap(array $classMap) { + if ($this->classMap) { + $this->classMap = array_merge($this->classMap, $classMap); + } + else { + $this->classMap = $classMap; + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, either + * appending or prepending to the ones previously set for this prefix. + * + * @param string $prefix The prefix + * @param array|string $paths The PSR-0 root directories + * @param bool $prepend Whether to prepend the directories + */ + public function add($prefix, $paths, $prepend = false) { + if (!$prefix) { + if ($prepend) { + $this->fallbackDirsPsr0 = array_merge( + (array) $paths, + $this->fallbackDirsPsr0 + ); + } + else { + $this->fallbackDirsPsr0 = array_merge( + $this->fallbackDirsPsr0, + (array) $paths + ); + } + + return; + } + + $first = $prefix[0]; + if (!isset($this->prefixesPsr0[$first][$prefix])) { + $this->prefixesPsr0[$first][$prefix] = (array) $paths; + + return; + } + if ($prepend) { + $this->prefixesPsr0[$first][$prefix] = array_merge( + (array) $paths, + $this->prefixesPsr0[$first][$prefix] + ); + } + else { + $this->prefixesPsr0[$first][$prefix] = array_merge( + $this->prefixesPsr0[$first][$prefix], + (array) $paths + ); + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, either + * appending or prepending to the ones previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param array|string $paths The PSR-0 base directories + * @param bool $prepend Whether to prepend the directories + * @throws \Exception + */ + public function addPsr4($prefix, $paths, $prepend = false) { + if (!$prefix) { + // Register directories for the root namespace. + if ($prepend) { + $this->fallbackDirsPsr4 = array_merge( + (array) $paths, + $this->fallbackDirsPsr4 + ); + } + else { + $this->fallbackDirsPsr4 = array_merge( + $this->fallbackDirsPsr4, + (array) $paths + ); + } + } + elseif (!isset($this->prefixDirsPsr4[$prefix])) { + // Register directories for a new namespace. + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \Exception("A non-empty PSR-4 prefix must end with a namespace separator."); + } + if ($length > self::PREDICTOR_INDEX) { + $predictor = $prefix[0] . $prefix[self::PREDICTOR_INDEX]; + $this->prefixLengthsPsr4[$predictor][$prefix] = $length; + } + else { + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + } + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } + elseif ($prepend) { + // Prepend directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + (array) $paths, + $this->prefixDirsPsr4[$prefix] + ); + } + else { + // Append directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + $this->prefixDirsPsr4[$prefix], + (array) $paths + ); + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, + * replacing any others previously set for this prefix. + * + * @param string $prefix The prefix + * @param array|string $paths The PSR-0 base directories + */ + public function set($prefix, $paths) { + if (!$prefix) { + $this->fallbackDirsPsr0 = (array) $paths; + } + else { + $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, + * replacing any others previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param array|string $paths The PSR-4 base directories + * @throws \Exception + */ + public function setPsr4($prefix, $paths) { + if (!$prefix) { + $this->fallbackDirsPsr4 = (array) $paths; + } + else { + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \Exception("A non-empty PSR-4 prefix must end with a namespace separator."); + } + if ($length > self::PREDICTOR_INDEX) { + $predictor = $prefix[0] . $prefix[self::PREDICTOR_INDEX]; + $this->prefixLengthsPsr4[$predictor][$prefix] = $length; + } + else { + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + } + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } + } + + /** + * Turns on searching the include path for class files. + * + * @param bool $useIncludePath + */ + public function setUseIncludePath($useIncludePath) { + $this->useIncludePath = $useIncludePath; + } + + /** + * Can be used to check if the autoloader uses the include path to check + * for classes. + * + * @return bool + */ + public function getUseIncludePath() { + return $this->useIncludePath; + } + + /** + * Registers this instance as an autoloader. + * + * @param bool $prepend Whether to prepend the autoloader or not + */ + public function register($prepend = false) { + spl_autoload_register(array($this, 'loadClass'), true, $prepend); + } + + /** + * Unregisters this instance as an autoloader. + */ + public function unregister() { + spl_autoload_unregister(array($this, 'loadClass')); + } + + /** + * Loads the given class or interface. + * + * @param string $class The name of the class + * @return bool|null True if loaded, null otherwise + */ + public function loadClass($class) { + if ($file = $this->findFile($class)) { + include $file; + + return true; + } + } + + /** + * Finds the path to the file where the class is defined. + * + * @param string $class The name of the class + * + * @return string|false The path if found, false otherwise + */ + public function findFile($class) { + // work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731 + if ('\\' == $class[0]) { + $class = substr($class, 1); + } + + // class map lookup + if (isset($this->classMap[$class])) { + return $this->classMap[$class]; + } + + // PSR-4 lookup + $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . '.php'; + + $first = $class[0]; + if (isset($class[self::PREDICTOR_INDEX])) { + $predictor = $first . $class[self::PREDICTOR_INDEX]; + if (isset($this->prefixLengthsPsr4[$predictor])) { + foreach ($this->prefixLengthsPsr4[$predictor] as $prefix => $length) { + if (0 === strpos($class, $prefix)) { + foreach ($this->prefixDirsPsr4[$prefix] as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) { + return $file; + } + } + } + } + } + } + + if (isset($this->prefixLengthsPsr4[$first])) { + foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) { + if (0 === strpos($class, $prefix)) { + foreach ($this->prefixDirsPsr4[$prefix] as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) { + return $file; + } + } + } + } + } + + // PSR-4 fallback dirs + foreach ($this->fallbackDirsPsr4 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { + return $file; + } + } + + // PSR-0 lookup + if (false !== $pos = strrpos($class, '\\')) { + // namespaced class name + $logicalPathPsr0 + = substr($logicalPathPsr4, 0, $pos + 1) + . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR) + ; + } + else { + // PEAR-like class name + $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . '.php'; + } + + if (isset($this->prefixesPsr0[$first])) { + foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { + if (0 === strpos($class, $prefix)) { + foreach ($dirs as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + } + } + } + + // PSR-0 fallback dirs + foreach ($this->fallbackDirsPsr0 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + + // PSR-0 include paths. + if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { + return $file; + } + + // Remember that this class does not exist. + return $this->classMap[$class] = false; + } +} diff --git a/core/lib/Drupal/Core/Autoload/DrupalAutoloaderInit.php b/core/lib/Drupal/Core/Autoload/DrupalAutoloaderInit.php new file mode 100644 index 0000000..87f6478 --- /dev/null +++ b/core/lib/Drupal/Core/Autoload/DrupalAutoloaderInit.php @@ -0,0 +1,65 @@ +setPsr4('Drupal\Core\\', $baseDir . '/core/lib/Drupal/Core'); + $loader->setPsr4('Drupal\Component\\', $baseDir . '/core/lib/Drupal/Component'); + $loader->setPsr4('Drupal\Driver\\', $baseDir . '/core/lib/Drupal/Driver'); + foreach ($map as $namespace => $path) { + $loader->set($namespace, $path); + } + + $classMap = require $composerDir . '/autoload_classmap.php'; + if ($classMap) { + $loader->addClassMap($classMap); + } + + $loader->register(true); + + // @todo This can be updated once Composer provides a autoload_files.php. + require $vendorDir . '/kriswallsmith/assetic/src/functions.php'; + require $baseDir . '/core/lib/Drupal.php'; + + return $loader; + } +} diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php index 1bf9c05..23ea4db 100644 --- a/core/lib/Drupal/Core/DrupalKernel.php +++ b/core/lib/Drupal/Core/DrupalKernel.php @@ -19,7 +19,7 @@ use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\TerminableInterface; -use Composer\Autoload\ClassLoader; +use Drupal\Core\Autoload\ClassLoader; /** * The DrupalKernel class is the core of Drupal itself. @@ -97,7 +97,7 @@ class DrupalKernel implements DrupalKernelInterface, TerminableInterface { /** * The classloader object. * - * @var \Composer\Autoload\ClassLoader + * @var \Drupal\Core\Autoload\ClassLoader */ protected $classLoader; @@ -150,7 +150,7 @@ class DrupalKernel implements DrupalKernelInterface, TerminableInterface { * String indicating the environment, e.g. 'prod' or 'dev'. Used by * Symfony\Component\HttpKernel\Kernel::__construct(). Drupal does not use * this value currently. Pass 'prod'. - * @param \Composer\Autoload\ClassLoader $class_loader + * @param \Drupal\Core\Autoload\ClassLoader $class_loader * (optional) The classloader is only used if $storage is not given or * the load from storage fails and a container rebuild is required. In * this case, the loaded modules will be registered with this loader in @@ -218,7 +218,7 @@ public function discoverServiceProviders() { $this->moduleList = isset($module_list['enabled']) ? $module_list['enabled'] : array(); } $module_filenames = $this->getModuleFileNames(); - $this->registerNamespaces($this->getModuleNamespaces($module_filenames)); + $this->registerNamespacesPsr4($this->getModuleNamespacesPsr4($module_filenames)); // Load each module's serviceProvider class. foreach ($this->moduleList as $module => $weight) { @@ -402,8 +402,8 @@ protected function initializeContainer() { // All namespaces must be registered before we attempt to use any service // from the container. $container_modules = $this->container->getParameter('container.modules'); - $namespaces_before = $this->classLoader->getPrefixes(); - $this->registerNamespaces($this->getModuleNamespaces($container_modules)); + $namespaces_before = $this->classLoader->getPrefixesPsr4(); + $this->registerNamespacesPsr4($this->getModuleNamespacesPsr4($container_modules)); // If 'container.modules' is wrong, the container must be rebuilt. if (!isset($this->moduleList)) { @@ -416,9 +416,9 @@ protected function initializeContainer() { // registerNamespaces() performs a merge rather than replace, so to // effectively remove erroneous registrations, we must replace them with // empty arrays. - $namespaces_after = $this->classLoader->getPrefixes(); + $namespaces_after = $this->classLoader->getPrefixesPsr4(); $namespaces_before += array_fill_keys(array_diff(array_keys($namespaces_after), array_keys($namespaces_before)), array()); - $this->registerNamespaces($namespaces_before); + $this->registerNamespacesPsr4($namespaces_before); } } @@ -492,14 +492,15 @@ protected function buildContainer() { $container->setParameter('container.modules', $this->getModuleFileNames()); // Get a list of namespaces and put it onto the container. - $namespaces = $this->getModuleNamespaces($this->getModuleFileNames()); + $namespaces = $this->getModuleNamespacesPsr4($this->getModuleFileNames()); // Add all components in \Drupal\Core and \Drupal\Component that have a // Plugin directory. foreach (array('Core', 'Component') as $parent_directory) { $path = DRUPAL_ROOT . '/core/lib/Drupal/' . $parent_directory; + $parent_namespace = 'Drupal\\' . $parent_directory; foreach (new \DirectoryIterator($path) as $component) { if (!$component->isDot() && is_dir($component->getPathname() . '/Plugin')) { - $namespaces['Drupal\\' . $parent_directory .'\\' . $component->getFilename()] = DRUPAL_ROOT . '/core/lib'; + $namespaces[$parent_namespace . '\\' . $component->getFilename()] = $path . '/' . $component->getFilename(); } } } @@ -632,7 +633,28 @@ protected function getModuleFileNames() { } /** - * Gets the namespaces of each enabled module. + * Gets the namespaces of each enabled module, + * each with their PSR-4 directories. + * + * @param array $moduleFileNames + * @return array + */ + protected function getModuleNamespacesPsr4($moduleFileNames) { + $namespaces = array(); + foreach ($moduleFileNames as $module => $filename) { + // @todo Remove lib/Drupal/$module, once the switch to PSR-4 is complete. + $namespaces["Drupal\\$module"][] = DRUPAL_ROOT . '/' . dirname($filename) . '/lib/Drupal/' . $module; + $namespaces["Drupal\\$module"][] = DRUPAL_ROOT . '/' . dirname($filename) . '/lib'; + } + return $namespaces; + } + + /** + * Gets the namespaces of each enabled module, + * each with its PSR-0 directory. + * + * @param array $moduleFileNames + * @return array */ protected function getModuleNamespaces($moduleFileNames) { $namespaces = array(); @@ -643,7 +665,20 @@ protected function getModuleNamespaces($moduleFileNames) { } /** - * Registers a list of namespaces. + * Registers a list of namespaces with PSR-4 directories. + * + * @param array $namespaces + */ + protected function registerNamespacesPsr4(array $namespaces = array()) { + foreach ($namespaces as $prefix => $paths) { + $this->classLoader->addPsr4($prefix . '\\', $paths); + } + } + + /** + * Registers a list of namespaces with PSR-0 directories. + * + * @param array $namespaces */ protected function registerNamespaces(array $namespaces = array()) { foreach ($namespaces as $prefix => $path) { diff --git a/core/lib/Drupal/Core/Plugin/Discovery/AnnotatedClassDiscovery.php b/core/lib/Drupal/Core/Plugin/Discovery/AnnotatedClassDiscovery.php index e033caf..ae208af 100644 --- a/core/lib/Drupal/Core/Plugin/Discovery/AnnotatedClassDiscovery.php +++ b/core/lib/Drupal/Core/Plugin/Discovery/AnnotatedClassDiscovery.php @@ -15,17 +15,23 @@ class AnnotatedClassDiscovery extends ComponentAnnotatedClassDiscovery { /** - * The subdirectory within a namespace to look for plugins. + * A suffix to append to each PSR-4 directory associated with a base + * namespace, to form the directories where plugins are found. * - * If the plugins are in the top level of the namespace and not within a - * subdirectory, set this to an empty string. + * @var string + */ + protected $directorySuffix = ''; + + /** + * A suffix to append to each base namespace, to obtain the namespaces where + * plugins are found. * * @var string */ - protected $subdir = ''; + protected $namespaceSuffix = ''; /** - * An object containing the namespaces to look for plugin implementations. + * A list of base namespaces with their PSR-4 directories. * * @var \Traversable */ @@ -47,7 +53,11 @@ class AnnotatedClassDiscovery extends ComponentAnnotatedClassDiscovery { */ function __construct($subdir, \Traversable $root_namespaces, $plugin_definition_annotation_name = 'Drupal\Component\Annotation\Plugin') { if ($subdir) { - $this->subdir = str_replace('/', '\\', $subdir); + if ('/' !== $subdir[0]) { + $subdir = '/' . $subdir; + } + $this->directorySuffix = $subdir; + $this->namespaceSuffix = str_replace('/', '\\', $subdir); } $this->rootNamespacesIterator = $root_namespaces; $plugin_namespaces = array(); @@ -92,11 +102,18 @@ protected function getProviderFromNamespace($namespace) { */ protected function getPluginNamespaces() { $plugin_namespaces = array(); - foreach ($this->rootNamespacesIterator as $namespace => $dir) { - if ($this->subdir) { - $namespace .= "\\{$this->subdir}"; + if ($this->namespaceSuffix) { + foreach ($this->rootNamespacesIterator as $namespace => $dirs) { + $namespace .= $this->namespaceSuffix; + foreach ((array) $dirs as $dir) { + $plugin_namespaces[$namespace][] = $dir . $this->directorySuffix; + } + } + } + else { + foreach ($this->rootNamespacesIterator as $namespace => $dirs) { + $plugin_namespaces[$namespace] = (array) $dirs; } - $plugin_namespaces[$namespace] = array($dir); } return $plugin_namespaces; diff --git a/core/modules/block/tests/lib/Drupal/block/Tests/BlockBaseTest.php b/core/modules/block/tests/Drupal/block/Tests/BlockBaseTest.php similarity index 100% rename from core/modules/block/tests/lib/Drupal/block/Tests/BlockBaseTest.php rename to core/modules/block/tests/Drupal/block/Tests/BlockBaseTest.php diff --git a/core/modules/block/tests/lib/Drupal/block/Tests/BlockFormControllerTest.php b/core/modules/block/tests/Drupal/block/Tests/BlockFormControllerTest.php similarity index 100% rename from core/modules/block/tests/lib/Drupal/block/Tests/BlockFormControllerTest.php rename to core/modules/block/tests/Drupal/block/Tests/BlockFormControllerTest.php diff --git a/core/modules/block/tests/lib/Drupal/block/Tests/Plugin/views/display/BlockTest.php b/core/modules/block/tests/Drupal/block/Tests/Plugin/views/display/BlockTest.php similarity index 100% rename from core/modules/block/tests/lib/Drupal/block/Tests/Plugin/views/display/BlockTest.php rename to core/modules/block/tests/Drupal/block/Tests/Plugin/views/display/BlockTest.php diff --git a/core/modules/comment/comment.install b/core/modules/comment/comment.install index 04e1291..0ff09b1 100644 --- a/core/modules/comment/comment.install +++ b/core/modules/comment/comment.install @@ -13,7 +13,11 @@ function comment_uninstall() { variable_del('comment_block_count'); $node_types = array_keys(node_type_get_types()); Drupal::entityManager()->addNamespaces(new ArrayIterator(array( - 'Drupal\comment' => DRUPAL_ROOT . '/core/modules/comment/lib', + 'Drupal\comment' => array( + DRUPAL_ROOT . '/core/modules/comment/lib/Drupal/comment', + DRUPAL_ROOT . '/core/modules/comment/lib', + DRUPAL_ROOT . '/core/modules/comment/src', + ), ))); drupal_classloader_register('comment', 'core/modules/comment'); foreach ($node_types as $node_type) { diff --git a/core/modules/simpletest/simpletest.module b/core/modules/simpletest/simpletest.module index 8d441f4..b98d528 100644 --- a/core/modules/simpletest/simpletest.module +++ b/core/modules/simpletest/simpletest.module @@ -454,21 +454,28 @@ function simpletest_test_get_all() { $all_data = $module_data + system_rebuild_theme_data(); $all_data += drupal_system_listing('/\.profile$/', 'profiles', 'name'); foreach ($all_data as $name => $data) { - // Build directory in which the test files would reside. - $tests_dir = DRUPAL_ROOT . '/' . dirname($data->uri) . '/lib/Drupal/' . $name . '/Tests'; + $extension_dir = DRUPAL_ROOT . '/' . dirname($data->uri); + + // Build directories in which the test files would reside. + $tests_dirs = array( + $extension_dir . '/lib/Drupal/' . $name . '/Tests', + $extension_dir . '/lib/Tests', + $extension_dir . '/tests/Drupal/' . $name . '/Tests', + $extension_dir . '/tests/lib', + ); + + $namespace = '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($data->uri) . '/lib/'; - foreach ($files as $file) { - // Convert the file name into the namespaced class name. - $replacements = array( - '/' => '\\', - $basedir => '', - '.php' => '', - ); - $classes[] = strtr($file->uri, $replacements); + foreach ($tests_dirs as $tests_dir) { + if (is_dir($tests_dir)) { + $files = file_scan_directory($tests_dir, '/.*\.php/'); + if (!empty($files)) { + $strlen = strlen($tests_dir) + 1; + // Convert the file names into the namespaced class names. + foreach ($files as $file) { + $classes[] = $namespace . str_replace('/', '\\', substr($file->uri, $strlen, -4)); + } } } } @@ -526,8 +533,14 @@ function simpletest_classloader_register() { foreach ($types as $type => $info) { $matches = drupal_system_listing('/^' . DRUPAL_PHP_FUNCTION_PATTERN . '\.' . $info['extension'] . '$/', $info['dir']); foreach ($matches as $name => $file) { + // @todo Register PSR-4 namespace directories, once our classloader supports it. + // See https://drupal.org/node/2058867 drupal_classloader_register($name, dirname($file->uri)); - $classloader->add('Drupal\\' . $name . '\\Tests', DRUPAL_ROOT . '/' . dirname($file->uri) . '/tests'); + $extension_dir = dirname($file->uri); + $classloader->addPsr4('Drupal\\' . $name . '\\Tests\\', array( + $extension_dir . '/tests/Drupal/' . $name . '/Tests', + $extension_dir . '/tests/lib', + )); // While being there, prime drupal_get_filename(). drupal_get_filename($type, $name, $file->uri); } diff --git a/core/modules/statistics/statistics.php b/core/modules/statistics/statistics.php index ed132e8..22acde2 100644 --- a/core/modules/statistics/statistics.php +++ b/core/modules/statistics/statistics.php @@ -9,7 +9,7 @@ chdir('../../..'); // Load the Drupal bootstrap. -require_once dirname(dirname(__DIR__)) . '/vendor/autoload.php'; +require_once dirname(dirname(__DIR__)) . '/autoload.php'; require_once dirname(dirname(__DIR__)) . '/includes/bootstrap.inc'; drupal_bootstrap(DRUPAL_BOOTSTRAP_VARIABLES); diff --git a/core/modules/system/lib/Drupal/system/Tests/Plugin/Discovery/AnnotatedClassDiscoveryTest.php b/core/modules/system/lib/Drupal/system/Tests/Plugin/Discovery/AnnotatedClassDiscoveryTest.php index d2fba9b..52bd303 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Plugin/Discovery/AnnotatedClassDiscoveryTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Plugin/Discovery/AnnotatedClassDiscoveryTest.php @@ -57,7 +57,13 @@ public function setUp() { 'provider' => 'plugin_test', ), ); - $namespaces = new \ArrayObject(array('Drupal\plugin_test' => DRUPAL_ROOT . '/core/modules/system/tests/modules/plugin_test/lib')); + $namespaces = new \ArrayObject(array( + 'Drupal\plugin_test' => array( + // @todo Remove lib/Drupal/$module, once the switch to PSR-4 is complete. + DRUPAL_ROOT . '/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test', + DRUPAL_ROOT . '/core/modules/system/tests/modules/plugin_test/lib', + ), + )); $this->discovery = new AnnotatedClassDiscovery('Plugin/plugin_test/fruit', $namespaces); $this->emptyDiscovery = new AnnotatedClassDiscovery('Plugin/non_existing_module/non_existing_plugin_type', $namespaces); } diff --git a/core/modules/system/lib/Drupal/system/Tests/Plugin/Discovery/CustomAnnotationClassDiscoveryTest.php b/core/modules/system/lib/Drupal/system/Tests/Plugin/Discovery/CustomAnnotationClassDiscoveryTest.php index d61c013..17bbfa5 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Plugin/Discovery/CustomAnnotationClassDiscoveryTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Plugin/Discovery/CustomAnnotationClassDiscoveryTest.php @@ -41,7 +41,13 @@ protected function setUp() { 'provider' => 'plugin_test', ), ); - $root_namespaces = new \ArrayObject(array('Drupal\plugin_test' => DRUPAL_ROOT . '/core/modules/system/tests/modules/plugin_test/lib')); + $root_namespaces = new \ArrayObject(array( + 'Drupal\plugin_test' => array( + // @todo Remove lib/Drupal/$module, once the switch to PSR-4 is complete. + DRUPAL_ROOT . '/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test', + DRUPAL_ROOT . '/core/modules/system/tests/modules/plugin_test/lib', + ), + )); $this->discovery = new AnnotatedClassDiscovery('Plugin/plugin_test/custom_annotation', $root_namespaces, 'Drupal\plugin_test\Plugin\Annotation\PluginExample'); $this->emptyDiscovery = new AnnotatedClassDiscovery('Plugin/non_existing_module/non_existing_plugin_type', $root_namespaces, 'Drupal\plugin_test\Plugin\Annotation\PluginExample'); diff --git a/core/modules/system/lib/Drupal/system/Tests/Plugin/Discovery/CustomDirectoryAnnotatedClassDiscoveryTest.php b/core/modules/system/lib/Drupal/system/Tests/Plugin/Discovery/CustomDirectoryAnnotatedClassDiscoveryTest.php index c005300..b817c68 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Plugin/Discovery/CustomDirectoryAnnotatedClassDiscoveryTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Plugin/Discovery/CustomDirectoryAnnotatedClassDiscoveryTest.php @@ -39,7 +39,13 @@ protected function setUp() { 'provider' => 'plugin_test', ), ); - $namespaces = new \ArrayObject(array('Drupal\plugin_test' => DRUPAL_ROOT . '/core/modules/system/tests/modules/plugin_test/lib')); + $namespaces = new \ArrayObject(array( + 'Drupal\plugin_test' => array( + // @todo Remove lib/Drupal/$module, once the switch to PSR-4 is complete. + DRUPAL_ROOT . '/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test', + DRUPAL_ROOT . '/core/modules/system/tests/modules/plugin_test/lib', + ), + )); $this->discovery = new AnnotatedClassDiscovery('', $namespaces); $empty_namespaces = new \ArrayObject(); $this->emptyDiscovery = new AnnotatedClassDiscovery('', $empty_namespaces); diff --git a/core/modules/system/tests/http.php b/core/modules/system/tests/http.php index 662031f..10f4e20 100644 --- a/core/modules/system/tests/http.php +++ b/core/modules/system/tests/http.php @@ -18,6 +18,6 @@ // Change current directory to the Drupal root. chdir('../../../..'); -require_once dirname(dirname(dirname(__DIR__))) . '/vendor/autoload.php'; +require_once dirname(dirname(dirname(__DIR__))) . '/autoload.php'; require_once dirname(dirname(dirname(__DIR__))) . '/includes/bootstrap.inc'; drupal_handle_request(TRUE); diff --git a/core/modules/system/tests/https.php b/core/modules/system/tests/https.php index 247e6e5..54c8afa 100644 --- a/core/modules/system/tests/https.php +++ b/core/modules/system/tests/https.php @@ -20,6 +20,6 @@ // Change current directory to the Drupal root. chdir('../../../..'); -require_once dirname(dirname(dirname(__DIR__))) . '/vendor/autoload.php'; +require_once dirname(dirname(dirname(__DIR__))) . '/autoload.php'; require_once dirname(dirname(dirname(__DIR__))) . '/includes/bootstrap.inc'; drupal_handle_request(TRUE); diff --git a/core/modules/taxonomy/taxonomy.install b/core/modules/taxonomy/taxonomy.install index 7648ba0..a4494e2 100644 --- a/core/modules/taxonomy/taxonomy.install +++ b/core/modules/taxonomy/taxonomy.install @@ -14,7 +14,11 @@ */ function taxonomy_uninstall() { Drupal::entityManager()->addNamespaces(new ArrayIterator(array( - 'Drupal\taxonomy' => DRUPAL_ROOT . '/core/modules/taxonomy/lib', + 'Drupal\taxonomy' => array( + // @todo Remove lib/Drupal/$module, once the switch to PSR-4 is complete. + DRUPAL_ROOT . '/core/modules/taxonomy/lib/Drupal/taxonomy', + DRUPAL_ROOT . '/core/modules/taxonomy/lib', + ), ))); drupal_classloader_register('taxonomy', 'core/modules/taxonomy'); // Remove taxonomy_term bundles. diff --git a/core/modules/views/lib/Drupal/views/Plugin/Discovery/ViewsHandlerDiscovery.php b/core/modules/views/lib/Drupal/views/Plugin/Discovery/ViewsHandlerDiscovery.php index a3a08c0..09f5255 100644 --- a/core/modules/views/lib/Drupal/views/Plugin/Discovery/ViewsHandlerDiscovery.php +++ b/core/modules/views/lib/Drupal/views/Plugin/Discovery/ViewsHandlerDiscovery.php @@ -22,13 +22,6 @@ class ViewsHandlerDiscovery extends AnnotatedClassDiscovery { protected $type; /** - * An object containing the namespaces to look for plugin implementations. - * - * @var \Traversable - */ - protected $rootNamespacesIterator; - - /** * Constructs a ViewsHandlerDiscovery object. * * @param string $type @@ -39,15 +32,7 @@ class ViewsHandlerDiscovery extends AnnotatedClassDiscovery { */ function __construct($type, \Traversable $root_namespaces) { $this->type = $type; - $this->rootNamespacesIterator = $root_namespaces; - - $plugin_namespaces = array(); - foreach ($root_namespaces as $namespace => $dir) { - $plugin_namespaces["$namespace\\Plugin\\views\\{$type}"] = array($dir); - } - - $this->pluginNamespaces = $plugin_namespaces; - $this->pluginDefinitionAnnotationName = 'Drupal\Component\Annotation\PluginID'; + parent::__construct("Plugin/views/$type", $root_namespaces, 'Drupal\Component\Annotation\PluginID'); } /** @@ -62,16 +47,4 @@ public function getDefinitions() { return $definitions; } - /** - * {@inheritdoc} - */ - protected function getPluginNamespaces() { - $plugin_namespaces = array(); - foreach ($this->rootNamespacesIterator as $namespace => $dir) { - $plugin_namespaces["$namespace\\Plugin\\views\\{$this->type}"] = array($dir); - } - - return $plugin_namespaces; - } - } diff --git a/core/scripts/run-tests.sh b/core/scripts/run-tests.sh index 31ea371..d274252 100755 --- a/core/scripts/run-tests.sh +++ b/core/scripts/run-tests.sh @@ -4,7 +4,7 @@ * This script runs Drupal tests from command line. */ -require_once __DIR__ . '/../vendor/autoload.php'; +require_once __DIR__ . '/../autoload.php'; use Drupal\Core\StreamWrapper\PublicStream; diff --git a/core/scripts/switch-psr4.sh b/core/scripts/switch-psr4.sh new file mode 100644 index 0000000..ed76b47 --- /dev/null +++ b/core/scripts/switch-psr4.sh @@ -0,0 +1,122 @@ +#!/bin/php +isDot()) { + // do nothing + } + elseif ($fileinfo->isDir()) { + process_candidate_dir($fileinfo->getPathname()); + } + } +} + +function process_candidate_dir($dir) { + foreach (new \DirectoryIterator($dir) as $fileinfo) { + if ($fileinfo->isDot()) { + // Ignore "." and "..". + } + elseif ($fileinfo->isDir()) { + // It's a directory. + switch ($fileinfo->getFilename()) { + case 'lib': + case 'module_autoload_test': + // Ignore these directory names. + continue; + default: + // Look for more extensions in subdirectories. + process_candidate_dir($fileinfo->getPathname()); + } + } + else { + // It's a file. + if (preg_match('/^(.+).info.yml$/', $fileinfo->getFilename(), $m)) { + // It's a *.info.yml file, so we found an extension directory. + $extension_name = $m[1]; + } + } + } + if (isset($extension_name)) { + process_extension($extension_name, $dir); + } +} + +function process_extension($name, $dir) { + + // Move main module class files. + if (is_dir("$dir/lib/Drupal/$name")) { + // This is a module directory with a PSR-0 /lib/ folder. + // Move to src/ as a temporary location. + if (!rename($src = "$dir/lib/Drupal/$name", $dest = "$dir/src")) { + throw new Exception("Rename $src to $dest failed."); + } + } + + // Move class files in tests directory. + if (is_dir("$dir/tests/Drupal/$name/Tests")) { + // Move to tests/src/ as a temporary location. + if (!rename($src = "$dir/tests/Drupal/$name/Tests", $dest = "$dir/tests/src")) { + throw new Exception("Rename $src to $dest failed."); + } + } + + // Clean up empty directories. + foreach (array( + "lib/Drupal/$name", + 'lib/Drupal', + 'lib', + "tests/Drupal/$name/Tests", + "tests/Drupal/$name", + "tests/Drupal", + ) as $subdir) { + if (!is_dir("$dir/$subdir")) { + continue; + } + if (!is_dir_empty("$dir/$subdir")) { + throw new Exception("$dir/$subdir is not empty."); + } + rmdir("$dir/$subdir"); + } + + // Move back to lib/ or tests/lib/. + if (is_dir("$dir/src")) { + rename("$dir/src", "$dir/lib"); + } + if (is_dir("$dir/tests/src")) { + rename("$dir/tests/src", "$dir/tests/lib"); + } +} + +function is_dir_empty($dir) { + if (!is_readable($dir)) { + return NULL; + } + $handle = opendir($dir); + while (false !== ($entry = readdir($handle))) { + if ($entry != "." && $entry != "..") { + return FALSE; + } + } + return TRUE; +} diff --git a/core/tests/bootstrap.php b/core/tests/bootstrap.php index 66c4be4..e0be3f8 100644 --- a/core/tests/bootstrap.php +++ b/core/tests/bootstrap.php @@ -1,7 +1,7 @@ add('Drupal\\Tests', __DIR__); foreach (scandir(__DIR__ . "/../modules") as $module) { diff --git a/core/update.php b/core/update.php index ac36b2a..0238871 100644 --- a/core/update.php +++ b/core/update.php @@ -22,7 +22,7 @@ // Change the directory to the Drupal root. chdir('..'); -require_once __DIR__ . '/vendor/autoload.php'; +require_once __DIR__ . '/autoload.php'; // Exit early if an incompatible PHP version would cause fatal errors. // The minimum version is specified explicitly, as DRUPAL_MINIMUM_PHP is not diff --git a/index.php b/index.php index 426aa22..5f5ada6 100644 --- a/index.php +++ b/index.php @@ -8,7 +8,7 @@ * See COPYRIGHT.txt and LICENSE.txt files in the "core" directory. */ -require_once __DIR__ . '/core/vendor/autoload.php'; +require_once __DIR__ . '/core/autoload.php'; require_once __DIR__ . '/core/includes/bootstrap.inc'; try {