jenkins-bot has submitted this change and it was merged.

Change subject: Cherry-pick I173a9820b and I7c7546ec5
......................................................................


Cherry-pick I173a9820b and I7c7546ec5

Cherry-pick of the following two changes:
* I173a9820b: resourceloader: Store relative instead of absolute paths in 
module_deps
* I7c7546ec5: resourceloader: Vary module_deps on language (in addition to skin)

Change-Id: I6651f2f34f489955a143f02b735af1929c20da77
---
M composer.json
M includes/resourceloader/ResourceLoader.php
M includes/resourceloader/ResourceLoaderFileModule.php
M includes/resourceloader/ResourceLoaderModule.php
M maintenance/tables.sql
M tests/phpunit/includes/resourceloader/ResourceLoaderModuleTest.php
6 files changed, 136 insertions(+), 49 deletions(-)

Approvals:
  Ori.livneh: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/composer.json b/composer.json
index 3c526c9..cc261cd 100644
--- a/composer.json
+++ b/composer.json
@@ -29,6 +29,7 @@
                "wikimedia/cdb": "1.3.0",
                "wikimedia/composer-merge-plugin": "1.2.1",
                "wikimedia/ip-set": "1.0.1",
+               "wikimedia/relpath": "1.0.3",
                "wikimedia/utfnormal": "1.0.3",
                "wikimedia/wrappedstring": "2.0.0",
                "zordius/lightncandy": "0.21"
diff --git a/includes/resourceloader/ResourceLoader.php 
b/includes/resourceloader/ResourceLoader.php
index d2e6c3c..afa1ee5 100644
--- a/includes/resourceloader/ResourceLoader.php
+++ b/includes/resourceloader/ResourceLoader.php
@@ -110,28 +110,27 @@
                $skin = $context->getSkin();
                $lang = $context->getLanguage();
 
-               // Get file dependency information
+               // Batched version of ResourceLoaderModule::getFileDependencies
+               $vary = "$skin|$lang";
                $res = $dbr->select( 'module_deps', array( 'md_module', 
'md_deps' ), array(
                                'md_module' => $modules,
-                               'md_skin' => $skin
+                               'md_skin' => $vary,
                        ), __METHOD__
                );
-
-               // Set modules' dependencies
+               // Prime in-object cache values for each module
                $modulesWithDeps = array();
                foreach ( $res as $row ) {
                        $module = $this->getModule( $row->md_module );
                        if ( $module ) {
-                               $module->setFileDependencies( $skin, 
FormatJson::decode( $row->md_deps, true ) );
+                               $module->setFileDependencies( $context, 
FormatJson::decode( $row->md_deps, true ) );
                                $modulesWithDeps[] = $row->md_module;
                        }
                }
-
                // Register the absence of a dependency row too
                foreach ( array_diff( $modules, $modulesWithDeps ) as $name ) {
                        $module = $this->getModule( $name );
                        if ( $module ) {
-                               $this->getModule( $name )->setFileDependencies( 
$skin, array() );
+                               $this->getModule( $name )->setFileDependencies( 
$context, array() );
                        }
                }
 
diff --git a/includes/resourceloader/ResourceLoaderFileModule.php 
b/includes/resourceloader/ResourceLoaderFileModule.php
index 26e5583..5d762d8 100644
--- a/includes/resourceloader/ResourceLoaderFileModule.php
+++ b/includes/resourceloader/ResourceLoaderFileModule.php
@@ -416,22 +416,8 @@
                        $context
                );
                // Collect referenced files
-               $this->localFileRefs = array_unique( $this->localFileRefs );
-               // If the list has been modified since last time we cached it, 
update the cache
-               try {
-                       if ( $this->localFileRefs !== 
$this->getFileDependencies( $context->getSkin() ) ) {
-                               $dbw = wfGetDB( DB_MASTER );
-                               $dbw->replace( 'module_deps',
-                                       array( array( 'md_module', 'md_skin' ) 
), array(
-                                               'md_module' => $this->getName(),
-                                               'md_skin' => 
$context->getSkin(),
-                                               'md_deps' => 
FormatJson::encode( $this->localFileRefs ),
-                                       )
-                               );
-                       }
-               } catch ( Exception $e ) {
-                       wfDebugLog( 'resourceloader', __METHOD__ . ": failed to 
update DB: $e" );
-               }
+               $this->saveFileDependencies( $context, $this->localFileRefs );
+
                return $styles;
        }
 
