Skip to content
Snippets Groups Projects
Verified Commit 7cfb8bbd authored by Alex Pott's avatar Alex Pott
Browse files

Issue #3443108 by catch: Optimize AssetResolver caching

(cherry picked from commit 181827af)
parent d8ceffab
Branches
Tags
23 merge requests!11958Issue #3490507 by alexpott, smustgrave: Fix bogus mocking in...,!11769Issue #3517987: Add option to contextual filters to encode slashes in query parameter.,!11185Issue #3477324 by andypost, alexpott: Fix usage of str_getcsv() and fgetcsv() for PHP 8.4,!10602Issue #3438769 by vinmayiswamy, antonnavi, michelle, amateescu: Sub workspace does not clear,!10301Issue #3469309 by mstrelan, smustgrave, moshe weitzman: Use one-time login...,!10187Issue #3487488 by dakwamine: ExtensionMimeTypeGuesser::guessMimeType must support file names with "0" (zero) like foo.0.zip,!9944Issue #3483353: Consider making the createCopy config action optionally fail...,!9929Issue #3445469 by pooja_sharma, smustgrave: Add additional test coverage for...,!9787Resolve issue 3479427 - bootstrap barrio issue under Windows,!9742Issue #3463908 by catch, quietone: Split OptionsFieldUiTest into two,!9526Issue #3458177 by mondrake, catch, quietone, godotislate, longwave, larowlan,...,!8738Issue #3424162 by camilledavis, dineshkumarbollu, smustgrave: Claro...,!8704Make greek characters available in ckeditor5,!8597Draft: Issue #3442259 by catch, quietone, dww: Reduce time of Migrate Upgrade tests...,!8533Issue #3446962 by kim.pepper: Remove incorrectly added...,!8517Issue #3443748 by NexusNovaz, smustgrave: Testcase creates false positive,!8325Update file Sort.php,!8095Expose document root on install,!7930Resolve #3427374 "Taxonomytid viewsargumentdefault plugin",!7445Issue #3440169: When using drupalGet(), provide an associative array for $headers,!6502Draft: Resolve #2938524 "Plach testing issue",!38582585169-10.1.x,!3226Issue #2987537: Custom menu link entity type should not declare "bundle" entity key
Pipeline #159450 passed with warnings
Pipeline: drupal

