aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad Jorsch <bjorsch@wikimedia.org>2018-09-20 13:44:35 -0400
committerBrad Jorsch <bjorsch@wikimedia.org>2018-09-20 15:15:27 -0400
commitca3789a271b982580c0be0b92599fa37f5c5948d (patch)
treee50b363699dd0136e7a1630204aaef7c989d6a49
parent62c6f40d73637c777a6bf14eaa4d1512e6663170 (diff)
downloadmediawikicore-ca3789a271b982580c0be0b92599fa37f5c5948d.tar.gz
mediawikicore-ca3789a271b982580c0be0b92599fa37f5c5948d.zip
AutoloadGenerator: Filter PSR4-compliant classes instead of ignoring directories
Per discussion in T166010, we're going to handle class aliases (e.g. for BC) by including the class_alias() call in the same file as the target class. When the target class is a PSR4-compliant class, we still need to pick up that alias for inclusion in autoload.php. Thus, instead of excluding whole directories, we need to process the files and filter out only those found classes that are PSR4 compliant. Bug: T204983 Change-Id: I1c516998df368531c90ea54acc5be8be96e1db6c
-rw-r--r--includes/utils/AutoloadGenerator.php42
-rw-r--r--maintenance/generateLocalAutoload.php2
-rw-r--r--tests/phpunit/structure/AutoLoaderStructureTest.php22
3 files changed, 64 insertions, 2 deletions
diff --git a/includes/utils/AutoloadGenerator.php b/includes/utils/AutoloadGenerator.php
index 511b67346b93..2fc7bc0645d2 100644
--- a/includes/utils/AutoloadGenerator.php
+++ b/includes/utils/AutoloadGenerator.php
@@ -50,6 +50,13 @@ class AutoloadGenerator {
protected $excludePaths = [];
/**
+ * Configured PSR4 namespaces
+ *
+ * @var string[] namespace => path
+ */
+ protected $psr4Namespaces = [];
+
+ /**
* @param string $basepath Root path of the project being scanned for classes
* @param array|string $flags
*
@@ -80,6 +87,22 @@ class AutoloadGenerator {
}
/**
+ * Set PSR4 namespaces
+ *
+ * Unlike self::setExcludePaths(), this will only skip outputting the
+ * autoloader entry when the namespace matches the path.
+ *
+ * @since 1.32
+ * @param string[] $namespaces Associative array mapping namespace to path
+ */
+ public function setPsr4Namespaces( array $namespaces ) {
+ foreach ( $namespaces as $ns => $path ) {
+ $ns = rtrim( $ns, '\\' ) . '\\';
+ $this->psr4Namespaces[$ns] = rtrim( self::normalizePathSeparator( $path ), '/' );
+ }
+ }
+
+ /**
* Whether the file should be excluded
*
* @param string $path File path
@@ -135,6 +158,25 @@ class AutoloadGenerator {
$result = $this->collector->getClasses(
file_get_contents( $inputPath )
);
+
+ // Filter out classes that will be found by PSR4
+ $result = array_filter( $result, function ( $class ) use ( $inputPath ) {
+ $parts = explode( '\\', $class );
+ for ( $i = count( $parts ) - 1; $i > 0; $i-- ) {
+ $ns = implode( '\\', array_slice( $parts, 0, $i ) ) . '\\';
+ if ( isset( $this->psr4Namespaces[$ns] ) ) {
+ $expectedPath = $this->psr4Namespaces[$ns] . '/'
+ . implode( '/', array_slice( $parts, $i ) )
+ . '.php';
+ if ( $inputPath === $expectedPath ) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ } );
+
if ( $result ) {
$shortpath = substr( $inputPath, $len );
$this->classes[$shortpath] = $result;
diff --git a/maintenance/generateLocalAutoload.php b/maintenance/generateLocalAutoload.php
index 189858c5af5d..19b7ee5a876e 100644
--- a/maintenance/generateLocalAutoload.php
+++ b/maintenance/generateLocalAutoload.php
@@ -11,7 +11,7 @@ require_once __DIR__ . '/../includes/utils/AutoloadGenerator.php';
$base = dirname( __DIR__ );
$generator = new AutoloadGenerator( $base, 'local' );
-$generator->setExcludePaths( array_values( AutoLoader::getAutoloadNamespaces() ) );
+$generator->setPsr4Namespaces( AutoLoader::getAutoloadNamespaces() );
$generator->initMediaWikiDefault();
// Write out the autoload
diff --git a/tests/phpunit/structure/AutoLoaderStructureTest.php b/tests/phpunit/structure/AutoLoaderStructureTest.php
index 2800d021f8d2..8be57601760e 100644
--- a/tests/phpunit/structure/AutoLoaderStructureTest.php
+++ b/tests/phpunit/structure/AutoLoaderStructureTest.php
@@ -130,6 +130,11 @@ class AutoLoaderStructureTest extends MediaWikiTestCase {
$expected = $wgAutoloadLocalClasses + $wgAutoloadClasses;
$actual = [];
+ $psr4Namespaces = [];
+ foreach ( AutoLoader::getAutoloadNamespaces() as $ns => $path ) {
+ $psr4Namespaces[rtrim( $ns, '\\' ) . '\\'] = rtrim( $path, '/' );
+ }
+
$files = array_unique( $expected );
foreach ( $files as $class => $file ) {
@@ -158,6 +163,21 @@ class AutoLoaderStructureTest extends MediaWikiTestCase {
list( $classesInFile, $aliasesInFile ) = self::parseFile( $contents );
foreach ( $classesInFile as $className => $ignore ) {
+ // Skip if it's a PSR4 class
+ $parts = explode( '\\', $className );
+ for ( $i = count( $parts ) - 1; $i > 0; $i-- ) {
+ $ns = implode( '\\', array_slice( $parts, 0, $i ) ) . '\\';
+ if ( isset( $psr4Namespaces[$ns] ) ) {
+ $expectedPath = $psr4Namespaces[$ns] . '/'
+ . implode( '/', array_slice( $parts, $i ) )
+ . '.php';
+ if ( $filePath === $expectedPath ) {
+ continue 2;
+ }
+ }
+ }
+
+ // Nope, add it.
$actual[$className] = $file;
}
@@ -183,7 +203,7 @@ class AutoLoaderStructureTest extends MediaWikiTestCase {
$path = realpath( __DIR__ . '/../../..' );
$oldAutoload = file_get_contents( $path . '/autoload.php' );
$generator = new AutoloadGenerator( $path, 'local' );
- $generator->setExcludePaths( array_values( AutoLoader::getAutoloadNamespaces() ) );
+ $generator->setPsr4Namespaces( AutoLoader::getAutoloadNamespaces() );
$generator->initMediaWikiDefault();
$newAutoload = $generator->getAutoload( 'maintenance/generateLocalAutoload.php' );