Legoktm has uploaded a new change for review. ( 
https://gerrit.wikimedia.org/r/373626 )

Change subject: [WIP] Enable using PSR-4 autoloader for MediaWiki core and 
extensions
......................................................................

[WIP] Enable using PSR-4 autoloader for MediaWiki core and extensions

This hooks up composer's ClassLoader to MediaWiki's autoloader and let's
us easily register PSR-4 namespaces that should be autoloaded.

Extensions can set a "AutoloadNamespaces" property in extension.json to
register PSR-4 compatible namespaces to be autoloaded.

Only the AutoLoader class is aware that composer is used underneath, so
in case we need to switch implementations later, nothing else would
require updating.

Still WIP because tests and generate autoload script need to be updated
to ignore PSR-4 autoloaded classes.

Bug: T99865
Bug: T173799
Change-Id: Id095dde37cbb40aa424fb628bd3c94e684ca2f65
---
M docs/extension.schema.v1.json
M docs/extension.schema.v2.json
M includes/AutoLoader.php
M includes/PreConfigSetup.php
M includes/registration/ExtensionRegistry.php
5 files changed, 79 insertions(+), 18 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/core 
refs/changes/26/373626/1

diff --git a/docs/extension.schema.v1.json b/docs/extension.schema.v1.json
index 7cfebca..ddf82e8 100644
--- a/docs/extension.schema.v1.json
+++ b/docs/extension.schema.v1.json
@@ -567,6 +567,10 @@
                        "type": "object",
                        "description": "SpecialPages implemented in this 
extension (mapping of page name to class name)"
                },
+               "AutoloadNamespaces": {
+                       "type": "object",
+                       "description": "Mapping of PSR-4 compliant namespace to 
directory for autoloading"
+               },
                "AutoloadClasses": {
                        "type": "object"
                },
diff --git a/docs/extension.schema.v2.json b/docs/extension.schema.v2.json
index 75a4f2c..0bdf97d 100644
--- a/docs/extension.schema.v2.json
+++ b/docs/extension.schema.v2.json
@@ -588,6 +588,10 @@
                        "type": "object",
                        "description": "SpecialPages implemented in this 
extension (mapping of page name to class name)"
                },
+               "AutoloadNamespaces": {
+                       "type": "object",
+                       "description": "Mapping of PSR-4 compliant namespace to 
directory for autoloading"
+               },
                "AutoloadClasses": {
                        "type": "object"
                },
diff --git a/includes/AutoLoader.php b/includes/AutoLoader.php
index 8dc7d40..b9faeda 100644
--- a/includes/AutoLoader.php
+++ b/includes/AutoLoader.php
@@ -27,8 +27,15 @@
  */
 require_once __DIR__ . '/../autoload.php';
 
+use Composer\Autoload\ClassLoader;
+
 class AutoLoader {
        static protected $autoloadLocalClassesLower = null;
+
+       /**
+        * @var ClassLoader
+        */
+       static protected $classLoader;
 
        /**
         * autoload - take a class name and attempt to load it
@@ -88,6 +95,47 @@
        static function resetAutoloadLocalClassesLower() {
                self::$autoloadLocalClassesLower = null;
        }
+
+       /**
+        * Require the composer autoloader
+        *
+        * @since 1.30
+        */
+       public static function requireComposerAutoloader() {
+               if ( !self::$classLoader ) {
+                       self::$classLoader = require dirname( __DIR__ ) . 
'/vendor/autoload.php';
+                       foreach ( self::getAutoloadNamespaces() as $ns => $path 
) {
+                               self::$classLoader->addPsr4( $ns, [ $path ] );
+                       }
+               }
+       }
+
+       /**
+        * Register PSR-4 compliant namespaces with the autoloader
+        *
+        * @param string[] $mapping Namespace => Path
+        * @since 1.30
+        */
+       public static function addAutoloadNamespaces( array $mapping ) {
+               self::requireComposerAutoloader();
+               foreach ( $mapping as $ns => $path ) {
+                       self::$classLoader->addPsr4( $ns, [ $path ] );
+               }
+       }
+
+       /**
+        * Get a mapping of namespace => file path
+        * The namespaces should follow the PSR-4 standard for autoloading
+        *
+        * @see <http://www.php-fig.org/psr/psr-4/>
+        * @since 1.30
+        * @return string[]
+        */
+       private static function getAutoloadNamespaces() {
+               return [
+                       'MediaWiki\\Linker\\' => __DIR__ .'/linker'
+               ];
+       }
 }
 
 spl_autoload_register( [ 'AutoLoader', 'autoload' ] );