#159459

    ......@@ -125,13 +125,24 @@ public function getCssAssets(AttachedAssetsInterface $assets, $optimize, Languag
    if (!$assets->getLibraries()) {
    return [];
    }
    $libraries_to_load = $this->getLibrariesToLoad($assets);
    foreach ($libraries_to_load as $key => $library) {
    [$extension, $name] = explode('/', $library, 2);
    $definition = $this->libraryDiscovery->getLibraryByName($extension, $name);
    if (empty($definition['css'])) {
    unset($libraries_to_load[$key]);
    }
    }
    $libraries_to_load = array_values($libraries_to_load);
    if (!$libraries_to_load) {
    return [];
    }
    if (!isset($language)) {
    $language = $this->languageManager->getCurrentLanguage();
    }
    $theme_info = $this->themeManager->getActiveTheme();
    // Add the theme name to the cache key since themes may implement
    // hook_library_info_alter().
    $libraries_to_load = $this->getLibrariesToLoad($assets);
    $cid = 'css:' . $theme_info->getName() . ':' . $language->getId() . Crypt::hashBase64(serialize($libraries_to_load)) . (int) $optimize;
    if ($cached = $this->cache->get($cid)) {
    return $cached->data;
    ......@@ -149,11 +160,6 @@ public function getCssAssets(AttachedAssetsInterface $assets, $optimize, Languag
    foreach ($libraries_to_load as $key => $library) {
    [$extension, $name] = explode('/', $library, 2);
    $definition = $this->libraryDiscovery->getLibraryByName($extension, $name);
    if (empty($definition['css'])) {
    unset($libraries_to_load[$key]);
    continue;
    }
    foreach ($definition['css'] as $options) {
    $options += $default_options;
    // Copy the asset library license information to each file.
    ......@@ -227,10 +233,34 @@ public function getJsAssets(AttachedAssetsInterface $assets, $optimize, Language
    $language = $this->languageManager->getCurrentLanguage();
    }
    $theme_info = $this->themeManager->getActiveTheme();
    $libraries_to_load = $this->getLibrariesToLoad($assets);
    // Collect all libraries that contain JS assets and are in the header.
    // Also remove any libraries with no JavaScript from the libraries to
    // load.
    $header_js_libraries = [];
    foreach ($libraries_to_load as $key => $library) {
    [$extension, $name] = explode('/', $library, 2);
    $definition = $this->libraryDiscovery->getLibraryByName($extension, $name);
    if (empty($definition['js'])) {
    unset($libraries_to_load[$key]);
    continue;
    }
    if (!empty($definition['header'])) {
    $header_js_libraries[] = $library;
    }
    }
    $libraries_to_load = array_values($libraries_to_load);
    // If all the libraries to load contained only CSS, there is nothing further
    // to do here, so return early.
    if (!$libraries_to_load && !$assets->getSettings()) {
    return [[], []];
    }
    // Add the theme name to the cache key since themes may implement
    // hook_library_info_alter(). Additionally add the current language to
    // support translation of JavaScript files via hook_js_alter().
    $libraries_to_load = $this->getLibrariesToLoad($assets);
    $cid = 'js:' . $theme_info->getName() . ':' . $language->getId() . ':' . Crypt::hashBase64(serialize($libraries_to_load)) . (int) (count($assets->getSettings()) > 0) . (int) $optimize;
    if ($cached = $this->cache->get($cid)) {
    ......@@ -248,22 +278,6 @@ public function getJsAssets(AttachedAssetsInterface $assets, $optimize, Language
    'version' => NULL,
    ];
    // Collect all libraries that contain JS assets and are in the header.
    // Also remove any libraries with no JavaScript from the libraries to
    // load.
    $header_js_libraries = [];
    foreach ($libraries_to_load as $key => $library) {
    [$extension, $name] = explode('/', $library, 2);
    $definition = $this->libraryDiscovery->getLibraryByName($extension, $name);
    if (empty($definition['js'])) {
    unset($libraries_to_load[$key]);
    continue;
    }
    if (!empty($definition['header'])) {
    $header_js_libraries[] = $library;
    }
    }
    $libraries_to_load = array_values($libraries_to_load);
    // The current list of header JS libraries are only those libraries that
    // are in the header, but their dependencies must also be loaded for them
    // to function correctly, so update the list with those.
    ......
    ......@@ -111,10 +111,10 @@ public function testAnonymous() {
    $this->assertSame($expected_queries, $recorded_queries);
    $this->assertSame(34, $performance_data->getQueryCount());
    $this->assertSame(124, $performance_data->getCacheGetCount());
    $this->assertSame(46, $performance_data->getCacheSetCount());
    $this->assertSame(45, $performance_data->getCacheSetCount());
    $this->assertSame(0, $performance_data->getCacheDeleteCount());
    $this->assertSame(37, $performance_data->getCacheTagChecksumCount());
    $this->assertSame(42, $performance_data->getCacheTagIsValidCount());
    $this->assertSame(36, $performance_data->getCacheTagChecksumCount());
    $this->assertSame(43, $performance_data->getCacheTagIsValidCount());
    $this->assertSame(0, $performance_data->getCacheTagInvalidationCount());
    // Test node page.
    ......
    ......@@ -76,6 +76,10 @@ class AssetResolverTest extends UnitTestCase {
    * A mocked Japanese language object.
    */
    protected LanguageInterface $japanese;
    /**
    * An array of library definitions.
    */
    protected $libraries = [];
    /**
    * {@inheritdoc}
    ......@@ -86,6 +90,44 @@ protected function setUp(): void {
    $this->libraryDiscovery = $this->getMockBuilder('Drupal\Core\Asset\LibraryDiscovery')
    ->disableOriginalConstructor()
    ->getMock();
    $this->libraries = [
    'drupal' => [
    'version' => '1.0.0',
    'css' => [],
    'js' =>
    [
    'core/misc/drupal.js' => ['data' => 'core/misc/drupal.js', 'preprocess' => TRUE],
    ],
    'license' => '',
    ],
    'jquery' => [
    'version' => '1.0.0',
    'css' => [],
    'js' =>
    [
    'core/misc/jquery.js' => ['data' => 'core/misc/jquery.js', 'minified' => TRUE],
    ],
    'license' => '',
    ],
    'llama' => [
    'version' => '1.0.0',
    'css' =>
    [
    'core/misc/llama.css' => ['data' => 'core/misc/llama.css'],
    ],
    'js' => [],
    'license' => '',
    ],
    'piggy' => [
    'version' => '1.0.0',
    'css' =>
    [
    'core/misc/piggy.css' => ['data' => 'core/misc/piggy.css'],
    ],
    'js' => [],
    'license' => '',
    ],
    ];
    $this->libraryDependencyResolver = $this->createMock('\Drupal\Core\Asset\LibraryDependencyResolverInterface');
    $this->libraryDependencyResolver->expects($this->any())
    ->method('getLibrariesWithDependencies')
    ......@@ -124,40 +166,77 @@ protected function setUp(): void {
    /**
    * @covers ::getCssAssets
    * @dataProvider providerAttachedAssets
    * @dataProvider providerAttachedCssAssets
    */
    public function testGetCssAssets(AttachedAssetsInterface $assets_a, AttachedAssetsInterface $assets_b, $expected_cache_item_count) {
    public function testGetCssAssets(AttachedAssetsInterface $assets_a, AttachedAssetsInterface $assets_b, $expected_css_cache_item_count) {
    $this->libraryDiscovery->expects($this->any())
    ->method('getLibraryByName')
    ->willReturnOnConsecutiveCalls(
    $this->libraries['drupal'],
    $this->libraries['llama'],
    $this->libraries['llama'],
    $this->libraries['piggy'],
    $this->libraries['piggy'],
    );
    $this->assetResolver->getCssAssets($assets_a, FALSE, $this->english);
    $this->assetResolver->getCssAssets($assets_b, FALSE, $this->english);
    $this->assertCount($expected_cache_item_count, $this->cache->getAllCids());
    $this->assertCount($expected_css_cache_item_count, $this->cache->getAllCids());
    }
    public static function providerAttachedCssAssets() {
    $time = time();
    return [
    'one js only library and one css only library' => [
    (new AttachedAssets())->setAlreadyLoadedLibraries([])->setLibraries(['core/drupal']),
    (new AttachedAssets())->setAlreadyLoadedLibraries([])->setLibraries(['llama/css']),
    1,
    ],
    'two different css libraries' => [
    (new AttachedAssets())->setAlreadyLoadedLibraries([])->setLibraries(['core/drupal', 'llama/css']),
    (new AttachedAssets())->setAlreadyLoadedLibraries([])->setLibraries(['piggy/css']),
    2,
    ],
    ];
    }
    /**
    * @covers ::getJsAssets
    * @dataProvider providerAttachedAssets
    * @dataProvider providerAttachedJsAssets
    */
    public function testGetJsAssets(AttachedAssetsInterface $assets_a, AttachedAssetsInterface $assets_b, $expected_cache_item_count) {
    public function testGetJsAssets(AttachedAssetsInterface $assets_a, AttachedAssetsInterface $assets_b, $expected_js_cache_item_count, $expected_multilingual_js_cache_item_count) {
    $this->libraryDiscovery->expects($this->any())
    ->method('getLibraryByName')
    ->willReturnOnConsecutiveCalls(
    $this->libraries['drupal'],
    $this->libraries['drupal'],
    $this->libraries['jquery'],
    $this->libraries['drupal'],
    $this->libraries['drupal'],
    $this->libraries['jquery'],
    );
    $this->assetResolver->getJsAssets($assets_a, FALSE, $this->english);
    $this->assetResolver->getJsAssets($assets_b, FALSE, $this->english);
    $this->assertCount($expected_cache_item_count, $this->cache->getAllCids());
    $this->assertCount($expected_js_cache_item_count, $this->cache->getAllCids());
    $this->assetResolver->getJsAssets($assets_a, FALSE, $this->japanese);
    $this->assetResolver->getJsAssets($assets_b, FALSE, $this->japanese);
    $this->assertCount($expected_cache_item_count * 2, $this->cache->getAllCids());
    $this->assertCount($expected_multilingual_js_cache_item_count, $this->cache->getAllCids());
    }
    public static function providerAttachedAssets() {
    public static function providerAttachedJsAssets() {
    $time = time();
    return [
    'same libraries, different timestamps' => [
    (new AttachedAssets())->setAlreadyLoadedLibraries([])->setLibraries(['core/drupal'])->setSettings(['currentTime' => $time]),
    (new AttachedAssets())->setAlreadyLoadedLibraries([])->setLibraries(['core/drupal'])->setSettings(['currentTime' => $time + 100]),
    1,
    2,
    ],
    'different libraries, same timestamps' => [
    (new AttachedAssets())->setAlreadyLoadedLibraries([])->setLibraries(['core/drupal'])->setSettings(['currentTime' => $time]),
    (new AttachedAssets())->setAlreadyLoadedLibraries([])->setLibraries(['core/drupal', 'core/jquery'])->setSettings(['currentTime' => $time]),
    2,
    3,
    ],
    ];
    }
    ......
    0% Loading or .
    You are about to add 0 people to the discussion. Proceed with caution.
    Please register or to comment