@@ -574,7 +560,7 @@
                }
                $files = array_map( array( $this, 'getLocalPath' ), $files );
                // File deps need to be treated separately because they're 
already prefixed
-               $files = array_merge( $files, $this->getFileDependencies( 
$context->getSkin() ) );
+               $files = array_merge( $files, $this->getFileDependencies( 
$context ) );
                // Filter out any duplicates from getFileDependencies() and 
others.
                // Most commonly introduced by compileLessFile(), which always 
includes the
                // entry point Less file we already know about.
diff --git a/includes/resourceloader/ResourceLoaderModule.php 
b/includes/resourceloader/ResourceLoaderModule.php
index 8c88ebe..5b424d2 100644
--- a/includes/resourceloader/ResourceLoaderModule.php
+++ b/includes/resourceloader/ResourceLoaderModule.php
@@ -376,32 +376,33 @@
         * Get the files this module depends on indirectly for a given skin.
         * Currently these are only image files referenced by the module's CSS.
         *
-        * @param string $skin Skin name
+        * @param ResourceLoaderContext $context
         * @return array List of files
         */
-       public function getFileDependencies( $skin ) {
+       protected function getFileDependencies( ResourceLoaderContext $context 
) {
+               $vary = $context->getSkin() . '|' . $context->getLanguage();
+
                // Try in-object cache first
-               if ( isset( $this->fileDeps[$skin] ) ) {
-                       return $this->fileDeps[$skin];
+               if ( !isset( $this->fileDeps[$vary] ) ) {
+                       $dbr = wfGetDB( DB_SLAVE );
+                       $deps = $dbr->selectField( 'module_deps',
+                               'md_deps',
+                               array(
+                                       'md_module' => $this->getName(),
+                                       'md_skin' => $vary,
+                               ),
+                               __METHOD__
+                       );
+
+                       if ( !is_null( $deps ) ) {
+                               $this->fileDeps[$vary] = 
self::expandRelativePaths(
+                                       (array)FormatJson::decode( $deps, true )
+                               );
+                       } else {
+                               $this->fileDeps[$vary] = array();
+                       }
                }
-
-               $dbr = wfGetDB( DB_SLAVE );
-               $deps = $dbr->selectField( 'module_deps',
-                       'md_deps',
-                       array(
-                               'md_module' => $this->getName(),
-                               'md_skin' => $skin,
-                       ),
-                       __METHOD__
-               );
-
-               if ( !is_null( $deps ) ) {
-                       $this->fileDeps[$skin] = (array)FormatJson::decode( 
$deps, true );
-               } else {
-                       $this->fileDeps[$skin] = array();
-               }
-
-               return $this->fileDeps[$skin];
+               return $this->fileDeps[$vary];
        }
 
        /**
@@ -410,8 +411,71 @@
         * @param string $skin Skin name
         * @param array $deps Array of file names
         */
-       public function setFileDependencies( $skin, $deps ) {
-               $this->fileDeps[$skin] = $deps;
+       public function setFileDependencies( ResourceLoaderContext $context, 
$files ) {
+               $vary = $context->getSkin() . '|' . $context->getLanguage();
+               $this->fileDeps[$vary] = $files;
+       }
+
+       /**
+        * Set the files this module depends on indirectly for a given skin.
+        *
+        * @since 1.26
+        * @param ResourceLoaderContext $context
+        * @param array $localFileRefs List of files
+        */
+       protected function saveFileDependencies( ResourceLoaderContext 
$context, $localFileRefs ) {
+               // Normalise array
+               $localFileRefs = array_values( array_unique( $localFileRefs ) );
+               sort( $localFileRefs );
+
+               try {
+                       // If the list has been modified since last time we 
cached it, update the cache
+                       if ( $localFileRefs !== $this->getFileDependencies( 
$context ) ) {
+                               $vary = $context->getSkin() . '|' . 
$context->getLanguage();
+                               $dbw = wfGetDB( DB_MASTER );
+                               $dbw->replace( 'module_deps',
+                                       array( array( 'md_module', 'md_skin' ) 
), array(
+                                               'md_module' => $this->getName(),
+                                               'md_skin' => $vary,
+                                               // Use relative paths to avoid 
ghost entries when $IP changes (T111481)
+                                               'md_deps' => 
FormatJson::encode( self::getRelativePaths( $localFileRefs ) ),
+                                       )
+                               );
+                       }
+               } catch ( Exception $e ) {
+                       wfDebugLog( 'resourceloader', __METHOD__ . ": failed to 
update DB: $e" );
+               }
+       }
+
+       /**
+        * Make file paths relative to MediaWiki directory.
+        *
+        * This is used to make file paths safe for storing in a database 
without the paths
+        * becoming stale or incorrect when MediaWiki is moved or upgraded 
(T111481).
+        *
+        * @since 1.26
+        * @param array $filePaths
+        * @return array
+        */
+       protected static function getRelativePaths( Array $filePaths ) {
+               global $IP;
+               return array_map( function ( $path ) use ( $IP ) {
+                       return RelPath\getRelativePath( $path, $IP );
+               }, $filePaths );
+       }
+
+       /**
+        * Expand directories relative to $IP.
+        *
+        * @since 1.26
+        * @param array $filePaths
+        * @return array
+        */
+       protected static function expandRelativePaths( Array $filePaths ) {
+               global $IP;
+               return array_map( function ( $path ) use ( $IP ) {
+                       return RelPath\joinPath( $IP, $path );
+               }, $filePaths );
        }
 
        /**
diff --git a/maintenance/tables.sql b/maintenance/tables.sql
index aa0c7ea..4b58b60 100644
--- a/maintenance/tables.sql
+++ b/maintenance/tables.sql
@@ -1524,7 +1524,7 @@
 CREATE TABLE /*_*/module_deps (
   -- Module name
   md_module varbinary(255) NOT NULL,
-  -- Skin name
+  -- Module context vary (includes skin and language; called "md_skin" for 
legacy reasons)
   md_skin varbinary(32) NOT NULL,
   -- JSON blob with file dependencies
   md_deps mediumblob NOT NULL
diff --git a/tests/phpunit/includes/resourceloader/ResourceLoaderModuleTest.php 
b/tests/phpunit/includes/resourceloader/ResourceLoaderModuleTest.php
index 41653fb..307e311 100644
--- a/tests/phpunit/includes/resourceloader/ResourceLoaderModuleTest.php
+++ b/tests/phpunit/includes/resourceloader/ResourceLoaderModuleTest.php
@@ -88,4 +88,41 @@
                        'Leave valid scripts as-is'
                );
        }
+
+       /**
+        * @covers ResourceLoaderModule::getRelativePaths
+        * @covers ResourceLoaderModule::expandRelativePaths
+        */
+       public function testPlaceholderize() {
+               $getRelativePaths = new ReflectionMethod( 
'ResourceLoaderModule', 'getRelativePaths' );
+               $getRelativePaths->setAccessible( true );
+               $expandRelativePaths = new ReflectionMethod( 
'ResourceLoaderModule', 'expandRelativePaths' );
+               $expandRelativePaths->setAccessible( true );
+
+               $this->setMwGlobals( array(
+                       'IP' => '/srv/example/mediawiki/core',
+               ) );
+               $raw = array(
+                               '/srv/example/mediawiki/core/resources/foo.js',
+                               
'/srv/example/mediawiki/core/extensions/Example/modules/bar.js',
+                               '/srv/example/mediawiki/skins/Example/baz.css',
+                               
'/srv/example/mediawiki/skins/Example/images/quux.png',
+               );
+               $canonical = array(
+                               'resources/foo.js',
+                               'extensions/Example/modules/bar.js',
+                               '../skins/Example/baz.css',
+                               '../skins/Example/images/quux.png',
+               );
+               $this->assertEquals(
+                       $getRelativePaths->invoke( null, $raw ),
+                       $canonical,
+                       'Insert placeholders'
+               );
+               $this->assertEquals(
+                       $expandRelativePaths->invoke( null, $canonical ),
+                       $raw,
+                       'Substitute placeholders'
+               );
+       }
 }

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

Gerrit-MessageType: merged
Gerrit-Change-Id: I6651f2f34f489955a143f02b735af1929c20da77
Gerrit-PatchSet: 2
Gerrit-Project: mediawiki/core
Gerrit-Branch: wmf/1.26wmf24
Gerrit-Owner: Ori.livneh <o...@wikimedia.org>
Gerrit-Reviewer: Daniel Friesen <dan...@nadir-seen-fire.com>
Gerrit-Reviewer: Jjanes <jeff.ja...@gmail.com>
Gerrit-Reviewer: Krinkle <krinklem...@gmail.com>
Gerrit-Reviewer: Legoktm <legoktm.wikipe...@gmail.com>
Gerrit-Reviewer: Ori.livneh <o...@wikimedia.org>
Gerrit-Reviewer: Parent5446 <tylerro...@gmail.com>
Gerrit-Reviewer: Springle <sprin...@wikimedia.org>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to