diff --git a/includes/PreConfigSetup.php b/includes/PreConfigSetup.php
index bda7886..672ec03 100644
--- a/includes/PreConfigSetup.php
+++ b/includes/PreConfigSetup.php
@@ -48,7 +48,5 @@
 // Load global functions
 require_once "$IP/includes/GlobalFunctions.php";
 
-// Load composer's autoloader if present
-if ( is_readable( "$IP/vendor/autoload.php" ) ) {
-       require_once "$IP/vendor/autoload.php";
-}
+// Load composer's autoloader
+Autoloader::requireComposerAutoloader();
diff --git a/includes/registration/ExtensionRegistry.php 
b/includes/registration/ExtensionRegistry.php
index eac04a9..574e9bd 100644
--- a/includes/registration/ExtensionRegistry.php
+++ b/includes/registration/ExtensionRegistry.php
@@ -196,6 +196,7 @@
        public function readFromQueue( array $queue ) {
                global $wgVersion;
                $autoloadClasses = [];
+               $autoloadNamespaces = [];
                $autoloaderPaths = [];
                $processor = new ExtensionProcessor();
                $versionChecker = new VersionChecker( $wgVersion );
@@ -226,10 +227,15 @@
                                $incompatible[] = "$path: unsupported 
manifest_version: {$version}";
                        }
 
-                       $autoload = $this->processAutoLoader( dirname( $path ), 
$info );
-                       // Set up the autoloader now so custom processors will 
work
-                       $GLOBALS['wgAutoloadClasses'] += $autoload;
-                       $autoloadClasses += $autoload;
+                       $dir = dirname( $path );
+                       if ( isset( $info['AutoloadClasses'] ) ) {
+                               $autoload = $this->processAutoLoader( $dir, 
$info['AutoloadClasses'] );
+                               $GLOBALS['wgAutoloadClasses'] += $autoload;
+                               $autoloadClasses += $autoload;
+                       }
+                       if ( isset( $info['AutoloadNamespaces'] ) ) {
+                               $autoloadNamespaces += 
$this->processAutoLoader( $dir, $info['AutoloadNamespaces'] );
+                       }
 
                        // get all requirements/dependencies for this extension
                        $requires = $processor->getRequirements( $info );
@@ -241,7 +247,7 @@
 
                        // Get extra paths for later inclusion
                        $autoloaderPaths = array_merge( $autoloaderPaths,
-                               $processor->getExtraAutoloaderPaths( dirname( 
$path ), $info ) );
+                               $processor->getExtraAutoloaderPaths( $dir, 
$info ) );
                        // Compatible, read and extract info
                        $processor->extractInfo( $path, $info, $version );
                }
@@ -268,6 +274,7 @@
                $data['globals']['wgAutoloadClasses'] = [];
                $data['autoload'] = $autoloadClasses;
                $data['autoloaderPaths'] = $autoloaderPaths;
+               $data['autoloaderNS'] = $autoloadNamespaces;
                return $data;
        }
 
@@ -313,6 +320,10 @@
                                default:
                                        throw new UnexpectedValueException( 
"Unknown merge strategy '$mergeStrategy'" );
                        }
+               }
+
+               if ( isset( $info['autoloaderNS'] ) ) {
+                       Autoloader::addAutoloadNamespaces( 
$info['autoloaderNS'] );
                }
 
                foreach ( $info['defines'] as $name => $val ) {
@@ -391,20 +402,16 @@
        }
 
        /**
-        * Register classes with the autoloader
+        * Fully expand autoloader paths
         *
         * @param string $dir
         * @param array $info
         * @return array
         */
        protected function processAutoLoader( $dir, array $info ) {
-               if ( isset( $info['AutoloadClasses'] ) ) {
-                       // Make paths absolute, relative to the JSON file
-                       return array_map( function ( $file ) use ( $dir ) {
-                               return "$dir/$file";
-                       }, $info['AutoloadClasses'] );
-               } else {
-                       return [];
-               }
+               // Make paths absolute, relative to the JSON file
+               return array_map( function ( $file ) use ( $dir ) {
+                       return "$dir/$file";
+               }, $info );
        }
 }

-- 
To view, visit https://gerrit.wikimedia.org/r/373626
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Id095dde37cbb40aa424fb628bd3c94e684ca2f65
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/core
Gerrit-Branch: master
Gerrit-Owner: Legoktm <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to