diff --git a/composer.json b/composer.json index 3e4e665acc274f09f080323ff80c446aea7ed11d..ac03753767b1af33f95d056cd28a8e7e2a35d42c 100644 --- a/composer.json +++ b/composer.json @@ -106,8 +106,8 @@ "drupal/ckeditor": "^1.0", "drupal/ckeditor_indentblock": "^1.0", "drupal/config_ignore": "^3.0", - "drupal/core-composer-scaffold": "^10", - "drupal/core-recommended": "^10", + "drupal/core-composer-scaffold": "^10.1", + "drupal/core-recommended": "^10.1", "drupal/crop": "2.3", "drupal/ctools": "^4.0", "drupal/decorative_image_widget": "^1.0", diff --git a/composer.lock b/composer.lock index 749218a732c441c87e28a087adb760910f74bb91..372dffe7c717ac9902bfb0fa6d736c67d445e940 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "83bb2cb6d9a59f12abaeb091ee6e9204", + "content-hash": "2a02d0e2e8242ba7416066e2ff6e0150", "packages": [ { "name": "asm89/stack-cors", @@ -2192,16 +2192,16 @@ }, { "name": "drupal/core", - "version": "10.1.5", + "version": "10.1.6", "source": { "type": "git", "url": "https://github.com/drupal/core.git", - "reference": "1272c35d547e844e7ebf3fe5513542291cda8cec" + "reference": "33695caf467e3e1e8c75d42215df57bee31be9ec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/drupal/core/zipball/1272c35d547e844e7ebf3fe5513542291cda8cec", - "reference": "1272c35d547e844e7ebf3fe5513542291cda8cec", + "url": "https://api.github.com/repos/drupal/core/zipball/33695caf467e3e1e8c75d42215df57bee31be9ec", + "reference": "33695caf467e3e1e8c75d42215df57bee31be9ec", "shasum": "" }, "require": { @@ -2346,13 +2346,13 @@ ], "description": "Drupal is an open source content management platform powering millions of websites and applications.", "support": { - "source": "https://github.com/drupal/core/tree/10.1.5" + "source": "https://github.com/drupal/core/tree/10.1.6" }, - "time": "2023-10-04T21:37:59+00:00" + "time": "2023-11-01T11:59:20+00:00" }, { "name": "drupal/core-composer-scaffold", - "version": "10.1.5", + "version": "10.1.6", "source": { "type": "git", "url": "https://github.com/drupal/core-composer-scaffold.git", @@ -2396,22 +2396,22 @@ "drupal" ], "support": { - "source": "https://github.com/drupal/core-composer-scaffold/tree/10.1.5" + "source": "https://github.com/drupal/core-composer-scaffold/tree/10.1.6" }, "time": "2023-04-30T16:15:32+00:00" }, { "name": "drupal/core-recommended", - "version": "10.1.5", + "version": "10.1.6", "source": { "type": "git", "url": "https://github.com/drupal/core-recommended.git", - "reference": "2c5cf420ddb06f3e9b624d168b724ca1c7c326e2" + "reference": "13f5968854fe8bc02e659d8a4facc04a1a576ce5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/drupal/core-recommended/zipball/2c5cf420ddb06f3e9b624d168b724ca1c7c326e2", - "reference": "2c5cf420ddb06f3e9b624d168b724ca1c7c326e2", + "url": "https://api.github.com/repos/drupal/core-recommended/zipball/13f5968854fe8bc02e659d8a4facc04a1a576ce5", + "reference": "13f5968854fe8bc02e659d8a4facc04a1a576ce5", "shasum": "" }, "require": { @@ -2420,7 +2420,7 @@ "doctrine/annotations": "~1.14.3", "doctrine/deprecations": "~v1.1.1", "doctrine/lexer": "~2.1.0", - "drupal/core": "10.1.5", + "drupal/core": "10.1.6", "egulias/email-validator": "~4.0.1", "guzzlehttp/guzzle": "~7.7.0", "guzzlehttp/psr7": "~2.5.0", @@ -2477,9 +2477,9 @@ ], "description": "Core and its dependencies with known-compatible minor versions. Require this project INSTEAD OF drupal/core.", "support": { - "source": "https://github.com/drupal/core-recommended/tree/10.1.5" + "source": "https://github.com/drupal/core-recommended/tree/10.1.6" }, - "time": "2023-10-04T21:37:59+00:00" + "time": "2023-11-01T11:59:20+00:00" }, { "name": "drupal/crop", diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index a728fa13cf91104fc2fde16d34accc2592597bb2..610b100d50501a113f8070c27ea5db958f60fdf4 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -2295,17 +2295,17 @@ }, { "name": "drupal/core", - "version": "10.1.5", - "version_normalized": "10.1.5.0", + "version": "10.1.6", + "version_normalized": "10.1.6.0", "source": { "type": "git", "url": "https://github.com/drupal/core.git", - "reference": "1272c35d547e844e7ebf3fe5513542291cda8cec" + "reference": "33695caf467e3e1e8c75d42215df57bee31be9ec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/drupal/core/zipball/1272c35d547e844e7ebf3fe5513542291cda8cec", - "reference": "1272c35d547e844e7ebf3fe5513542291cda8cec", + "url": "https://api.github.com/repos/drupal/core/zipball/33695caf467e3e1e8c75d42215df57bee31be9ec", + "reference": "33695caf467e3e1e8c75d42215df57bee31be9ec", "shasum": "" }, "require": { @@ -2382,7 +2382,7 @@ "suggest": { "ext-zip": "Needed to extend the plugin.manager.archiver service capability with the handling of files in the ZIP format." }, - "time": "2023-10-04T21:37:59+00:00", + "time": "2023-11-01T11:59:20+00:00", "type": "drupal-core", "extra": { "drupal-scaffold": { @@ -2455,14 +2455,14 @@ ], "description": "Drupal is an open source content management platform powering millions of websites and applications.", "support": { - "source": "https://github.com/drupal/core/tree/10.1.5" + "source": "https://github.com/drupal/core/tree/10.1.6" }, "install-path": "../../web/core" }, { "name": "drupal/core-composer-scaffold", - "version": "10.1.5", - "version_normalized": "10.1.5.0", + "version": "10.1.6", + "version_normalized": "10.1.6.0", "source": { "type": "git", "url": "https://github.com/drupal/core-composer-scaffold.git", @@ -2508,23 +2508,23 @@ "drupal" ], "support": { - "source": "https://github.com/drupal/core-composer-scaffold/tree/10.1.5" + "source": "https://github.com/drupal/core-composer-scaffold/tree/10.1.6" }, "install-path": "../drupal/core-composer-scaffold" }, { "name": "drupal/core-recommended", - "version": "10.1.5", - "version_normalized": "10.1.5.0", + "version": "10.1.6", + "version_normalized": "10.1.6.0", "source": { "type": "git", "url": "https://github.com/drupal/core-recommended.git", - "reference": "2c5cf420ddb06f3e9b624d168b724ca1c7c326e2" + "reference": "13f5968854fe8bc02e659d8a4facc04a1a576ce5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/drupal/core-recommended/zipball/2c5cf420ddb06f3e9b624d168b724ca1c7c326e2", - "reference": "2c5cf420ddb06f3e9b624d168b724ca1c7c326e2", + "url": "https://api.github.com/repos/drupal/core-recommended/zipball/13f5968854fe8bc02e659d8a4facc04a1a576ce5", + "reference": "13f5968854fe8bc02e659d8a4facc04a1a576ce5", "shasum": "" }, "require": { @@ -2533,7 +2533,7 @@ "doctrine/annotations": "~1.14.3", "doctrine/deprecations": "~v1.1.1", "doctrine/lexer": "~2.1.0", - "drupal/core": "10.1.5", + "drupal/core": "10.1.6", "egulias/email-validator": "~4.0.1", "guzzlehttp/guzzle": "~7.7.0", "guzzlehttp/psr7": "~2.5.0", @@ -2583,7 +2583,7 @@ "conflict": { "webflo/drupal-core-strict": "*" }, - "time": "2023-10-04T21:37:59+00:00", + "time": "2023-11-01T11:59:20+00:00", "type": "metapackage", "notification-url": "https://packagist.org/downloads/", "license": [ @@ -2591,7 +2591,7 @@ ], "description": "Core and its dependencies with known-compatible minor versions. Require this project INSTEAD OF drupal/core.", "support": { - "source": "https://github.com/drupal/core-recommended/tree/10.1.5" + "source": "https://github.com/drupal/core-recommended/tree/10.1.6" }, "install-path": null }, diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php index d0a63856e6447d391eb1b15523c44dcb65d5785f..ce3011d089f1e05ae7f82ac5b887397336a5b463 100644 --- a/vendor/composer/installed.php +++ b/vendor/composer/installed.php @@ -3,7 +3,7 @@ 'name' => 'osu-asc-webservices/d8-upstream', 'pretty_version' => 'dev-master', 'version' => 'dev-master', - 'reference' => 'ee2cb1c3540cb7e67140dd667e6828b9b59e5c9a', + 'reference' => '6d88cd620aad5c039922728fc2c186268a052911', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -359,9 +359,9 @@ 'dev_requirement' => false, ), 'drupal/core' => array( - 'pretty_version' => '10.1.5', - 'version' => '10.1.5.0', - 'reference' => '1272c35d547e844e7ebf3fe5513542291cda8cec', + 'pretty_version' => '10.1.6', + 'version' => '10.1.6.0', + 'reference' => '33695caf467e3e1e8c75d42215df57bee31be9ec', 'type' => 'drupal-core', 'install_path' => __DIR__ . '/../../web/core', 'aliases' => array(), @@ -370,24 +370,24 @@ 'drupal/core-annotation' => array( 'dev_requirement' => false, 'replaced' => array( - 0 => '10.1.5', + 0 => '10.1.6', ), ), 'drupal/core-assertion' => array( 'dev_requirement' => false, 'replaced' => array( - 0 => '10.1.5', + 0 => '10.1.6', ), ), 'drupal/core-class-finder' => array( 'dev_requirement' => false, 'replaced' => array( - 0 => '10.1.5', + 0 => '10.1.6', ), ), 'drupal/core-composer-scaffold' => array( - 'pretty_version' => '10.1.5', - 'version' => '10.1.5.0', + 'pretty_version' => '10.1.6', + 'version' => '10.1.6.0', 'reference' => '1ccd7db5ff8a5425b5bbba9b9a05e366363c0a51', 'type' => 'composer-plugin', 'install_path' => __DIR__ . '/../drupal/core-composer-scaffold', @@ -397,97 +397,97 @@ 'drupal/core-datetime' => array( 'dev_requirement' => false, 'replaced' => array( - 0 => '10.1.5', + 0 => '10.1.6', ), ), 'drupal/core-dependency-injection' => array( 'dev_requirement' => false, 'replaced' => array( - 0 => '10.1.5', + 0 => '10.1.6', ), ), 'drupal/core-diff' => array( 'dev_requirement' => false, 'replaced' => array( - 0 => '10.1.5', + 0 => '10.1.6', ), ), 'drupal/core-discovery' => array( 'dev_requirement' => false, 'replaced' => array( - 0 => '10.1.5', + 0 => '10.1.6', ), ), 'drupal/core-event-dispatcher' => array( 'dev_requirement' => false, 'replaced' => array( - 0 => '10.1.5', + 0 => '10.1.6', ), ), 'drupal/core-file-cache' => array( 'dev_requirement' => false, 'replaced' => array( - 0 => '10.1.5', + 0 => '10.1.6', ), ), 'drupal/core-file-security' => array( 'dev_requirement' => false, 'replaced' => array( - 0 => '10.1.5', + 0 => '10.1.6', ), ), 'drupal/core-filesystem' => array( 'dev_requirement' => false, 'replaced' => array( - 0 => '10.1.5', + 0 => '10.1.6', ), ), 'drupal/core-front-matter' => array( 'dev_requirement' => false, 'replaced' => array( - 0 => '10.1.5', + 0 => '10.1.6', ), ), 'drupal/core-gettext' => array( 'dev_requirement' => false, 'replaced' => array( - 0 => '10.1.5', + 0 => '10.1.6', ), ), 'drupal/core-graph' => array( 'dev_requirement' => false, 'replaced' => array( - 0 => '10.1.5', + 0 => '10.1.6', ), ), 'drupal/core-http-foundation' => array( 'dev_requirement' => false, 'replaced' => array( - 0 => '10.1.5', + 0 => '10.1.6', ), ), 'drupal/core-php-storage' => array( 'dev_requirement' => false, 'replaced' => array( - 0 => '10.1.5', + 0 => '10.1.6', ), ), 'drupal/core-plugin' => array( 'dev_requirement' => false, 'replaced' => array( - 0 => '10.1.5', + 0 => '10.1.6', ), ), 'drupal/core-proxy-builder' => array( 'dev_requirement' => false, 'replaced' => array( - 0 => '10.1.5', + 0 => '10.1.6', ), ), 'drupal/core-recommended' => array( - 'pretty_version' => '10.1.5', - 'version' => '10.1.5.0', - 'reference' => '2c5cf420ddb06f3e9b624d168b724ca1c7c326e2', + 'pretty_version' => '10.1.6', + 'version' => '10.1.6.0', + 'reference' => '13f5968854fe8bc02e659d8a4facc04a1a576ce5', 'type' => 'metapackage', 'install_path' => NULL, 'aliases' => array(), @@ -496,37 +496,37 @@ 'drupal/core-render' => array( 'dev_requirement' => false, 'replaced' => array( - 0 => '10.1.5', + 0 => '10.1.6', ), ), 'drupal/core-serialization' => array( 'dev_requirement' => false, 'replaced' => array( - 0 => '10.1.5', + 0 => '10.1.6', ), ), 'drupal/core-transliteration' => array( 'dev_requirement' => false, 'replaced' => array( - 0 => '10.1.5', + 0 => '10.1.6', ), ), 'drupal/core-utility' => array( 'dev_requirement' => false, 'replaced' => array( - 0 => '10.1.5', + 0 => '10.1.6', ), ), 'drupal/core-uuid' => array( 'dev_requirement' => false, 'replaced' => array( - 0 => '10.1.5', + 0 => '10.1.6', ), ), 'drupal/core-version' => array( 'dev_requirement' => false, 'replaced' => array( - 0 => '10.1.5', + 0 => '10.1.6', ), ), 'drupal/crop' => array( @@ -1393,7 +1393,7 @@ 'osu-asc-webservices/d8-upstream' => array( 'pretty_version' => 'dev-master', 'version' => 'dev-master', - 'reference' => 'ee2cb1c3540cb7e67140dd667e6828b9b59e5c9a', + 'reference' => '6d88cd620aad5c039922728fc2c186268a052911', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), diff --git a/web/core/assets/scaffold/files/modules.README.txt b/web/core/assets/scaffold/files/modules.README.txt index 529c31b2ba23f2281d9276e05dfb48ecda265395..249e8177ac230814f80fd44ea0acfadf2e6a2bb1 100644 --- a/web/core/assets/scaffold/files/modules.README.txt +++ b/web/core/assets/scaffold/files/modules.README.txt @@ -38,5 +38,5 @@ pattern may be used to restrict modules to a specific site instance. MORE INFORMATION ---------------- -Refer to the “Developing for Drupal” section of the README.txt in the Drupal +Refer to the “Developing for Drupal” section of the README.md in the Drupal root directory for further information on extending Drupal with custom modules. diff --git a/web/core/assets/scaffold/files/profiles.README.txt b/web/core/assets/scaffold/files/profiles.README.txt index b0f0c0bac99138cd636c0e865eaa2354cc6531a3..6d11a51114c4598e66501df0864ace82c2576950 100644 --- a/web/core/assets/scaffold/files/profiles.README.txt +++ b/web/core/assets/scaffold/files/profiles.README.txt @@ -24,5 +24,5 @@ available to all sites during their initial site installation. MORE INFORMATION ---------------- -Refer to the "Installation profiles" section of the README.txt in the Drupal +Refer to the "Installation profiles" section of the README.md in the Drupal root directory for further information on extending Drupal with custom profiles. diff --git a/web/core/assets/scaffold/files/themes.README.txt b/web/core/assets/scaffold/files/themes.README.txt index 039aaaf83a06ad33744027fa4ec95e8cc852e765..1e00ead6d85b3624bb7f3c5280c5a551c6ef84b7 100644 --- a/web/core/assets/scaffold/files/themes.README.txt +++ b/web/core/assets/scaffold/files/themes.README.txt @@ -26,6 +26,6 @@ pattern may be used to restrict themes to a specific site instance. MORE INFORMATION ----------------- -Refer to the "Appearance" section of the README.txt in the Drupal root directory +Refer to the "Appearance" section of the README.md in the Drupal root directory for further information on customizing the appearance of Drupal with custom themes. diff --git a/web/core/lib/Drupal.php b/web/core/lib/Drupal.php index dd4bd657f55c8aa1f466498d7f3531186c95b6de..0dfbd6316d62bf70c9db379879176db6280e11b0 100644 --- a/web/core/lib/Drupal.php +++ b/web/core/lib/Drupal.php @@ -75,7 +75,7 @@ class Drupal { /** * The current system version. */ - const VERSION = '10.1.5'; + const VERSION = '10.1.6'; /** * Core API compatibility. diff --git a/web/core/lib/Drupal/Core/Asset/AssetResolver.php b/web/core/lib/Drupal/Core/Asset/AssetResolver.php index 04a5186368b3e3c678491437d6b545a8a73b4896..e92102d4e385370350033ddc646ccf2c00d021ea 100644 --- a/web/core/lib/Drupal/Core/Asset/AssetResolver.php +++ b/web/core/lib/Drupal/Core/Asset/AssetResolver.php @@ -170,11 +170,13 @@ public function getCssAssets(AttachedAssetsInterface $assets, $optimize, Languag $this->moduleHandler->alter('css', $css, $assets, $language); $this->themeManager->alter('css', $css, $assets, $language); - // Sort CSS items, so that they appear in the correct order. - uasort($css, [static::class, 'sort']); + if (!empty($css)) { + // Sort CSS items, so that they appear in the correct order. + uasort($css, [static::class, 'sort']); - if ($optimize) { - $css = \Drupal::service('asset.css.collection_optimizer')->optimize($css, $libraries_to_load, $language); + if ($optimize) { + $css = \Drupal::service('asset.css.collection_optimizer')->optimize($css, $libraries_to_load, $language); + } } $this->cache->set($cid, $css, CacheBackendInterface::CACHE_PERMANENT, ['library_info']); diff --git a/web/core/lib/Drupal/Core/Condition/ConditionPluginCollection.php b/web/core/lib/Drupal/Core/Condition/ConditionPluginCollection.php index ec15926c65ad296188b681dd7dc566dc4412f713..4717cd997afd409239eaa402b42149d09698c7a0 100644 --- a/web/core/lib/Drupal/Core/Condition/ConditionPluginCollection.php +++ b/web/core/lib/Drupal/Core/Condition/ConditionPluginCollection.php @@ -44,7 +44,12 @@ public function getConfiguration() { unset($instance_config['context_mapping']); ksort($default_config); ksort($instance_config); - if ($default_config === $instance_config) { + // With PHP 8 type juggling, there should not be an issue using equal + // operator instead of identical operator. Allowing looser comparison here + // will prevent configuration from being erroneously exported when values + // are updated via form elements that return values of the wrong type, for + // example, '0'/'1' vs FALSE/TRUE. + if ($default_config == $instance_config) { unset($configuration[$instance_id]); } } diff --git a/web/core/lib/Drupal/Core/Config/ConfigBase.php b/web/core/lib/Drupal/Core/Config/ConfigBase.php index e4d298511599eeabfab91f6c8c71dccf964f7708..744af363b157b633f7063004207b4f5aa14c499d 100644 --- a/web/core/lib/Drupal/Core/Config/ConfigBase.php +++ b/web/core/lib/Drupal/Core/Config/ConfigBase.php @@ -200,8 +200,6 @@ public function set($key, $value) { * @param array $data * Configuration array structure. * - * @return null - * * @throws \Drupal\Core\Config\ConfigValueException * If any key in $data in any depth contains a dot. */ diff --git a/web/core/lib/Drupal/Core/Config/ConfigImporter.php b/web/core/lib/Drupal/Core/Config/ConfigImporter.php index b6c6c7f9aa1b43d8d32eb8f4ba18d10dc4e2aaf7..3be2b32273e520803ebce610db70f4b62423f150 100644 --- a/web/core/lib/Drupal/Core/Config/ConfigImporter.php +++ b/web/core/lib/Drupal/Core/Config/ConfigImporter.php @@ -996,6 +996,9 @@ protected function importConfig($collection, $op, $name) { $config->delete(); } else { + if ($old_data = $this->storageComparer->getTargetStorage($collection)->read($name)) { + $config->initWithData($old_data); + } $data = $this->storageComparer->getSourceStorage($collection)->read($name); $config->setData($data ? $data : []); $config->save(); diff --git a/web/core/lib/Drupal/Core/Config/ImmutableConfig.php b/web/core/lib/Drupal/Core/Config/ImmutableConfig.php index b0d4e8d8dcd6bcd9199b34d057e13133cdeab321..806c6b98cd6d0bbaac1083426280f62d4625a337 100644 --- a/web/core/lib/Drupal/Core/Config/ImmutableConfig.php +++ b/web/core/lib/Drupal/Core/Config/ImmutableConfig.php @@ -42,10 +42,7 @@ public function save($has_trusted_data = FALSE) { } /** - * Deletes the configuration object. - * - * @return \Drupal\Core\Config\Config - * The configuration object. + * {@inheritdoc} */ public function delete() { throw new ImmutableConfigException("Can not delete immutable configuration {$this->getName()}. Use \\Drupal\\Core\\Config\\ConfigFactoryInterface::getEditable() to retrieve a mutable configuration object"); diff --git a/web/core/lib/Drupal/Core/Config/StorableConfigBase.php b/web/core/lib/Drupal/Core/Config/StorableConfigBase.php index f3202a764441f6e0f23af3c445b40bccea454f45..ae521919d00a507200e9de28a39371907ef1a622 100644 --- a/web/core/lib/Drupal/Core/Config/StorableConfigBase.php +++ b/web/core/lib/Drupal/Core/Config/StorableConfigBase.php @@ -145,8 +145,6 @@ protected function getSchemaWrapper() { * @param mixed $value * Value to associate with the key. * - * @return null - * * @throws \Drupal\Core\Config\UnsupportedDataTypeConfigException * If the value is unsupported in configuration. */ diff --git a/web/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php b/web/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php index 48adc9772a3d54b97411fc527a290c2f854bffae..b2eb730adadf39860ddbc0a0953fc7b8f6465327 100644 --- a/web/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php +++ b/web/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php @@ -1455,9 +1455,6 @@ protected function addTableDefaults(&$schema) { * The entity type. * @param array $schema * The table schema, passed by reference. - * - * @return array - * A partial schema array for the base table. */ protected function processDataTable(ContentEntityTypeInterface $entity_type, array &$schema) { // Marking the respective fields as NOT NULL makes the indexes more @@ -1470,11 +1467,8 @@ protected function processDataTable(ContentEntityTypeInterface $entity_type, arr * * @param \Drupal\Core\Entity\ContentEntityTypeInterface $entity_type * The entity type. - * @param array $schema + * @param array &$schema * The table schema, passed by reference. - * - * @return array - * A partial schema array for the base table. */ protected function processRevisionDataTable(ContentEntityTypeInterface $entity_type, array &$schema) { // Marking the respective fields as NOT NULL makes the indexes more diff --git a/web/core/lib/Drupal/Core/EventSubscriber/ExceptionLoggingSubscriber.php b/web/core/lib/Drupal/Core/EventSubscriber/ExceptionLoggingSubscriber.php index 526cb42d69ae6f8d5023281626ba0034f5ed2596..8adc67a6c969b4e512e3e29b8d25bd77ef81c572 100644 --- a/web/core/lib/Drupal/Core/EventSubscriber/ExceptionLoggingSubscriber.php +++ b/web/core/lib/Drupal/Core/EventSubscriber/ExceptionLoggingSubscriber.php @@ -75,6 +75,22 @@ public function onError(ExceptionEvent $event) { } } + /** + * Log 4xx errors that are not 403 or 404. + * + * @param \Symfony\Component\HttpKernel\Event\ExceptionEvent $event + * The event to process. + */ + public function onClientError(ExceptionEvent $event) { + $exception = $event->getThrowable(); + $error = Error::decodeException($exception); + $error += [ + 'status_code' => $exception->getStatusCode(), + ]; + $this->logger->get('client error') + ->log($error['severity_level'], Error::DEFAULT_ERROR_MESSAGE, $error); + } + /** * Log all exceptions. * @@ -88,10 +104,14 @@ public function onException(ExceptionEvent $event) { // Treat any non-HTTP exception as if it were one, so we log it the same. if ($exception instanceof HttpExceptionInterface) { - $possible_method = 'on' . $exception->getStatusCode(); + $status_code = $exception->getStatusCode(); + $possible_method = 'on' . $status_code; if (method_exists($this, $possible_method)) { $method = $possible_method; } + elseif ($status_code >= 400 && $status_code < 500) { + $method = 'onClientError'; + } } $this->$method($event); diff --git a/web/core/lib/Drupal/Core/Field/Entity/BaseFieldOverride.php b/web/core/lib/Drupal/Core/Field/Entity/BaseFieldOverride.php index 54c08284f4e1ec92e5f0c287a400205dd606d60b..2fb62c010762a1bac91cc85f81b5776c1faf1343 100644 --- a/web/core/lib/Drupal/Core/Field/Entity/BaseFieldOverride.php +++ b/web/core/lib/Drupal/Core/Field/Entity/BaseFieldOverride.php @@ -145,6 +145,13 @@ public function isComputed() { return $this->getBaseFieldDefinition()->isComputed(); } + /** + * {@inheritdoc} + */ + public function isInternal(): bool { + return $this->getBaseFieldDefinition()->isInternal(); + } + /** * {@inheritdoc} */ diff --git a/web/core/lib/Drupal/Core/Field/FieldStorageDefinitionInterface.php b/web/core/lib/Drupal/Core/Field/FieldStorageDefinitionInterface.php index d75eb2295b2f4ba43f7e11dd149f6da31684785d..ead716800865c4d101c951eee233a00fca827d6a 100644 --- a/web/core/lib/Drupal/Core/Field/FieldStorageDefinitionInterface.php +++ b/web/core/lib/Drupal/Core/Field/FieldStorageDefinitionInterface.php @@ -74,7 +74,7 @@ public function getSettings(); * The setting name. * * @return mixed - * The setting value. + * The setting value or NULL if the setting name doesn't exist. */ public function getSetting($setting_name); diff --git a/web/core/lib/Drupal/Core/Form/EnforcedResponseException.php b/web/core/lib/Drupal/Core/Form/EnforcedResponseException.php index 73649845eb467558e39688acf3278c79bf1e5f3b..ca3b8b8688e14f6687e446e9fd2122e3b4b571c3 100644 --- a/web/core/lib/Drupal/Core/Form/EnforcedResponseException.php +++ b/web/core/lib/Drupal/Core/Form/EnforcedResponseException.php @@ -37,7 +37,7 @@ public function __construct(Response $response, $message = "", $code = 0, \Excep /** * Return the response to be enforced. * - * @returns \Symfony\Component\HttpFoundation\Response $response + * @return \Symfony\Component\HttpFoundation\Response * The response to be enforced. */ public function getResponse() { diff --git a/web/core/lib/Drupal/Core/Menu/menu.api.php b/web/core/lib/Drupal/Core/Menu/menu.api.php index 10a3793b46c0467445facb6d2274e2b1fa121c56..4d775978c22590538f6c6b5a0642b4ca5fd732e4 100644 --- a/web/core/lib/Drupal/Core/Menu/menu.api.php +++ b/web/core/lib/Drupal/Core/Menu/menu.api.php @@ -221,11 +221,8 @@ /** * Alters all the menu links discovered by the menu link plugin manager. * - * @param array $links - * The link definitions to be altered. - * - * @return array - * An array of discovered menu links. Each link has a key that is the machine + * @param array &$links + * The link definitions to be altered. Each link has a key that is the machine * name, which must be unique. By default, use the route name as the * machine name. In cases where multiple links use the same route name, such * as two links to the same page in different menus, or two links using the diff --git a/web/core/lib/Drupal/Core/Password/PasswordInterface.php b/web/core/lib/Drupal/Core/Password/PasswordInterface.php index c514b840feb5c57ac3b664a47cab037e915ee83f..84aa11f3c59dee6b92edbfb306be55c90baab40e 100644 --- a/web/core/lib/Drupal/Core/Password/PasswordInterface.php +++ b/web/core/lib/Drupal/Core/Password/PasswordInterface.php @@ -27,8 +27,8 @@ public function hash(#[\SensitiveParameter] $password); * Check whether a plain text password matches a hashed password. * * @param string $password - * A plain-text password - * @param string $hash + * A plain-text password. + * @param string|null $hash * A hashed password. * * @return bool @@ -46,7 +46,7 @@ public function check(#[\SensitiveParameter] $password, #[\SensitiveParameter] $ * This method returns TRUE if the password was hashed with an older * algorithm. * - * @param string $hash + * @param string|null $hash * The hash to be checked. * * @return bool diff --git a/web/core/lib/Drupal/Core/Password/PhpPassword.php b/web/core/lib/Drupal/Core/Password/PhpPassword.php index f16eeb200cab3e254fc09d758ce1c914ee2674f9..c199de8fd8b7af65ebc5687c889dbc96e57e1322 100644 --- a/web/core/lib/Drupal/Core/Password/PhpPassword.php +++ b/web/core/lib/Drupal/Core/Password/PhpPassword.php @@ -45,6 +45,10 @@ public function check(#[\SensitiveParameter] $password, #[\SensitiveParameter] $ if (strlen($password) > static::PASSWORD_MAX_LENGTH) { return FALSE; } + // Newly created accounts may have empty passwords. + if ($hash === NULL || $hash === '') { + return FALSE; + } return password_verify($password, $hash); } diff --git a/web/core/lib/Drupal/Core/Password/PhpassHashedPasswordBase.php b/web/core/lib/Drupal/Core/Password/PhpassHashedPasswordBase.php index 052c2be81ee3ed86be160356609000c64eb23349..7be8e393801f79071cf74430b636b401fc417952 100644 --- a/web/core/lib/Drupal/Core/Password/PhpassHashedPasswordBase.php +++ b/web/core/lib/Drupal/Core/Password/PhpassHashedPasswordBase.php @@ -242,6 +242,10 @@ public function hash(#[\SensitiveParameter] $password) { * {@inheritdoc} */ public function check(#[\SensitiveParameter] $password, #[\SensitiveParameter] $hash) { + // Newly created accounts may have empty passwords. + if ($hash === NULL || $hash === '') { + return FALSE; + } if (substr($hash, 0, 2) == 'U$') { // This may be an updated password from user_update_7000(). Such hashes // have 'U' added as the first character and need an extra md5() (see the diff --git a/web/core/lib/Drupal/Core/Queue/QueueInterface.php b/web/core/lib/Drupal/Core/Queue/QueueInterface.php index 8b9ff654c068bed674ed92d54e7fc2f2bcfd1118..5305a26be02a3cc94565f5a5e89d2274f2bec92f 100644 --- a/web/core/lib/Drupal/Core/Queue/QueueInterface.php +++ b/web/core/lib/Drupal/Core/Queue/QueueInterface.php @@ -18,7 +18,7 @@ interface QueueInterface { * @param $data * Arbitrary data to be associated with the new task in the queue. * - * @return bool|int|string + * @return false|int|string * A unique ID if the item was successfully created and was (best effort) * added to the queue, otherwise FALSE. We don't guarantee the item was * committed to disk etc, but as far as we know, the item is now in the diff --git a/web/core/lib/Drupal/Core/Render/MainContent/DialogRenderer.php b/web/core/lib/Drupal/Core/Render/MainContent/DialogRenderer.php index 3438d0fd27c792e66b7d2d4a94b65adcf477ad77..6468e02d17e71aa1bbe3015e2c109bded32ae49d 100644 --- a/web/core/lib/Drupal/Core/Render/MainContent/DialogRenderer.php +++ b/web/core/lib/Drupal/Core/Render/MainContent/DialogRenderer.php @@ -61,7 +61,7 @@ public function renderResponse(array $main_content, Request $request, RouteMatch $title = $main_content['#title'] ?? $this->titleResolver->getTitle($request, $route_match->getRouteObject()); // Determine the dialog options and the target for the OpenDialogCommand. - $options = $request->request->all('dialogOptions'); + $options = $this->getDialogOptions($request); $target = $this->determineTargetSelector($options, $route_match); $response->addCommand(new OpenDialogCommand($target, $title, $content, $options)); @@ -100,4 +100,20 @@ protected function determineTargetSelector(array &$options, RouteMatchInterface return $target; } + /** + * Returns the dialog options from request. + * + * @param \Symfony\Component\HttpFoundation\Request $request + * The HTTP request. + * + * @return array + * The dialog options used for OpenDialogCommand. + */ + protected function getDialogOptions(Request $request): array { + if ($request->getMethod() === 'GET') { + return $request->query->all('dialogOptions'); + } + return $request->request->all('dialogOptions'); + } + } diff --git a/web/core/lib/Drupal/Core/Render/MainContent/ModalRenderer.php b/web/core/lib/Drupal/Core/Render/MainContent/ModalRenderer.php index df80b7dce00ccc5237f8264a09b452ce86587900..6e344ce6397abede1d77932d7bd32e9ec61bb080 100644 --- a/web/core/lib/Drupal/Core/Render/MainContent/ModalRenderer.php +++ b/web/core/lib/Drupal/Core/Render/MainContent/ModalRenderer.php @@ -29,9 +29,8 @@ public function renderResponse(array $main_content, Request $request, RouteMatch // If the main content doesn't provide a title, use the title resolver. $title = $main_content['#title'] ?? $this->titleResolver->getTitle($request, $route_match->getRouteObject()); - // Determine the title: use the title provided by the main content if any, - // otherwise get it from the routing information. - $options = $request->request->all('dialogOptions'); + // Determine the dialog options for the OpenDialogCommand. + $options = $this->getDialogOptions($request); $response->addCommand(new OpenModalDialogCommand($title, $content, $options)); return $response; diff --git a/web/core/lib/Drupal/Core/Render/Renderer.php b/web/core/lib/Drupal/Core/Render/Renderer.php index 5d794f4517876ebd370cebf3bb027a658a1974f1..8097d84d7479daaa5c242a25bc707c3c0e537461 100644 --- a/web/core/lib/Drupal/Core/Render/Renderer.php +++ b/web/core/lib/Drupal/Core/Render/Renderer.php @@ -641,7 +641,7 @@ protected function setCurrentRenderContext(RenderContext $context = NULL) { * bubbleable metadata associated with the markup that replaced the * placeholders. * - * @returns bool + * @return bool * Whether placeholders were replaced. * * @see \Drupal\Core\Render\Renderer::renderPlaceholder() diff --git a/web/core/lib/Drupal/Core/Render/theme.api.php b/web/core/lib/Drupal/Core/Render/theme.api.php index aba99058bca30e074062ac25765a5b255d2b4c91..36f1c096987366221c962e51395be162b9dd0502 100644 --- a/web/core/lib/Drupal/Core/Render/theme.api.php +++ b/web/core/lib/Drupal/Core/Render/theme.api.php @@ -688,9 +688,6 @@ function hook_theme_suggestions_HOOK(array $variables) { * (in this case 'node__article') is available in * $variables['theme_hook_original']. * - * @return array - * An array of theme suggestions. - * * @see hook_theme_suggestions_HOOK_alter() */ function hook_theme_suggestions_alter(array &$suggestions, array $variables, $hook) { diff --git a/web/core/lib/Drupal/Core/Session/SessionConfiguration.php b/web/core/lib/Drupal/Core/Session/SessionConfiguration.php index 2687ac94b614dcd916f5c89b3797cf636b37fc9b..d1e5de1d934e40f9760c84d16def656cccab1d79 100644 --- a/web/core/lib/Drupal/Core/Session/SessionConfiguration.php +++ b/web/core/lib/Drupal/Core/Session/SessionConfiguration.php @@ -82,7 +82,7 @@ protected function getName(Request $request) { * @param \Symfony\Component\HttpFoundation\Request $request * The request. * - * @returns string + * @return string * The session name without the prefix (SESS/SSESS). */ protected function getUnprefixedName(Request $request) { @@ -118,7 +118,7 @@ protected function getUnprefixedName(Request $request) { * @param \Symfony\Component\HttpFoundation\Request $request * The request. * - * @returns string|null + * @return string|null * The session cookie domain, or NULL if the calculated value is invalid. */ protected function getCookieDomain(Request $request) { diff --git a/web/core/lib/Drupal/Core/TypedData/DataDefinitionInterface.php b/web/core/lib/Drupal/Core/TypedData/DataDefinitionInterface.php index e5614d3d462e85e092f7fad8a2f43654463b4a6f..3b9c64f4337aa5c0460e31b20f761fb0a60aaa79 100644 --- a/web/core/lib/Drupal/Core/TypedData/DataDefinitionInterface.php +++ b/web/core/lib/Drupal/Core/TypedData/DataDefinitionInterface.php @@ -143,7 +143,7 @@ public function getSettings(); * The setting name. * * @return mixed - * The setting value. + * The setting value or NULL if the setting name doesn't exist. */ public function getSetting($setting_name); diff --git a/web/core/modules/big_pipe/js/big_pipe.js b/web/core/modules/big_pipe/js/big_pipe.js index d20331de05673c7dfe5e390f7971e30caeec8cdc..fbfc7b26c12a5b088c6791aee8bf4439d82f05ee 100644 --- a/web/core/modules/big_pipe/js/big_pipe.js +++ b/web/core/modules/big_pipe/js/big_pipe.js @@ -59,8 +59,9 @@ */ function processReplacement(replacement) { const id = replacement.dataset.bigPipeReplacementForPlaceholderWithId; - // Because we use a mutation observer the content is guaranteed to be - // complete at this point. + // The content is not guaranteed to be complete at this point, but trimming + // it will not make a big change, since json will not be valid if it was + // not fully loaded anyway. const content = replacement.textContent.trim(); // Ignore any placeholders that are not in the known placeholder list. Used @@ -69,20 +70,32 @@ return; } - // Immediately remove the replacement to prevent it being processed twice. - delete drupalSettings.bigPipePlaceholderIds[id]; - const response = mapTextContentToAjaxResponse(content); if (response === false) { return; } + // Immediately remove the replacement to prevent it being processed twice. + delete drupalSettings.bigPipePlaceholderIds[id]; + // Then, simulate an AJAX response having arrived, and let the Ajax system // handle it. ajaxObject.success(response, 'success'); } + /** + * Checks if node is valid big pipe replacement. + */ + function checkMutation(node) { + return Boolean( + node.nodeType === Node.ELEMENT_NODE && + node.nodeName === 'SCRIPT' && + node.dataset && + node.dataset.bigPipeReplacementForPlaceholderWithId, + ); + } + /** * Check that the element is valid to process and process it. * @@ -90,12 +103,7 @@ * The node added to the body element. */ function checkMutationAndProcess(node) { - if ( - node.nodeType === Node.ELEMENT_NODE && - node.nodeName === 'SCRIPT' && - node.dataset && - node.dataset.bigPipeReplacementForPlaceholderWithId - ) { + if (checkMutation(node)) { processReplacement(node); } } @@ -107,8 +115,20 @@ * The list of mutations registered by the browser. */ function processMutations(mutations) { - mutations.forEach(({ addedNodes }) => { + mutations.forEach(({ addedNodes, type, target }) => { addedNodes.forEach(checkMutationAndProcess); + + // Checks if parent node of target node has not been processed. + // @see `@ingroup large_chunk` for more information. + if ( + type === 'characterData' && + checkMutation(target.parentNode) && + drupalSettings.bigPipePlaceholderIds[ + target.parentNode.dataset.bigPipeReplacementForPlaceholderWithId + ] === true + ) { + processReplacement(target.parentNode); + } }); } @@ -121,8 +141,19 @@ // in the DOM before the mutation observer is started. document.querySelectorAll(replacementsSelector).forEach(processReplacement); - // Start observing the body element for new children. - observer.observe(document.body, { childList: true }); + // Start observing the body element for new children and for new changes in + // Text nodes of elements. We need to track Text nodes because content + // of the node can be too large, browser will receive not fully loaded chunk + // and render it as is. At this moment json inside script will be invalid and + // we need to track new changes to that json (Text node), once it will be + // fully loaded it will be processed. + // @ingroup large_chunk + observer.observe(document.body, { + childList: true, + // Without this options characterData will not be triggered inside child nodes. + subtree: true, + characterData: true, + }); // As soon as the document is loaded, no more replacements will be added. // Immediately fetch and process all pending mutations and stop the observer. diff --git a/web/core/modules/big_pipe/tests/modules/big_pipe_regression_test/big_pipe_regression_test.module b/web/core/modules/big_pipe/tests/modules/big_pipe_regression_test/big_pipe_regression_test.module new file mode 100644 index 0000000000000000000000000000000000000000..c56a6bd86b4323522547867131f53bee217b11aa --- /dev/null +++ b/web/core/modules/big_pipe/tests/modules/big_pipe_regression_test/big_pipe_regression_test.module @@ -0,0 +1,19 @@ +<?php + +/** + * @file + * Support module for BigPipe testing. + */ + +/** + * Implements hook_theme(). + * + * @see \Drupal\Tests\big_pipe\FunctionalJavascript\BigPipeRegressionTest::testBigPipeLargeContent + */ +function big_pipe_regression_test_theme() { + return [ + 'big_pipe_test_large_content' => [ + 'variables' => [], + ], + ]; +} diff --git a/web/core/modules/big_pipe/tests/modules/big_pipe_regression_test/big_pipe_regression_test.routing.yml b/web/core/modules/big_pipe/tests/modules/big_pipe_regression_test/big_pipe_regression_test.routing.yml index bd0543b0e7a567a8d6b915bafd358d4d6ae1e812..82a53d6e2f6018bb194f0d601d0ad2ffc70954b3 100644 --- a/web/core/modules/big_pipe/tests/modules/big_pipe_regression_test/big_pipe_regression_test.routing.yml +++ b/web/core/modules/big_pipe/tests/modules/big_pipe_regression_test/big_pipe_regression_test.routing.yml @@ -11,3 +11,11 @@ big_pipe_regression_test.2802923: _controller: '\Drupal\big_pipe_regression_test\BigPipeRegressionTestController::regression2802923' requirements: _access: 'TRUE' + +big_pipe_test_large_content: + path: '/big_pipe_test_large_content' + defaults: + _controller: '\Drupal\big_pipe_regression_test\BigPipeRegressionTestController::largeContent' + _title: 'BigPipe test large content' + requirements: + _access: 'TRUE' diff --git a/web/core/modules/big_pipe/tests/modules/big_pipe_regression_test/src/BigPipeRegressionTestController.php b/web/core/modules/big_pipe/tests/modules/big_pipe_regression_test/src/BigPipeRegressionTestController.php index 6c1fde73319e62fa8eb78df65443c588a0d43b50..f612330e0292675985991768f53f6e1ae28a7317 100644 --- a/web/core/modules/big_pipe/tests/modules/big_pipe_regression_test/src/BigPipeRegressionTestController.php +++ b/web/core/modules/big_pipe/tests/modules/big_pipe_regression_test/src/BigPipeRegressionTestController.php @@ -32,6 +32,32 @@ public function regression2802923() { ]; } + /** + * A page with large content. + * + * @see \Drupal\Tests\big_pipe\FunctionalJavascript\BigPipeRegressionTest::testBigPipeLargeContent + */ + public function largeContent() { + return [ + 'item1' => [ + '#lazy_builder' => [static::class . '::largeContentBuilder', []], + '#create_placeholder' => TRUE, + ], + ]; + } + + /** + * Renders large content. + * + * @see \Drupal\Tests\big_pipe\FunctionalJavascript\BigPipeRegressionTest::testBigPipeLargeContent + */ + public static function largeContentBuilder() { + return [ + '#theme' => 'big_pipe_test_large_content', + '#cache' => ['max-age' => 0], + ]; + } + /** * #lazy_builder callback; builds <time> markup with current time. * @@ -48,7 +74,7 @@ public static function currentTime() { * {@inheritdoc} */ public static function trustedCallbacks() { - return ['currentTime']; + return ['currentTime', 'largeContentBuilder']; } } diff --git a/web/core/modules/big_pipe/tests/modules/big_pipe_regression_test/templates/big-pipe-test-large-content.html.twig b/web/core/modules/big_pipe/tests/modules/big_pipe_regression_test/templates/big-pipe-test-large-content.html.twig new file mode 100644 index 0000000000000000000000000000000000000000..86a5291cc6535d4fac8bfa944f9a42caffaf9bf9 --- /dev/null +++ b/web/core/modules/big_pipe/tests/modules/big_pipe_regression_test/templates/big-pipe-test-large-content.html.twig @@ -0,0 +1,6 @@ +<div id="big-pipe-large-content"> + {% for i in 0..130000 %} + boing + {% endfor %} +</div> + diff --git a/web/core/modules/big_pipe/tests/src/FunctionalJavascript/BigPipeRegressionTest.php b/web/core/modules/big_pipe/tests/src/FunctionalJavascript/BigPipeRegressionTest.php index 0cfeb11875e58ab3ada6fc1094776be0f009ba17..a06f39e9c7208867b96572fdc8b579d5c690d975 100644 --- a/web/core/modules/big_pipe/tests/src/FunctionalJavascript/BigPipeRegressionTest.php +++ b/web/core/modules/big_pipe/tests/src/FunctionalJavascript/BigPipeRegressionTest.php @@ -124,4 +124,28 @@ public function testPlaceholderInParagraph_2802923() { $this->assertJsCondition('document.querySelectorAll(\'p\').length === 1'); } + /** + * Tests BigPipe large content. + * + * Repeat loading of same page for two times, after second time the page is + * cached and the bug consistently reproducible. + */ + public function testBigPipeLargeContent() { + $user = $this->drupalCreateUser(); + $this->drupalLogin($user); + $assert_session = $this->assertSession(); + + $this->drupalGet(Url::fromRoute('big_pipe_test_large_content')); + $this->assertNotNull($assert_session->waitForElement('css', 'script[data-big-pipe-event="stop"]')); + $this->assertCount(0, $this->getDrupalSettings()['bigPipePlaceholderIds']); + $this->assertCount(2, $this->getSession()->getPage()->findAll('css', 'script[data-big-pipe-replacement-for-placeholder-with-id]')); + $assert_session->elementExists('css', '#big-pipe-large-content'); + + $this->drupalGet(Url::fromRoute('big_pipe_test_large_content')); + $this->assertNotNull($assert_session->waitForElement('css', 'script[data-big-pipe-event="stop"]')); + $this->assertCount(0, $this->getDrupalSettings()['bigPipePlaceholderIds']); + $this->assertCount(2, $this->getSession()->getPage()->findAll('css', 'script[data-big-pipe-replacement-for-placeholder-with-id]')); + $assert_session->elementExists('css', '#big-pipe-large-content'); + } + } diff --git a/web/core/modules/block/migrations/d7_block.yml b/web/core/modules/block/migrations/d7_block.yml index c6b8dffbca3112d48d87d62f5bb296c52e3f2394..184eee2f81ba7c4b198f29a143fdb0481e29bafa 100644 --- a/web/core/modules/block/migrations/d7_block.yml +++ b/web/core/modules/block/migrations/d7_block.yml @@ -1,4 +1,4 @@ -# cspell: ignore firstcolumn secondcolumn thirdcolumn fourthcolumn +# cspell:ignore firstcolumn secondcolumn thirdcolumn fourthcolumn id: d7_block label: Blocks # This configuration migration depends on the d7_custom_block content migration. diff --git a/web/core/modules/block/src/BlockForm.php b/web/core/modules/block/src/BlockForm.php index 90cd6823ffb4881561f2d1e4fd7136f7245b19f9..7bbf1b8654b6c8ae3eceb16f936fb087aab6be3e 100644 --- a/web/core/modules/block/src/BlockForm.php +++ b/web/core/modules/block/src/BlockForm.php @@ -309,13 +309,6 @@ public function validateForm(array &$form, FormStateInterface $form_state) { protected function validateVisibility(array $form, FormStateInterface $form_state) { // Validate visibility condition settings. foreach ($form_state->getValue('visibility') as $condition_id => $values) { - // All condition plugins use 'negate' as a Boolean in their schema. - // However, certain form elements may return it as 0/1. Cast here to - // ensure the data is in the expected type. - if (array_key_exists('negate', $values)) { - $form_state->setValue(['visibility', $condition_id, 'negate'], (bool) $values['negate']); - } - // Allow the condition to validate the form. $condition = $form_state->get(['conditions', $condition_id]); $condition->validateConfigurationForm($form['visibility'][$condition_id], SubformState::createForSubform($form['visibility'][$condition_id], $form, $form_state)); @@ -342,9 +335,13 @@ public function submitForm(array &$form, FormStateInterface $form_state) { } $this->submitVisibility($form, $form_state); + } - // Save the settings of the plugin. - $entity->save(); + /** + * {@inheritdoc} + */ + public function save(array $form, FormStateInterface $form_state) { + $value = parent::save($form, $form_state); $this->messenger()->addStatus($this->t('The block configuration has been saved.')); $form_state->setRedirect( @@ -354,6 +351,8 @@ public function submitForm(array &$form, FormStateInterface $form_state) { ], ['query' => ['block-placement' => Html::getClass($this->entity->id())]] ); + + return $value; } /** diff --git a/web/core/modules/block/src/Plugin/migrate/process/BlockPluginId.php b/web/core/modules/block/src/Plugin/migrate/process/BlockPluginId.php index 73444dfab1fd2c7d99ed2ec1ea138ac15f55f869..8f7f9f6e36a0c1f9de4aed6a5a40c68118054628 100644 --- a/web/core/modules/block/src/Plugin/migrate/process/BlockPluginId.php +++ b/web/core/modules/block/src/Plugin/migrate/process/BlockPluginId.php @@ -28,7 +28,7 @@ class BlockPluginId extends ProcessPluginBase implements ContainerFactoryPluginI /** * The block_content entity storage handler. * - * @var \Drupal\Core\Entity\EntityStorageInterface + * @var \Drupal\Core\Entity\EntityStorageInterface|null */ protected $blockContentStorage; @@ -41,12 +41,13 @@ class BlockPluginId extends ProcessPluginBase implements ContainerFactoryPluginI * The plugin ID. * @param array $plugin_definition * The plugin definition. - * @param \Drupal\Core\Entity\EntityStorageInterface $storage - * The block content storage object. + * @param \Drupal\Core\Entity\EntityStorageInterface|null $storage + * The block content storage object. NULL if the block_content module is + * not installed. * @param \Drupal\migrate\MigrateLookupInterface $migrate_lookup * The migrate lookup service. */ - public function __construct(array $configuration, $plugin_id, array $plugin_definition, EntityStorageInterface $storage, MigrateLookupInterface $migrate_lookup) { + public function __construct(array $configuration, $plugin_id, array $plugin_definition, ?EntityStorageInterface $storage, MigrateLookupInterface $migrate_lookup) { parent::__construct($configuration, $plugin_id, $plugin_definition); $this->blockContentStorage = $storage; $this->migrateLookup = $migrate_lookup; @@ -61,7 +62,7 @@ public static function create(ContainerInterface $container, array $configuratio $configuration, $plugin_id, $plugin_definition, - $entity_type_manager->getDefinition('block_content') ? $entity_type_manager->getStorage('block_content') : NULL, + $entity_type_manager->hasDefinition('block_content') ? $entity_type_manager->getStorage('block_content') : NULL, $container->get('migrate.lookup') ); } diff --git a/web/core/modules/block/tests/src/Kernel/Migrate/d7/MigrateBlockNoBlockContentTest.php b/web/core/modules/block/tests/src/Kernel/Migrate/d7/MigrateBlockNoBlockContentTest.php new file mode 100644 index 0000000000000000000000000000000000000000..6c7b92dc9ee1daaa27e865948364f262a94f037d --- /dev/null +++ b/web/core/modules/block/tests/src/Kernel/Migrate/d7/MigrateBlockNoBlockContentTest.php @@ -0,0 +1,161 @@ +<?php + +namespace Drupal\Tests\block\Kernel\Migrate\d7; + +use Drupal\block\Entity\Block; +use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase; + +/** + * Tests the migration of blocks without Block Content installed. + * + * @group block + */ +class MigrateBlockNoBlockContentTest extends MigrateDrupal7TestBase { + + /** + * {@inheritdoc} + */ + protected static $modules = [ + 'block', + 'views', + 'comment', + 'menu_ui', + 'node', + 'text', + 'filter', + 'path_alias', + 'user', + ]; + + /** + * {@inheritdoc} + */ + protected function setUp(): void { + parent::setUp(); + + // Install the themes used for this test. + $this->container->get('theme_installer')->install(['olivero', 'claro']); + + $this->installConfig(static::$modules); + + // Set Olivero and Claro as the default public and admin theme. + $config = $this->config('system.theme'); + $config->set('default', 'olivero'); + $config->set('admin', 'claro'); + $config->save(); + + $this->executeMigrations([ + 'd7_filter_format', + 'd7_user_role', + 'd7_block', + ]); + block_rebuild(); + } + + /** + * Asserts various aspects of a block. + * + * @param string $id + * The block ID. + * @param string $plugin_id + * The block's plugin ID. + * @param array $roles + * Role IDs the block is expected to have. + * @param string $pages + * The list of pages on which the block should appear. + * @param string $region + * The display region. + * @param string $theme + * The theme. + * @param int $weight + * The block weight. + * @param string $label + * The block label. + * @param string $label_display + * The block label display setting. + * @param bool $status + * Whether the block is expected to be enabled or disabled. + * + * @internal + */ + public function assertEntity(string $id, string $plugin_id, array $roles, string $pages, string $region, string $theme, int $weight, string $label, string $label_display, bool $status = TRUE): void { + $block = Block::load($id); + $this->assertInstanceOf(Block::class, $block); + /** @var \Drupal\block\BlockInterface $block */ + $this->assertSame($plugin_id, $block->getPluginId()); + + $visibility = $block->getVisibility(); + if ($roles) { + $this->assertSame($roles, array_values($visibility['user_role']['roles'])); + $this->assertSame('@user.current_user_context:current_user', $visibility['user_role']['context_mapping']['user']); + } + if ($pages) { + $this->assertSame($pages, $visibility['request_path']['pages']); + } + + $this->assertSame($region, $block->getRegion()); + $this->assertSame($theme, $block->getTheme()); + $this->assertSame($weight, $block->getWeight()); + $this->assertSame($status, $block->status()); + + $config = $this->config('block.block.' . $id); + $this->assertSame($label, $config->get('settings.label')); + $this->assertSame($label_display, $config->get('settings.label_display')); + } + + /** + * Tests the block migration. + */ + public function testBlockMigration(): void { + $this->assertEntity('bartik_system_main', 'system_main_block', [], '', 'content', 'olivero', 0, '', '0'); + $this->assertEntity('bartik_search_form', 'search_form_block', [], '', 'content', 'olivero', -1, '', '0'); + $this->assertEntity('bartik_user_login', 'user_login_block', [], '', 'content', 'olivero', 0, 'User login title', 'visible'); + $this->assertEntity('bartik_system_powered_by', 'system_powered_by_block', [], '', 'footer_bottom', 'olivero', 10, '', '0'); + $this->assertEntity('seven_system_main', 'system_main_block', [], '', 'content', 'claro', 0, '', '0'); + $this->assertEntity('seven_user_login', 'user_login_block', [], '', 'content', 'claro', 10, 'User login title', 'visible'); + + // Assert that disabled blocks (or enabled blocks whose plugin IDs could + // be resolved) did not migrate. + $non_existent_blocks = [ + 'bartik_system_navigation', + 'bartik_system_help', + 'seven_user_new', + 'seven_search_form', + 'bartik_comment_recent', + 'bartik_node_syndicate', + 'bartik_node_recent', + 'bartik_shortcut_shortcuts', + 'bartik_system_management', + 'bartik_system_user-menu', + 'bartik_system_main-menu', + 'bartik_user_new', + 'bartik_user_online', + 'seven_comment_recent', + 'seven_node_syndicate', + 'seven_shortcut_shortcuts', + 'seven_system_powered-by', + 'seven_system_navigation', + 'seven_system_management', + 'seven_system_user-menu', + 'seven_system_main-menu', + 'seven_user_online', + 'bartik_blog_recent', + 'bartik_book_navigation', + 'bartik_locale_language', + 'bartik_forum_active', + 'bartik_forum_new', + 'seven_blog_recent', + 'seven_book_navigation', + 'seven_locale_language', + 'seven_forum_active', + 'seven_forum_new', + 'bartik_menu_menu-test-menu', + 'bartik_statistics_popular', + 'seven_menu_menu-test-menu', + 'seven_statistics_popular', + 'seven_block_1', + ]; + $this->assertEmpty(Block::loadMultiple($non_existent_blocks)); + } + +} diff --git a/web/core/modules/ckeditor5/js/ckeditor5.dialog.fix.js b/web/core/modules/ckeditor5/js/ckeditor5.dialog.fix.js index 1f4ed1d7feb523cffee35f245b7dab06da4f38fa..41449dcf693fab7ff15220fd4b57bd89a71cab8d 100644 --- a/web/core/modules/ckeditor5/js/ckeditor5.dialog.fix.js +++ b/web/core/modules/ckeditor5/js/ckeditor5.dialog.fix.js @@ -12,6 +12,12 @@ // CKEditor 5 in modals can work as expected. // @see https://api.jqueryui.com/dialog/#method-_allowInteraction _allowInteraction(event) { + // Fixes "Uncaught TypeError: event.target.classList is undefined" + // in Firefox (only). + // @see https://www.drupal.org/project/drupal/issues/3351600 + if (event.target.classList === undefined) { + return this._super(event); + } return event.target.classList.contains('ck') || this._super(event); }, }); diff --git a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalHtmlEngine/src/drupalhtmlbuilder.js b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalHtmlEngine/src/drupalhtmlbuilder.js index fb5846b3b4a384511550b0722295686712e76820..48178378d5de70cf916cc90d7da4e69c4deb8cbb 100644 --- a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalHtmlEngine/src/drupalhtmlbuilder.js +++ b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalHtmlEngine/src/drupalhtmlbuilder.js @@ -1,4 +1,4 @@ -// cSpell:words apos +// cspell:ignore apos /** * HTML builder that converts document fragments into strings. diff --git a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalHtmlEngine/src/drupalhtmlengine.js b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalHtmlEngine/src/drupalhtmlengine.js index e365d42d4955fbcc45f9b0f15307f3ec60d0bd41..1bbb1514aa538741e698dfe0cbe9c03f53f54e1b 100644 --- a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalHtmlEngine/src/drupalhtmlengine.js +++ b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalHtmlEngine/src/drupalhtmlengine.js @@ -1,5 +1,5 @@ /* eslint-disable import/no-extraneous-dependencies */ -// cSpell:words drupalhtmlwriter +// cspell:ignore drupalhtmlwriter import { Plugin } from 'ckeditor5/src/core'; import DrupalHtmlWriter from './drupalhtmlwriter'; diff --git a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalHtmlEngine/src/drupalhtmlwriter.js b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalHtmlEngine/src/drupalhtmlwriter.js index 4851ebdc720a4a9615ec0b06e86fcd80139a9110..5201504dd160cfa792eb59b15924e8e17de91ba2 100644 --- a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalHtmlEngine/src/drupalhtmlwriter.js +++ b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalHtmlEngine/src/drupalhtmlwriter.js @@ -1,4 +1,4 @@ -// cSpell:words drupalhtmlbuilder dataprocessor basichtmlwriter htmlwriter +// cspell:ignore drupalhtmlbuilder dataprocessor basichtmlwriter htmlwriter import DrupalHtmlBuilder from './drupalhtmlbuilder'; /** diff --git a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalImage/src/drupalimage.js b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalImage/src/drupalimage.js index 5b67bd18d09168f548567c861cf2726a636a7388..53b405468e8b281c6644da6cf0297ede67e22e38 100644 --- a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalImage/src/drupalimage.js +++ b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalImage/src/drupalimage.js @@ -1,5 +1,5 @@ /* eslint-disable import/no-extraneous-dependencies */ -/* cspell:words drupalimageediting drupalimagealternativetext */ +/* cspell:ignore drupalimageediting drupalimagealternativetext */ import { Plugin } from 'ckeditor5/src/core'; import DrupalImageEditing from './drupalimageediting'; diff --git a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalImage/src/drupalimagealternativetext.js b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalImage/src/drupalimagealternativetext.js index e82ab82527434cb261028234abeb0b5f1b45109f..18059d9d5ad39dc6c60a12887ad6b89abc088c85 100644 --- a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalImage/src/drupalimagealternativetext.js +++ b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalImage/src/drupalimagealternativetext.js @@ -1,5 +1,5 @@ /* eslint-disable import/no-extraneous-dependencies */ -/* cspell:words imagealternativetext imagetextalternativeediting drupalimagealternativetextediting drupalimagealternativetextui */ +/* cspell:ignore imagealternativetext imagetextalternativeediting drupalimagealternativetextediting drupalimagealternativetextui */ /** * @module drupalImage/imagealternativetext diff --git a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalImage/src/drupalimageediting.js b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalImage/src/drupalimageediting.js index f1a5be865d95cef94d93b576c435d8aa2f921ea2..b594e2a1f9989ddbe60afd2d69bcb1d0ab8d9689 100644 --- a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalImage/src/drupalimageediting.js +++ b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalImage/src/drupalimageediting.js @@ -1,5 +1,5 @@ /* eslint-disable import/no-extraneous-dependencies */ -// cSpell:words datafilter downcasted linkimageediting emptyelement downcastdispatcher +// cspell:ignore datafilter downcasted linkimageediting emptyelement downcastdispatcher import { Plugin } from 'ckeditor5/src/core'; import { setViewAttributes } from '@ckeditor/ckeditor5-html-support/src/utils'; diff --git a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalImage/src/imagealternativetext/drupalimagealternativetextediting.js b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalImage/src/imagealternativetext/drupalimagealternativetextediting.js index f931c874fe43938b373b4273eb33f8a45c32200e..ce35fa5a225160450c6cdfb3c39198b1a138fb59 100644 --- a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalImage/src/imagealternativetext/drupalimagealternativetextediting.js +++ b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalImage/src/imagealternativetext/drupalimagealternativetextediting.js @@ -1,5 +1,5 @@ /* eslint-disable import/no-extraneous-dependencies */ -/* cspell:words imagealternativetext drupalimagealternativetextediting drupalimagetextalternativecommand textalternativemissingview imagetextalternativecommand */ +/* cspell:ignore imagealternativetext drupalimagealternativetextediting drupalimagetextalternativecommand textalternativemissingview imagetextalternativecommand */ /** * @module drupalImage/imagealternativetext/drupalimagealternativetextediting diff --git a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalImage/src/imagealternativetext/drupalimagealternativetextui.js b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalImage/src/imagealternativetext/drupalimagealternativetextui.js index 597ebda91e0b6d3397bb48b42982fac510e290a1..ed10936a9fa5518dd8dc04ca94900ae6c56fe74b 100644 --- a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalImage/src/imagealternativetext/drupalimagealternativetextui.js +++ b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalImage/src/imagealternativetext/drupalimagealternativetextui.js @@ -1,5 +1,5 @@ /* eslint-disable import/no-extraneous-dependencies */ -/* cspell:words drupalimagealternativetextui contextualballoon componentfactory imagealternativetextformview missingalternativetextview imagetextalternativeui imagealternativetext */ +/* cspell:ignore drupalimagealternativetextui contextualballoon componentfactory imagealternativetextformview missingalternativetextview imagetextalternativeui imagealternativetext */ /** * @module drupalImage/imagealternativetext/drupalimagealternativetextui diff --git a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalImage/src/imagealternativetext/ui/imagealternativetextformview.js b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalImage/src/imagealternativetext/ui/imagealternativetextformview.js index df231866fe49250ed156cb8b65568bca2ffbc52d..e87c06521d527f55e01165d1abb656680bbe7932 100644 --- a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalImage/src/imagealternativetext/ui/imagealternativetextformview.js +++ b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalImage/src/imagealternativetext/ui/imagealternativetextformview.js @@ -1,5 +1,5 @@ /* eslint-disable import/no-extraneous-dependencies */ -/* cspell:words focustracker keystrokehandler labeledfield labeledfieldview buttonview viewcollection focusables focuscycler switchbuttonview imagealternativetextformview imagealternativetext */ +/* cspell:ignore focustracker keystrokehandler labeledfield labeledfieldview buttonview viewcollection focusables focuscycler switchbuttonview imagealternativetextformview imagealternativetext */ /** * @module drupalImage/imagealternativetext/ui/imagealternativetextformview diff --git a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalImage/src/imagealternativetext/ui/missingalternativetextview.js b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalImage/src/imagealternativetext/ui/missingalternativetextview.js index ddd8f6e3b77783b3800c56e5d99045e3786794fa..a1bb44567ae63592d8ce913a67f6a93b42c377d3 100644 --- a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalImage/src/imagealternativetext/ui/missingalternativetextview.js +++ b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalImage/src/imagealternativetext/ui/missingalternativetextview.js @@ -1,5 +1,5 @@ /* eslint-disable import/no-extraneous-dependencies */ -/* cspell:words imagetextalternative missingalternativetextview imagealternativetext */ +/* cspell:ignore imagetextalternative missingalternativetextview imagealternativetext */ import { View, ButtonView } from 'ckeditor5/src/ui'; diff --git a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalImage/src/imageupload/drupalfilerepository.js b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalImage/src/imageupload/drupalfilerepository.js index a851e38efee188d63b0e92510b525141d9c7d31a..4604b9e12c9f6f68d39da0ab3dbfb17b6096d11c 100644 --- a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalImage/src/imageupload/drupalfilerepository.js +++ b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalImage/src/imageupload/drupalfilerepository.js @@ -1,5 +1,5 @@ /* eslint-disable import/no-extraneous-dependencies */ -/* cspell:words uploadurl drupalimageuploadadapter */ +/* cspell:ignore uploadurl drupalimageuploadadapter */ import { Plugin } from 'ckeditor5/src/core'; import { FileRepository } from 'ckeditor5/src/upload'; diff --git a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalImage/src/imageupload/drupalimageupload.js b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalImage/src/imageupload/drupalimageupload.js index 629f086cc92fb76e1c420fe48383708d98965521..fc37adb824dcd1c93ade199b0d3d5f31e4c9c5e0 100644 --- a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalImage/src/imageupload/drupalimageupload.js +++ b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalImage/src/imageupload/drupalimageupload.js @@ -1,5 +1,5 @@ /* eslint-disable import/no-extraneous-dependencies */ -/* cspell:words drupalimageuploadediting drupalfilerepository */ +/* cspell:ignore drupalimageuploadediting drupalfilerepository */ import { Plugin } from 'ckeditor5/src/core'; import DrupalImageUploadEditing from './drupalimageuploadediting'; diff --git a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalImage/src/imageupload/drupalimageuploadadapter.js b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalImage/src/imageupload/drupalimageuploadadapter.js index 50969fb00c3078fc518a284104098d044f5167cf..13abca90afa69e0f81e096f92e385613780d6f32 100644 --- a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalImage/src/imageupload/drupalimageuploadadapter.js +++ b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalImage/src/imageupload/drupalimageuploadadapter.js @@ -1,5 +1,5 @@ /* eslint-disable import/no-extraneous-dependencies */ -/* cspell:words simpleuploadadapter filerepository */ +/* cspell:ignore simpleuploadadapter filerepository */ /** * Upload adapter. diff --git a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupalelementstyle.js b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupalelementstyle.js index 52d120693fe7ed09143c549fe5d1024ffa210609..ea61869a8c2f75ab3236421d2e5c96a0250ab987 100644 --- a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupalelementstyle.js +++ b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupalelementstyle.js @@ -1,5 +1,5 @@ /* eslint-disable import/no-extraneous-dependencies */ -/* cspell:words drupalelementstyle drupalelementstyleui drupalelementstyleediting imagestyle drupalmediatoolbar drupalmediaediting */ +/* cspell:ignore drupalelementstyle drupalelementstyleui drupalelementstyleediting imagestyle drupalmediatoolbar drupalmediaediting */ import { Plugin } from 'ckeditor5/src/core'; import DrupalElementStyleUi from './drupalelementstyle/drupalelementstyleui'; import DrupalElementStyleEditing from './drupalelementstyle/drupalelementstyleediting'; diff --git a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupalelementstyle/drupalelementstyleediting.js b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupalelementstyle/drupalelementstyleediting.js index dd8eba70dd3989cdd5ce38f9e63bcf1b9a1c88e6..c2e0922a7112aa7e51cfb01c2acd740c7622e5c4 100644 --- a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupalelementstyle/drupalelementstyleediting.js +++ b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupalelementstyle/drupalelementstyleediting.js @@ -1,5 +1,5 @@ /* eslint-disable import/no-extraneous-dependencies */ -/* cspell:words drupalelementstylecommand */ +/* cspell:ignore drupalelementstylecommand */ import { Plugin, icons } from 'ckeditor5/src/core'; import { first } from 'ckeditor5/src/utils'; import DrupalElementStyleCommand from './drupalelementstylecommand'; diff --git a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupalelementstyle/drupalelementstyleui.js b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupalelementstyle/drupalelementstyleui.js index 21869fe57f5d4d57e5c54afdfcc106077a506358..3dbb39553800dabb7bedf6705334326104b995c6 100644 --- a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupalelementstyle/drupalelementstyleui.js +++ b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupalelementstyle/drupalelementstyleui.js @@ -1,5 +1,5 @@ /* eslint-disable import/no-extraneous-dependencies */ -/* cspell:words drupalelementstyleediting splitbutton imagestyle componentfactory buttonview */ +/* cspell:ignore drupalelementstyleediting splitbutton imagestyle componentfactory buttonview */ import { Plugin } from 'ckeditor5/src/core'; import { Collection, toMap } from 'ckeditor5/src/utils'; import utils from '@ckeditor/ckeditor5-image/src/imagestyle/utils'; diff --git a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupalelementstyle/utils.js b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupalelementstyle/utils.js index 4db1f8ee409408a02b1eb765c6fb64919799bf3b..7de86e4c58db5cd5745c1ae8930d6629d2ab0bfc 100644 --- a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupalelementstyle/utils.js +++ b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupalelementstyle/utils.js @@ -1,4 +1,4 @@ -/* cspell:words documentselection */ +/* cspell:ignore documentselection */ /** * Checks the schema to see if drupalElementStyle is supported on the element. * diff --git a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupallinkmedia/drupallinkmedia.js b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupallinkmedia/drupallinkmedia.js index 847f762b55fe6d0e83c6e31fd0dcd63dcd2f7b08..fbb37e8eb11289e8425898edcc4c095fb9357c61 100644 --- a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupallinkmedia/drupallinkmedia.js +++ b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupallinkmedia/drupallinkmedia.js @@ -1,5 +1,5 @@ /* eslint-disable import/no-extraneous-dependencies */ -/* cspell:words drupallinkmediaediting drupallinkmediaui */ +/* cspell:ignore drupallinkmediaediting drupallinkmediaui */ import { Plugin } from 'ckeditor5/src/core'; import DrupalLinkMediaEditing from './drupallinkmediaediting'; diff --git a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupallinkmedia/drupallinkmediaediting.js b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupallinkmedia/drupallinkmediaediting.js index 658e6ee66b9f952e7e37ee25f3d684a7247c8d59..67f7f303d12944e5b4809458250347d5e115ff5c 100644 --- a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupallinkmedia/drupallinkmediaediting.js +++ b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupallinkmedia/drupallinkmediaediting.js @@ -1,5 +1,5 @@ /* eslint-disable import/no-extraneous-dependencies */ -/* cspell:words drupallinkmediaediting linkediting linkimageediting linkcommand */ +/* cspell:ignore drupallinkmediaediting linkediting linkimageediting linkcommand */ import { Plugin } from 'ckeditor5/src/core'; import { Matcher } from 'ckeditor5/src/engine'; import { toMap } from 'ckeditor5/src/utils'; diff --git a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupallinkmedia/drupallinkmediaui.js b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupallinkmedia/drupallinkmediaui.js index c366ec21025cd0d935039bc6e6699519d18f001e..cb4685e49f23bed535c2f512f6d1f349ef57e910 100644 --- a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupallinkmedia/drupallinkmediaui.js +++ b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupallinkmedia/drupallinkmediaui.js @@ -1,5 +1,5 @@ /* eslint-disable import/no-extraneous-dependencies */ -// cSpell:words linkui +// cspell:ignore linkui import { Plugin } from 'ckeditor5/src/core'; import { LINK_KEYSTROKE } from '@ckeditor/ckeditor5-link/src/utils'; import { ButtonView } from 'ckeditor5/src/ui'; diff --git a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupalmedia.js b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupalmedia.js index 74167436c3f19a4db113ce170a802b9bd9e69e95..c7271d361467b34e1033f892f16d70d8a9763a1f 100644 --- a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupalmedia.js +++ b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupalmedia.js @@ -1,5 +1,5 @@ /* eslint-disable import/no-extraneous-dependencies */ -/* cspell:words drupalmediaediting drupalmediageneralhtmlsupport drupalmediaui drupalmediatoolbar mediaimagetextalternative */ +/* cspell:ignore drupalmediaediting drupalmediageneralhtmlsupport drupalmediaui drupalmediatoolbar mediaimagetextalternative */ import { Plugin } from 'ckeditor5/src/core'; import DrupalMediaEditing from './drupalmediaediting'; diff --git a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupalmediacaption.js b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupalmediacaption.js index 3abd8b45af4941033d2cb1646a9e86c01ab77655..c5a1a62dd222cab77ae9ceea824554eed27b362f 100644 --- a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupalmediacaption.js +++ b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupalmediacaption.js @@ -1,5 +1,5 @@ /* eslint-disable import/no-extraneous-dependencies */ -/* cspell:words drupalmediacaption drupalmediacaptionediting drupalmediacaptionui */ +/* cspell:ignore drupalmediacaption drupalmediacaptionediting drupalmediacaptionui */ import { Plugin } from 'ckeditor5/src/core'; import DrupalMediaCaptionEditing from './drupalmediacaption/drupalmediacaptionediting'; import DrupalMediaCaptionUI from './drupalmediacaption/drupalmediacaptionui'; diff --git a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupalmediacaption/drupalmediacaptioncommand.js b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupalmediacaption/drupalmediacaptioncommand.js index c17a9e1beff66deda310c92c26686a5ebaac6c4b..f1268afdab03696d93b1c76fc450f0699a8f8b13 100644 --- a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupalmediacaption/drupalmediacaptioncommand.js +++ b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupalmediacaption/drupalmediacaptioncommand.js @@ -1,5 +1,5 @@ /* eslint-disable import/no-extraneous-dependencies */ -/* cspell:words imagecaption */ +/* cspell:ignore imagecaption */ import { Command } from 'ckeditor5/src/core'; import { getClosestSelectedDrupalMediaElement, isDrupalMedia } from '../utils'; import { getMediaCaptionFromModelSelection } from './utils'; diff --git a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupalmediacaption/drupalmediacaptionediting.js b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupalmediacaption/drupalmediacaptionediting.js index d22100c4761b37bbcf339a44e46f51de64c2e8c1..f0d5faa5efbeb99f5a8a8e0012aa4cd5f2dbbae6 100644 --- a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupalmediacaption/drupalmediacaptionediting.js +++ b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupalmediacaption/drupalmediacaptionediting.js @@ -1,5 +1,5 @@ /* eslint-disable import/no-extraneous-dependencies */ -/* cspell:words insertdrupalmedia JSONified drupalmediacaptioncommand downcasted */ +/* cspell:ignore insertdrupalmedia JSONified drupalmediacaptioncommand downcasted */ import { Plugin } from 'ckeditor5/src/core'; import { Element, enablePlaceholder } from 'ckeditor5/src/engine'; import { toWidgetEditable } from 'ckeditor5/src/widget'; diff --git a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupalmediaediting.js b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupalmediaediting.js index d31db61f7a472f5fcc43eb45511334ed6c08d8ea..d4f227f01c97b63f6c233ced921ddd888580fc44 100644 --- a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupalmediaediting.js +++ b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupalmediaediting.js @@ -1,5 +1,5 @@ /* eslint-disable import/no-extraneous-dependencies */ -/* cspell:words insertdrupalmedia drupalmediaediting insertdrupalmediacommand drupalmediametadatarepository */ +/* cspell:ignore insertdrupalmedia drupalmediaediting insertdrupalmediacommand drupalmediametadatarepository */ import { Plugin } from 'ckeditor5/src/core'; import { toWidget, Widget } from 'ckeditor5/src/widget'; diff --git a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupalmediageneralhtmlsupport.js b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupalmediageneralhtmlsupport.js index c770a53169eac81474783d2de163b831e96df2cf..66ca7dbee62ee9bb97f9bed0f95a2ec718903f18 100644 --- a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupalmediageneralhtmlsupport.js +++ b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupalmediageneralhtmlsupport.js @@ -1,5 +1,5 @@ /* eslint-disable import/no-extraneous-dependencies */ -// cSpell:words datafilter eventinfo downcastdispatcher generalhtmlsupport +// cspell:ignore datafilter eventinfo downcastdispatcher generalhtmlsupport import { Plugin } from 'ckeditor5/src/core'; import { setViewAttributes } from '@ckeditor/ckeditor5-html-support/src/utils'; diff --git a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupalmediametadatarepository.js b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupalmediametadatarepository.js index a6ebd11a1b7b603edc43c263974687296ed95dfc..81e2f79d6b20bfd5981f97e33dddc36df1b82f2d 100644 --- a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupalmediametadatarepository.js +++ b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupalmediametadatarepository.js @@ -1,5 +1,5 @@ /* eslint-disable import/no-extraneous-dependencies */ -/* cspell:words drupalmediametadatarepository */ +/* cspell:ignore drupalmediametadatarepository */ import { Plugin } from 'ckeditor5/src/core'; diff --git a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupalmediatoolbar.js b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupalmediatoolbar.js index de4dc9e177f0d11d9aa3fe837558dea288968395..e79f82282f0531207fce03dbe07b4bf525ed8a10 100644 --- a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupalmediatoolbar.js +++ b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/drupalmediatoolbar.js @@ -1,5 +1,5 @@ /* eslint-disable import/no-extraneous-dependencies */ -/* cspell:words drupalmediatoolbar */ +/* cspell:ignore drupalmediatoolbar */ import { Plugin } from 'ckeditor5/src/core'; import { WidgetToolbarRepository } from 'ckeditor5/src/widget'; diff --git a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/insertdrupalmedia.js b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/insertdrupalmedia.js index be47f38c313c040005618fd84d3cfd1f912172b1..df600cd3d0af8e1093379037a4158e2dfa48f436 100644 --- a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/insertdrupalmedia.js +++ b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/insertdrupalmedia.js @@ -1,5 +1,5 @@ /* eslint-disable import/no-extraneous-dependencies */ -// cSpell:words insertdrupalmediacommand +// cspell:ignore insertdrupalmediacommand import { Command } from 'ckeditor5/src/core'; import { groupNameToModelAttributeKey } from './utils'; diff --git a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/mediaimagetextalternative/mediaimagetextalternativeediting.js b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/mediaimagetextalternative/mediaimagetextalternativeediting.js index 994c6b83fc40566bf11d7dc4186fb0566e1ac404..984058ccf108f1897f0ad99ce4ccc488926d4aaa 100644 --- a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/mediaimagetextalternative/mediaimagetextalternativeediting.js +++ b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/mediaimagetextalternative/mediaimagetextalternativeediting.js @@ -1,5 +1,5 @@ /* eslint-disable import/no-extraneous-dependencies */ -/* cspell:words mediaimagetextalternativecommand drupalmediametadatarepository insertdrupalmediacommand */ +/* cspell:ignore mediaimagetextalternativecommand drupalmediametadatarepository insertdrupalmediacommand */ import { Plugin } from 'ckeditor5/src/core'; import { Template } from 'ckeditor5/src/ui'; diff --git a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/mediaimagetextalternative/mediaimagetextalternativeui.js b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/mediaimagetextalternative/mediaimagetextalternativeui.js index 4972715ebc591b2ff52071431bc46b493aa40e3b..b6a313efa447755a6c9add342bf9113ff7ddcbb3 100644 --- a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/mediaimagetextalternative/mediaimagetextalternativeui.js +++ b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/mediaimagetextalternative/mediaimagetextalternativeui.js @@ -1,5 +1,5 @@ /* eslint-disable import/no-extraneous-dependencies */ -/* cspell:words textalternativeformview */ +/* cspell:ignore textalternativeformview */ import { Plugin, icons } from 'ckeditor5/src/core'; import { diff --git a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/utils.js b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/utils.js index 1095686ee8bb4f4a0373eea03d165016be750d02..afd77f4cd9828c77c226ddda92437775f3cd8686 100644 --- a/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/utils.js +++ b/web/core/modules/ckeditor5/js/ckeditor5_plugins/drupalMedia/src/utils.js @@ -1,5 +1,5 @@ /* eslint-disable import/no-extraneous-dependencies */ -// cSpell:words documentselection +// cspell:ignore documentselection import { isWidget } from 'ckeditor5/src/widget'; /** diff --git a/web/core/modules/content_translation/src/ContentTranslationManagerInterface.php b/web/core/modules/content_translation/src/ContentTranslationManagerInterface.php index 1852026126cdab26d104a0ce274111f37a61dec6..1b36b077342b9c4f1af40b09b2e52820d7ddd3d9 100644 --- a/web/core/modules/content_translation/src/ContentTranslationManagerInterface.php +++ b/web/core/modules/content_translation/src/ContentTranslationManagerInterface.php @@ -71,7 +71,7 @@ public function setEnabled($entity_type_id, $bundle, $value); * (optional) The bundle of the entity. If no bundle is provided, all the * available bundles are checked. * - * @returns bool + * @return bool * TRUE if the specified bundle is translatable. If no bundle is provided * returns TRUE if at least one of the entity bundles is translatable. */ diff --git a/web/core/modules/content_translation/src/FieldTranslationSynchronizer.php b/web/core/modules/content_translation/src/FieldTranslationSynchronizer.php index 336909d2a7e89d6f00cdd95a2746ff6189429501..0bd8e2c6d833209ea214e3834d53c7e41a0f5daf 100644 --- a/web/core/modules/content_translation/src/FieldTranslationSynchronizer.php +++ b/web/core/modules/content_translation/src/FieldTranslationSynchronizer.php @@ -327,7 +327,7 @@ protected function createMergedItem(array $source_item, array $target_item, arra * @param array $properties * An array of column names to be synchronized. * - * @returns string + * @return string * A hash code that can be used to identify the item. */ protected function itemHash(array $items, $delta, array $properties) { diff --git a/web/core/modules/jsonapi/jsonapi.module b/web/core/modules/jsonapi/jsonapi.module index 804e78fd643749229202121bca760e8fba21fc3c..fa21b18d960e45e3e6e25d35bda833af7644c6f9 100644 --- a/web/core/modules/jsonapi/jsonapi.module +++ b/web/core/modules/jsonapi/jsonapi.module @@ -183,6 +183,7 @@ function jsonapi_jsonapi_block_content_filter_access(EntityTypeInterface $entity // \Drupal\jsonapi\Access\TemporaryQueryGuard adds the condition for // (isReusable()), so this does not have to. return ([ + JSONAPI_FILTER_AMONG_ALL => AccessResult::allowedIfHasPermission($account, 'access block library'), JSONAPI_FILTER_AMONG_PUBLISHED => AccessResult::allowed(), ]); } diff --git a/web/core/modules/jsonapi/src/Normalizer/Value/TemporaryArrayObjectThrowingExceptions.php b/web/core/modules/jsonapi/src/Normalizer/Value/TemporaryArrayObjectThrowingExceptions.php index 63b7ada5d3edc176dc195d1311ba2ec46adc8259..397dd2c624e7fd073f545fc295d58e6f5480ceb5 100644 --- a/web/core/modules/jsonapi/src/Normalizer/Value/TemporaryArrayObjectThrowingExceptions.php +++ b/web/core/modules/jsonapi/src/Normalizer/Value/TemporaryArrayObjectThrowingExceptions.php @@ -30,9 +30,6 @@ public function append($value): void { * @param int $flags * The flags to sort the ArrayObject by. * - * @return bool - * This method always returns TRUE. - * * @throws \Exception * This class does not support this action but it must implement it, because * it is extending \ArrayObject. @@ -45,9 +42,6 @@ public function asort($flags = SORT_REGULAR): bool { /** * Count the ArrayObject. * - * @return int - * The number of public properties in the \ArrayObject. - * * @throws \Exception * This class does not support this action but it must implement it, because * it is extending \ArrayObject. @@ -62,9 +56,6 @@ public function count(): int { * @param array|object $array * The array to replace for the current array. * - * @return array - * The new array or object to exchange with the current array. - * * @throws \Exception * This class does not support this action but it must implement it, because * it is extending \ArrayObject. @@ -76,9 +67,6 @@ public function exchangeArray($array): array { /** * Exports the \ArrayObject to an array. * - * @return array - * Returns a copy of the array. - * * @throws \Exception * This class does not support this action but it must implement it, because * it is extending \ArrayObject. @@ -90,9 +78,6 @@ public function getArrayCopy(): array { /** * Gets the behavior flags of the \ArrayObject. * - * @return int - * Returns the behavior flags of the \ArrayObject. - * * @throws \Exception * This class does not support this action but it must implement it, because * it is extending \ArrayObject. @@ -104,9 +89,6 @@ public function getFlags(): int { /** * Create a new iterator from an ArrayObject instance. * - * @return \Iterator - * An iterator from the ArrayObject. - * * @throws \Exception * This class does not support this action but it must implement it, because * it is extending \ArrayObject. @@ -118,9 +100,6 @@ public function getIterator(): \Iterator { /** * Gets the class name of the array iterator that is used by \ArrayObject::getIterator(). * - * @return string - * Returns the iterator class name that is used to iterate over this object. - * * @throws \Exception * This class does not support this action but it must implement it, because * it is extending \ArrayObject. @@ -135,9 +114,6 @@ public function getIteratorClass(): string { * @param int $flags * The flags to sort the ArrayObject by. * - * @return bool - * This method always returns TRUE. - * * @throws \Exception * This class does not support this action but it must implement it, because * it is extending \ArrayObject. @@ -150,9 +126,6 @@ public function ksort($flags = SORT_REGULAR): bool { /** * Sort an array using a case insensitive "natural order" algorithm. * - * @return bool - * This method always returns TRUE. - * * @throws \Exception * This class does not support this action but it must implement it, because * it is extending \ArrayObject. @@ -165,9 +138,6 @@ public function natcasesort(): bool { /** * Sort entries using a "natural order" algorithm. * - * @return bool - * This method always returns TRUE. - * * @throws \Exception * This class does not support this action but it must implement it, because * it is extending \ArrayObject. @@ -183,9 +153,6 @@ public function natsort(): bool { * @param mixed $key * The index being checked. * - * @return bool - * Return TRUE if the requested index exists, otherwise FALSE. - * * @throws \Exception * This class does not support this action but it must implement it, because * it is extending \ArrayObject. @@ -279,9 +246,6 @@ public function setIteratorClass($iteratorClass): void { * greater than zero if the first argument is considered to be respectively * less than, equal to, or greater than the second. * - * @return bool - * This method always returns TRUE. - * * @throws \Exception * This class does not support this action but it must implement it, because * it is extending \ArrayObject. @@ -299,9 +263,6 @@ public function uasort($callback): bool { * greater than zero if the first argument is considered to be respectively * less than, equal to, or greater than the second. * - * @return bool - * This method always returns TRUE. - * * @throws \Exception * This class does not support this action but it must implement it, because * it is extending \ArrayObject. diff --git a/web/core/modules/jsonapi/tests/src/Functional/BlockContentTest.php b/web/core/modules/jsonapi/tests/src/Functional/BlockContentTest.php index a0d689169c12e3d880429c97d4370209b8bffede..2e5308890e10aec4a773f08f19b764ea7bd12042 100644 --- a/web/core/modules/jsonapi/tests/src/Functional/BlockContentTest.php +++ b/web/core/modules/jsonapi/tests/src/Functional/BlockContentTest.php @@ -68,6 +68,11 @@ class BlockContentTest extends ResourceTestBase { protected function setUpAuthorization($method) { switch ($method) { case 'GET': + $this->grantPermissionsToTestedRole([ + 'access block library', + ]); + break; + case 'PATCH': $this->grantPermissionsToTestedRole([ 'access block library', @@ -86,6 +91,14 @@ protected function setUpAuthorization($method) { } } + /** + * {@inheritdoc} + */ + protected function setUpRevisionAuthorization($method) { + parent::setUpRevisionAuthorization($method); + $this->grantPermissionsToTestedRole(['view any basic block content history']); + } + /** * {@inheritdoc} */ diff --git a/web/core/modules/jsonapi/tests/src/Kernel/ResourceType/ResourceTypeRepositoryTest.php b/web/core/modules/jsonapi/tests/src/Kernel/ResourceType/ResourceTypeRepositoryTest.php index e7d5216e5c5eb7823a589d1d4ef1a4aedbc19b1d..88c60f7203cf11813a423e1b79b529f6b78d6cf5 100644 --- a/web/core/modules/jsonapi/tests/src/Kernel/ResourceType/ResourceTypeRepositoryTest.php +++ b/web/core/modules/jsonapi/tests/src/Kernel/ResourceType/ResourceTypeRepositoryTest.php @@ -90,7 +90,7 @@ public function testGet($entity_type_id, $bundle, $entity_class) { /** * Data provider for testGet. * - * @returns array + * @return array * The data for the test method. */ public function getProvider() { @@ -137,7 +137,7 @@ public function testMappingNameConflictCheck($field_name_list) { * mapping: the special-cased names "type" or "id", and the name * "{$entity_type_id}_type" or "{$entity_type_id}_id", respectively. * - * @returns array + * @return array * The data for the test method. */ public function getFieldsProvider() { diff --git a/web/core/modules/locale/locale.compare.inc b/web/core/modules/locale/locale.compare.inc index b07c5360c70bcd0d624d0817c2ae3f4c759c3de2..5a5a9c165ad5f657cc988a723cad784626f678d6 100644 --- a/web/core/modules/locale/locale.compare.inc +++ b/web/core/modules/locale/locale.compare.inc @@ -177,9 +177,6 @@ function locale_translation_default_translation_server() { * @param array $langcodes * Array of language codes. Defaults to all translatable languages. * - * @return array - * Available sources indexed by project and language. - * * @todo Return batch or NULL. */ function locale_translation_check_projects($projects = [], $langcodes = []) { diff --git a/web/core/modules/locale/src/PluralFormula.php b/web/core/modules/locale/src/PluralFormula.php index fc7fd88519faf1bc91a9870e24c5ded4afae5ef4..398fc0f2340cc2efa6c273f435938655f2dba657 100644 --- a/web/core/modules/locale/src/PluralFormula.php +++ b/web/core/modules/locale/src/PluralFormula.php @@ -93,8 +93,6 @@ public function getFormula($langcode) { /** * Loads the formulae and stores them on the PluralFormula object if not set. - * - * @return array */ protected function loadFormulae() { if (!isset($this->formulae)) { diff --git a/web/core/modules/migrate/src/Plugin/MigrationInterface.php b/web/core/modules/migrate/src/Plugin/MigrationInterface.php index 7936485997b76cdc555d9dbe9e9343c27980541c..132582852d7c153af4a3df34fb2ffef001fee640 100644 --- a/web/core/modules/migrate/src/Plugin/MigrationInterface.php +++ b/web/core/modules/migrate/src/Plugin/MigrationInterface.php @@ -106,7 +106,7 @@ public function label(); /** * Get a list of required plugin IDs. * - * @returns string[] + * @return string[] */ public function getRequirements(): array; diff --git a/web/core/modules/page_cache/src/StackMiddleware/PageCache.php b/web/core/modules/page_cache/src/StackMiddleware/PageCache.php index 05a70187e1ad03d82187afdd8a982b25fa7ff48c..07456a40976dadc56d1987efa2b8e72d5c83a9e5 100644 --- a/web/core/modules/page_cache/src/StackMiddleware/PageCache.php +++ b/web/core/modules/page_cache/src/StackMiddleware/PageCache.php @@ -99,7 +99,7 @@ public function handle(Request $request, $type = self::MAIN_REQUEST, $catch = TR * @param bool $catch * Whether to catch exceptions or not * - * @returns \Symfony\Component\HttpFoundation\Response $response + * @return \Symfony\Component\HttpFoundation\Response * A response object. */ protected function pass(Request $request, $type = self::MAIN_REQUEST, $catch = TRUE) { @@ -117,7 +117,7 @@ protected function pass(Request $request, $type = self::MAIN_REQUEST, $catch = T * @param bool $catch * Whether to catch exceptions or not * - * @returns \Symfony\Component\HttpFoundation\Response $response + * @return \Symfony\Component\HttpFoundation\Response * A response object. */ protected function lookup(Request $request, $type = self::MAIN_REQUEST, $catch = TRUE) { @@ -183,7 +183,7 @@ protected function lookup(Request $request, $type = self::MAIN_REQUEST, $catch = * @param bool $catch * Whether to catch exceptions or not * - * @returns \Symfony\Component\HttpFoundation\Response $response + * @return \Symfony\Component\HttpFoundation\Response * A response object. */ protected function fetch(Request $request, $type = self::MAIN_REQUEST, $catch = TRUE) { @@ -207,7 +207,8 @@ protected function fetch(Request $request, $type = self::MAIN_REQUEST, $catch = * @param \Symfony\Component\HttpFoundation\Response $response * A response object that should be stored in the page cache. * - * @returns bool + * @return bool + * TRUE if the response has been stored successfully, FALSE otherwise. */ protected function storeResponse(Request $request, Response $response) { // Drupal's primary cache invalidation architecture is cache tags: any diff --git a/web/core/modules/phpass/tests/src/Tests/LegacyPasswordHashingTest.php b/web/core/modules/phpass/tests/src/Unit/LegacyPasswordHashingTest.php similarity index 93% rename from web/core/modules/phpass/tests/src/Tests/LegacyPasswordHashingTest.php rename to web/core/modules/phpass/tests/src/Unit/LegacyPasswordHashingTest.php index b8064d84a3ad5d965163c932d84e199ccddb8240..586d20818ce9e2e67f65447667675f4e988b8ea5 100644 --- a/web/core/modules/phpass/tests/src/Tests/LegacyPasswordHashingTest.php +++ b/web/core/modules/phpass/tests/src/Unit/LegacyPasswordHashingTest.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\Tests\phpass\Password; +namespace Drupal\Tests\phpass\Unit; use Drupal\phpass\Password\PhpassHashedPassword; use Drupal\Tests\UnitTestCase; @@ -60,14 +60,6 @@ protected function setUp(): void { $this->md5HashedPassword = 'U' . $this->passwordHasher->hash(md5($this->password)); } - /** - * Tests invalid constructor arguments. - */ - public function testInvalidArguments() { - $this->expectException(\InvalidArgumentException::class); - new PhpassHashedPassword('not a number'); - } - /** * Tests a password needs update. * @@ -122,4 +114,14 @@ public function testPasswordRehashing() { $this->assertTrue($this->passwordHasher->check($this->password, $rehashed_password), 'Password check succeeds with re-hashed password with original hasher.'); } + /** + * Tests password validation when the hash is NULL. + * + * @covers ::check + */ + public function testEmptyHash(): void { + $this->assertFalse($this->passwordHasher->check($this->password, NULL)); + $this->assertFalse($this->passwordHasher->check($this->password, '')); + } + } diff --git a/web/core/modules/phpass/tests/src/Tests/PasswordVerifyTest.php b/web/core/modules/phpass/tests/src/Unit/PasswordVerifyTest.php similarity index 99% rename from web/core/modules/phpass/tests/src/Tests/PasswordVerifyTest.php rename to web/core/modules/phpass/tests/src/Unit/PasswordVerifyTest.php index 828eae0e9c10081725163c7dab23b0d9f4546cad..f080bd2396deff3b6516a04f6bdb86d703218ddc 100644 --- a/web/core/modules/phpass/tests/src/Tests/PasswordVerifyTest.php +++ b/web/core/modules/phpass/tests/src/Unit/PasswordVerifyTest.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\Tests\phpass\Password; +namespace Drupal\Tests\phpass\Unit; use Drupal\phpass\Password\PhpassHashedPassword; use Drupal\Core\Password\PasswordInterface; diff --git a/web/core/modules/rest/src/Routing/ResourceRoutes.php b/web/core/modules/rest/src/Routing/ResourceRoutes.php index a3cfe746057d253aa7a2ac0e5b6c0faa08482610..21fc270caa49ba77d41b9b91fc23c7ba51593ad5 100644 --- a/web/core/modules/rest/src/Routing/ResourceRoutes.php +++ b/web/core/modules/rest/src/Routing/ResourceRoutes.php @@ -58,8 +58,6 @@ public function __construct(ResourcePluginManager $manager, EntityTypeManagerInt * * @param \Drupal\Core\Routing\RouteBuildEvent $event * The route build event. - * - * @return array */ public function onDynamicRouteEvent(RouteBuildEvent $event) { // Iterate over all enabled REST resource config entities. diff --git a/web/core/modules/rest/tests/src/Functional/ResourceTestBase.php b/web/core/modules/rest/tests/src/Functional/ResourceTestBase.php index 5d32aa20bf43a40131eda444e74cf6a9ec66c0df..3b5fe5ec7d7fce0e057db133642721a0625da404 100644 --- a/web/core/modules/rest/tests/src/Functional/ResourceTestBase.php +++ b/web/core/modules/rest/tests/src/Functional/ResourceTestBase.php @@ -487,9 +487,6 @@ protected function decorateWithXdebugCookie(array $request_options) { * * @param array $array * An array to sort. - * - * @return array - * The sorted array. */ protected static function recursiveKSort(array &$array) { // First, sort the main array. @@ -501,8 +498,6 @@ protected static function recursiveKSort(array &$array) { static::recursiveKSort($value); } } - - return $array; } } diff --git a/web/core/modules/sdc/src/Element/ComponentElement.php b/web/core/modules/sdc/src/Element/ComponentElement.php index de540ae24d6351249ca573ffbebbf77aa81cb461..b7e259d762aee00611dab6ee9afcf9520a3a5d87 100644 --- a/web/core/modules/sdc/src/Element/ComponentElement.php +++ b/web/core/modules/sdc/src/Element/ComponentElement.php @@ -105,9 +105,14 @@ private function generateComponentTemplate( $template .= sprintf('{%% embed \'%s\' %%}', $id); $template .= PHP_EOL; foreach ($slots as $slot_name => $slot_value) { + if (\is_scalar($slot_value)) { + $slot_value = [ + "#plain_text" => (string) $slot_value, + ]; + } if (!Utilities::isRenderArray($slot_value)) { $message = sprintf( - 'Unable to render component "%s". A render array is expected for the slot "%s" when using the render element with the "#slots" property', + 'Unable to render component "%s". A render array or a scalar is expected for the slot "%s" when using the render element with the "#slots" property', $id, $slot_name ); diff --git a/web/core/modules/sdc/src/Twig/ComponentNodeVisitor.php b/web/core/modules/sdc/src/Twig/ComponentNodeVisitor.php index e7f2a928a5c56b1ca9d21bf545425bda99a0a1e8..5fdffa5c1e4069da52905db23ba255ad8707baeb 100644 --- a/web/core/modules/sdc/src/Twig/ComponentNodeVisitor.php +++ b/web/core/modules/sdc/src/Twig/ComponentNodeVisitor.php @@ -71,15 +71,25 @@ public function leaveNode(Node $node, Environment $env): ?Node { new Node([new ConstantExpression($component_id, $line)]), $line ), $line); - foreach ($print_nodes as $index => $print_node) { - $node->getNode('display_start')->setNode((string) $index, $print_node); - } + + // Append the print nodes to the display_start node. + $node->setNode( + 'display_start', + new Node([ + $node->getNode('display_start'), + ...$print_nodes, + ]), + ); + if ($env->isDebug()) { - $node->getNode('display_end') - ->setNode( - '0', - new PrintNode(new ConstantExpression(sprintf('<!-- %s Component end: %s -->', $emoji, $component_id), $line), $line) - ); + // Append the closing comment to the display_end node. + $node->setNode( + 'display_end', + new Node([ + new PrintNode(new ConstantExpression(sprintf('<!-- %s Component end: %s -->', $emoji, $component_id), $line), $line), + $node->getNode('display_end'), + ]) + ); } // Slots can be validated at compile time, we don't need to add nodes to // execute functions during display with the actual data. diff --git a/web/core/modules/sdc/tests/modules/sdc_other_node_visitor/sdc_other_node_visitor.info.yml b/web/core/modules/sdc/tests/modules/sdc_other_node_visitor/sdc_other_node_visitor.info.yml new file mode 100644 index 0000000000000000000000000000000000000000..ba20067f05346b92727c656cc4e4816d50f7bda7 --- /dev/null +++ b/web/core/modules/sdc/tests/modules/sdc_other_node_visitor/sdc_other_node_visitor.info.yml @@ -0,0 +1,5 @@ +name: 'Add another node visitor' +type: module +dependencies: + - sdc:sdc +package: Testing diff --git a/web/core/modules/sdc/tests/modules/sdc_other_node_visitor/sdc_other_node_visitor.services.yml b/web/core/modules/sdc/tests/modules/sdc_other_node_visitor/sdc_other_node_visitor.services.yml new file mode 100644 index 0000000000000000000000000000000000000000..38b78f5aced4cd216e5d36b1cdfafbf96c159c81 --- /dev/null +++ b/web/core/modules/sdc/tests/modules/sdc_other_node_visitor/sdc_other_node_visitor.services.yml @@ -0,0 +1,5 @@ +services: + sdc_other_node_visitor.twig.extension.profiler: + class: Drupal\sdc_other_node_visitor\Twig\Extension\TestProfilerExtension + tags: + - { name: twig.extension, priority: 100 } diff --git a/web/core/modules/sdc/tests/modules/sdc_other_node_visitor/src/Twig/Extension/TestProfilerExtension.php b/web/core/modules/sdc/tests/modules/sdc_other_node_visitor/src/Twig/Extension/TestProfilerExtension.php new file mode 100644 index 0000000000000000000000000000000000000000..78b19f319f94a747af22225aa0642476142b826e --- /dev/null +++ b/web/core/modules/sdc/tests/modules/sdc_other_node_visitor/src/Twig/Extension/TestProfilerExtension.php @@ -0,0 +1,34 @@ +<?php + +namespace Drupal\sdc_other_node_visitor\Twig\Extension; + +use Drupal\sdc_other_node_visitor\Twig\NodeVisitor\TestNodeVisitor; +use Twig\Extension\AbstractExtension; + +/** + * Twig extension to add a test node visitor. + */ +class TestProfilerExtension extends AbstractExtension { + + /** + * {@inheritdoc} + */ + public function getNodeVisitors(): array { + return [new TestNodeVisitor(static::class)]; + } + + /** + * Dummy function called when a Twig template is entered. + */ + public function enter() { + // NOOP. + } + + /** + * Dummy function called when a Twig template is left. + */ + public function leave() { + // NOOP. + } + +} diff --git a/web/core/modules/sdc/tests/modules/sdc_other_node_visitor/src/Twig/NodeVisitor/TestNodeVisitor.php b/web/core/modules/sdc/tests/modules/sdc_other_node_visitor/src/Twig/NodeVisitor/TestNodeVisitor.php new file mode 100644 index 0000000000000000000000000000000000000000..8e3305b83315e7bf724d7665c7ea9632d1b6c1cc --- /dev/null +++ b/web/core/modules/sdc/tests/modules/sdc_other_node_visitor/src/Twig/NodeVisitor/TestNodeVisitor.php @@ -0,0 +1,67 @@ +<?php + +namespace Drupal\sdc_other_node_visitor\Twig\NodeVisitor; + +use Drupal\sdc_other_node_visitor\Twig\Profiler\EnterProfileNode; +use Drupal\sdc_other_node_visitor\Twig\Profiler\LeaveProfileNode; +use Twig\Environment; +use Twig\Node\ModuleNode; +use Twig\Node\Node; +use Twig\NodeVisitor\NodeVisitorInterface; + +/** + * A node visitor that adds nodes to the Twig template. + * + * Most of this code is copied from + * Twig\Profiler\NodeVisitor\ProfilerNodeVisitor. + */ +final class TestNodeVisitor implements NodeVisitorInterface { + + private string $extensionName; + + private string $varName; + + /** + * TestNodeVisitor constructor. + * + * @param string $extensionName + * The name of the extension. + */ + public function __construct(string $extensionName) { + $this->extensionName = $extensionName; + $this->varName = sprintf('__internal_%s', hash(\PHP_VERSION_ID < 80100 ? 'sha256' : 'xxh128', $extensionName)); + } + + /** + * {@inheritdoc} + */ + public function enterNode(Node $node, Environment $env): Node { + return $node; + } + + /** + * {@inheritdoc} + */ + public function leaveNode(Node $node, Environment $env): ?Node { + if ($node instanceof ModuleNode) { + $node->setNode('display_start', new Node([ + new EnterProfileNode($this->extensionName, $this->varName), + $node->getNode('display_start'), + ])); + $node->setNode('display_end', new Node([ + new LeaveProfileNode($this->varName), + $node->getNode('display_end'), + ])); + } + + return $node; + } + + /** + * {@inheritdoc} + */ + public function getPriority(): int { + return 0; + } + +} diff --git a/web/core/modules/sdc/tests/modules/sdc_other_node_visitor/src/Twig/Profiler/EnterProfileNode.php b/web/core/modules/sdc/tests/modules/sdc_other_node_visitor/src/Twig/Profiler/EnterProfileNode.php new file mode 100644 index 0000000000000000000000000000000000000000..7e55b192682f59264288a56546a848232ae0d40e --- /dev/null +++ b/web/core/modules/sdc/tests/modules/sdc_other_node_visitor/src/Twig/Profiler/EnterProfileNode.php @@ -0,0 +1,30 @@ +<?php + +namespace Drupal\sdc_other_node_visitor\Twig\Profiler; + +use Twig\Compiler; +use Twig\Node\Node; + +/** + * Represents a profile enter node. + */ +class EnterProfileNode extends Node { + + public function __construct(string $extensionName, string $varName) { + parent::__construct([], [ + 'extension_name' => $extensionName, + 'var_name' => $varName, + ]); + } + + public function compile(Compiler $compiler): void { + $compiler + ->write(sprintf('$%s = $this->extensions[', $this->getAttribute('var_name'))) + /* cspell:disable-next-line */ + ->repr($this->getAttribute('extension_name')) + ->raw("];\n") + ->write(sprintf('$%s->enter();', $this->getAttribute('var_name'))) + ->raw("\n\n"); + } + +} diff --git a/web/core/modules/sdc/tests/modules/sdc_other_node_visitor/src/Twig/Profiler/LeaveProfileNode.php b/web/core/modules/sdc/tests/modules/sdc_other_node_visitor/src/Twig/Profiler/LeaveProfileNode.php new file mode 100644 index 0000000000000000000000000000000000000000..52e86a4c9c939abef2d8f2fe79341658185c3fb4 --- /dev/null +++ b/web/core/modules/sdc/tests/modules/sdc_other_node_visitor/src/Twig/Profiler/LeaveProfileNode.php @@ -0,0 +1,23 @@ +<?php + +namespace Drupal\sdc_other_node_visitor\Twig\Profiler; + +use Twig\Compiler; +use Twig\Node\Node; + +/** + * Represents a profile leave node. + */ +class LeaveProfileNode extends Node { + + public function __construct(string $varName) { + parent::__construct([], ['var_name' => $varName]); + } + + public function compile(Compiler $compiler): void { + $compiler + ->write("\n") + ->write(sprintf("\$%s->leave();\n\n", $this->getAttribute('var_name'))); + } + +} diff --git a/web/core/modules/sdc/tests/src/Kernel/ComponentNodeVisitorTest.php b/web/core/modules/sdc/tests/src/Kernel/ComponentNodeVisitorTest.php new file mode 100644 index 0000000000000000000000000000000000000000..ef541d0aa532c7dbd0ec910e163a3d17a8331be6 --- /dev/null +++ b/web/core/modules/sdc/tests/src/Kernel/ComponentNodeVisitorTest.php @@ -0,0 +1,39 @@ +<?php + +namespace Drupal\Tests\sdc\Kernel; + +/** + * Tests the node visitor. + * + * @coversDefaultClass \Drupal\sdc\Twig\ComponentNodeVisitor + * @group sdc + * + * @internal + */ +final class ComponentNodeVisitorTest extends ComponentKernelTestBase { + + /** + * {@inheritdoc} + */ + protected static $modules = ['sdc', 'sdc_other_node_visitor']; + + /** + * {@inheritdoc} + */ + protected static $themes = ['sdc_theme_test']; + + /** + * Test that other visitors can modify Twig nodes. + */ + public function testOtherVisitorsCanModifyTwigNodes(): void { + $build = [ + '#type' => 'inline_template', + '#template' => "{% embed('sdc_theme_test_base:my-card-no-schema') %}{% block card_body %}Foo bar{% endblock %}{% endembed %}", + ]; + $this->renderComponentRenderArray($build); + + // If this is reached, the test passed. + $this->assertTrue(TRUE); + } + +} diff --git a/web/core/modules/sdc/tests/src/Kernel/ComponentRenderTest.php b/web/core/modules/sdc/tests/src/Kernel/ComponentRenderTest.php index 174a2dcbbe4d83f5a498da41f486c44669c08115..d4ea6194ebe8226afda0f6833e1edef697784caf 100644 --- a/web/core/modules/sdc/tests/src/Kernel/ComponentRenderTest.php +++ b/web/core/modules/sdc/tests/src/Kernel/ComponentRenderTest.php @@ -42,6 +42,7 @@ public function testRender(): void { $this->checkLibraryOverrides(); $this->checkAttributeMerging(); $this->checkRenderElementAlters(); + $this->checkSlots(); $this->checkInvalidSlot(); } @@ -284,7 +285,36 @@ public function checkRenderElementAlters(): void { } /** - * Ensure that the slots receive a render array when using the render element. + * Ensure that the slots allow a render array or a scalar when using the render element. + */ + public function checkSlots(): void { + $slots = [ + 'This is the contents of the banner body.', + [ + '#plain_text' => 'This is the contents of the banner body.', + ], + ]; + foreach ($slots as $slot) { + $build = [ + '#type' => 'component', + '#component' => 'sdc_test:my-banner', + '#props' => [ + 'heading' => $this->t('I am a banner'), + 'ctaText' => $this->t('Click me'), + 'ctaHref' => 'https://www.example.org', + 'ctaTarget' => '', + ], + '#slots' => [ + 'banner_body' => $slot, + ], + ]; + $crawler = $this->renderComponentRenderArray($build); + $this->assertNotEmpty($crawler->filter('#sdc-wrapper [data-component-id="sdc_test:my-banner"] .component--my-banner--body:contains("This is the contents of the banner body.")')); + } + } + + /** + * Ensure that the slots throw an error for invalid slots. */ public function checkInvalidSlot(): void { $build = [ @@ -297,11 +327,11 @@ public function checkInvalidSlot(): void { 'ctaTarget' => '', ], '#slots' => [ - 'banner_body' => 'I am an invalid render array.', + 'banner_body' => new \stdClass(), ], ]; $this->expectException(InvalidComponentDataException::class); - $this->expectExceptionMessage('Unable to render component "sdc_test:my-banner". A render array is expected for the slot "banner_body" when using the render element with the "#slots" property'); + $this->expectExceptionMessage('Unable to render component "sdc_test:my-banner". A render array or a scalar is expected for the slot "banner_body" when using the render element with the "#slots" property'); $this->renderComponentRenderArray($build); } diff --git a/web/core/modules/serialization/src/Normalizer/DateTimeNormalizer.php b/web/core/modules/serialization/src/Normalizer/DateTimeNormalizer.php index c1fdf1fb1834ed9f4ddbbbb8ba8c003e90baee4c..83ffe156fe6e6ebaa5ae5c09016dcc4c19697286 100644 --- a/web/core/modules/serialization/src/Normalizer/DateTimeNormalizer.php +++ b/web/core/modules/serialization/src/Normalizer/DateTimeNormalizer.php @@ -69,7 +69,7 @@ public function normalize($datetime, $format = NULL, array $context = []): array * @see ::normalize * @see \Drupal\Core\Datetime\DrupalDateTime::prepareTimezone() * - * @returns \DateTimeZone + * @return \DateTimeZone * The timezone to use. */ protected function getNormalizationTimezone() { diff --git a/web/core/modules/system/src/Controller/AssetControllerBase.php b/web/core/modules/system/src/Controller/AssetControllerBase.php index 7a161a5d7e47aa08fea81bec61abed680425757c..3c662294a2e49cc18bbbd579a00de0d49696e931 100644 --- a/web/core/modules/system/src/Controller/AssetControllerBase.php +++ b/web/core/modules/system/src/Controller/AssetControllerBase.php @@ -195,11 +195,7 @@ public function deliver(Request $request, string $file_name) { // from filling the disk, while still serving aggregates that may be // referenced in cached HTML. if (hash_equals($generated_hash, $received_hash)) { - $uri = $this->dumper->dumpToUri($data, $this->assetType, $uri); - $state_key = 'drupal_' . $this->assetType . '_cache_files'; - $files = $this->state()->get($state_key, []); - $files[] = $uri; - $this->state()->set($state_key, $files); + $this->dumper->dumpToUri($data, $this->assetType, $uri); } return new Response($data, 200, [ 'Cache-control' => static::CACHE_CONTROL, diff --git a/web/core/modules/system/tests/modules/ajax_test/ajax_test.routing.yml b/web/core/modules/system/tests/modules/ajax_test/ajax_test.routing.yml index 12e65477897736f2e4e97b6ea89c8b13a134e5c4..b846939a6e076f80c7e38f90fa21ef034b5d917b 100644 --- a/web/core/modules/system/tests/modules/ajax_test/ajax_test.routing.yml +++ b/web/core/modules/system/tests/modules/ajax_test/ajax_test.routing.yml @@ -129,3 +129,19 @@ ajax_test.throw_exception: _controller: '\Drupal\ajax_test\Controller\AjaxTestController::throwException' requirements: _access: 'TRUE' + +ajax_test.http_methods: + path: '/ajax-test/http-methods' + defaults: + _controller: Drupal\ajax_test\Controller\AjaxTestController::httpMethods + requirements: + _access: 'TRUE' + options: + no_cache: TRUE + +ajax_test.http_methods.dialog: + path: '/ajax-test/http-methods-dialog' + defaults: + _controller: Drupal\ajax_test\Controller\AjaxTestController::httpMethodsDialog + requirements: + _access: 'TRUE' diff --git a/web/core/modules/system/tests/modules/ajax_test/src/Controller/AjaxTestController.php b/web/core/modules/system/tests/modules/ajax_test/src/Controller/AjaxTestController.php index ad883b145e7f9d4c387a396e001a14081098c6b2..b91b37d038e7d9b005cb3e757f133c58ce6eda75 100644 --- a/web/core/modules/system/tests/modules/ajax_test/src/Controller/AjaxTestController.php +++ b/web/core/modules/system/tests/modules/ajax_test/src/Controller/AjaxTestController.php @@ -2,6 +2,7 @@ namespace Drupal\ajax_test\Controller; +use Drupal\Component\Serialization\Json; use Drupal\Core\Ajax\AjaxResponse; use Drupal\Core\Ajax\AlertCommand; use Drupal\Core\Ajax\CloseDialogCommand; @@ -419,4 +420,41 @@ public function exceptionLink() { ]; } + /** + * Provides an Ajax link used with different HTTP methods. + * + * @return array + * The AJAX link. + */ + public function httpMethods(): array { + return [ + '#type' => 'link', + '#title' => 'Link', + '#url' => Url::fromRoute('ajax_test.http_methods.dialog'), + '#attributes' => [ + 'class' => ['use-ajax'], + 'data-dialog-type' => 'modal', + 'data-dialog-options' => Json::encode(['width' => 800]), + // Use this state var to change the HTTP method in tests. + // @see \Drupal\FunctionalJavascriptTests\Ajax\DialogTest::testHttpMethod() + 'data-ajax-http-method' => \Drupal::state()->get('ajax_test.http_method', 'POST'), + ], + '#attached' => [ + 'library' => [ + 'core/drupal.dialog.ajax', + ], + ], + ]; + } + + /** + * Provides a modal dialog to test links with different HTTP methods. + * + * @return array + * The render array. + */ + public function httpMethodsDialog(): array { + return ['#markup' => 'Modal dialog contents']; + } + } diff --git a/web/core/modules/system/tests/modules/decoupled_menus_test/decoupled_menus_test.info.yml b/web/core/modules/system/tests/modules/decoupled_menus_test/decoupled_menus_test.info.yml index 40b4a30052762a0d8821a817784e617a9fe2a303..3d3cf4403e54551ea7df609d452a9ac89006eec0 100644 --- a/web/core/modules/system/tests/modules/decoupled_menus_test/decoupled_menus_test.info.yml +++ b/web/core/modules/system/tests/modules/decoupled_menus_test/decoupled_menus_test.info.yml @@ -4,5 +4,5 @@ description: 'Support module for decoupled_menus endpoint.' package: Testing version: VERSION dependencies: - drupal:rest - drupal:user + - drupal:rest + - drupal:user diff --git a/web/core/modules/system/tests/modules/router_test_directory/src/TestContent.php b/web/core/modules/system/tests/modules/router_test_directory/src/TestContent.php index 7f4166078b0eaaf0d2b637cb55f5e6ac66938faf..38ec6982ed12e60cf97a0bd767a1be6e4485c710 100644 --- a/web/core/modules/system/tests/modules/router_test_directory/src/TestContent.php +++ b/web/core/modules/system/tests/modules/router_test_directory/src/TestContent.php @@ -44,7 +44,7 @@ public function test1() { /** * Provides example content for route specific authentication. * - * @returns string + * @return string * The user name of the current logged in user. */ public function test11() { diff --git a/web/core/modules/views/src/Plugin/views/field/EntityLink.php b/web/core/modules/views/src/Plugin/views/field/EntityLink.php index 3ebe91a109cbda23758690d4ef290a59c79b1209..b96d1d445cc5bc3730cba74d71a06ad5a567193f 100644 --- a/web/core/modules/views/src/Plugin/views/field/EntityLink.php +++ b/web/core/modules/views/src/Plugin/views/field/EntityLink.php @@ -50,7 +50,7 @@ protected function getUrlInfo(ResultRow $row) { /** * Returns the entity link template name identifying the link route. * - * @returns string + * @return string * The link template name. */ protected function getEntityLinkTemplate() { diff --git a/web/core/package.json b/web/core/package.json index 2450d4d499257fd3cf87f26489eaffb89a9f6a4b..7196bd4c00205f9b2f5296a41d14d37afab7264d 100644 --- a/web/core/package.json +++ b/web/core/package.json @@ -78,7 +78,7 @@ "mkdirp": "^3.0.1", "nightwatch": "^2.3.9", "normalize.css": "8.0.x", - "postcss": "^8.4.24", + "postcss": "^8.4.31", "postcss-header": "^3.0.2", "postcss-import": "^15.0.0", "postcss-preset-env": "^8.4.2", diff --git a/web/core/phpstan-baseline.neon b/web/core/phpstan-baseline.neon index 113f73abdc042d40f84370498d2c54f371342439..8b902e8e670c0c10f60037a270353f63098c8226 100644 --- a/web/core/phpstan-baseline.neon +++ b/web/core/phpstan-baseline.neon @@ -425,16 +425,6 @@ parameters: count: 2 path: lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php - - - message: "#^Method Drupal\\\\Core\\\\Entity\\\\Sql\\\\SqlContentEntityStorageSchema\\:\\:processDataTable\\(\\) should return array but return statement is missing\\.$#" - count: 1 - path: lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php - - - - message: "#^Method Drupal\\\\Core\\\\Entity\\\\Sql\\\\SqlContentEntityStorageSchema\\:\\:processRevisionDataTable\\(\\) should return array but return statement is missing\\.$#" - count: 1 - path: lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php - - message: "#^Variable \\$initial_storage_value in empty\\(\\) always exists and is not falsy\\.$#" count: 1 @@ -1370,11 +1360,6 @@ parameters: count: 1 path: modules/locale/locale.bulk.inc - - - message: "#^Function locale_translation_check_projects\\(\\) should return array but return statement is missing\\.$#" - count: 1 - path: modules/locale/locale.compare.inc - - message: "#^Variable \\$item in empty\\(\\) always exists and is not falsy\\.$#" count: 1 @@ -1400,11 +1385,6 @@ parameters: count: 1 path: modules/locale/src/LocaleProjectStorage.php - - - message: "#^Method Drupal\\\\locale\\\\PluralFormula\\:\\:loadFormulae\\(\\) should return array but return statement is missing\\.$#" - count: 1 - path: modules/locale/src/PluralFormula.php - - message: "#^Method Drupal\\\\locale\\\\PoDatabaseReader\\:\\:readItem\\(\\) should return Drupal\\\\Component\\\\Gettext\\\\PoItem but return statement is missing\\.$#" count: 1 @@ -1820,11 +1800,6 @@ parameters: count: 1 path: modules/responsive_image/src/ResponsiveImageStyleForm.php - - - message: "#^Method Drupal\\\\rest\\\\Routing\\\\ResourceRoutes\\:\\:onDynamicRouteEvent\\(\\) should return array but return statement is missing\\.$#" - count: 1 - path: modules/rest/src/Routing/ResourceRoutes.php - - message: "#^Variable \\$created_entity might not be defined\\.$#" count: 4 diff --git a/web/core/profiles/demo_umami/themes/umami/css/classy/components/form.css b/web/core/profiles/demo_umami/themes/umami/css/components/forms/form.css similarity index 96% rename from web/core/profiles/demo_umami/themes/umami/css/classy/components/form.css rename to web/core/profiles/demo_umami/themes/umami/css/components/forms/form.css index 302e279771ff909863db3a05923ef40e5c6fd874..a07557d3449c9e776ece7c8ac7ab225ae3c044d7 100644 --- a/web/core/profiles/demo_umami/themes/umami/css/classy/components/form.css +++ b/web/core/profiles/demo_umami/themes/umami/css/components/forms/form.css @@ -78,7 +78,7 @@ label.option { content: ""; vertical-align: super; /* Use a background image to prevent screen readers from announcing the text. */ - background-image: url(../../../../../../../misc/icons/ee0000/required.svg); + background-image: url(../../../images/svg/e40000/required.svg); background-repeat: no-repeat; background-size: 6px 6px; } diff --git a/web/core/profiles/demo_umami/themes/umami/images/svg/e40000/required.svg b/web/core/profiles/demo_umami/themes/umami/images/svg/e40000/required.svg new file mode 100644 index 0000000000000000000000000000000000000000..d837dbccc0ba7397b3b3f52e2172830d0938274e --- /dev/null +++ b/web/core/profiles/demo_umami/themes/umami/images/svg/e40000/required.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#E40000" d="M0,7.562l1.114-3.438c2.565,0.906,4.43,1.688,5.59,2.35C6.398,3.553,6.237,1.544,6.22,0.447h3.511 c-0.05,1.597-0.234,3.6-0.558,6.003c1.664-0.838,3.566-1.613,5.714-2.325L16,7.562c-2.05,0.678-4.06,1.131-6.028,1.356 c0.984,0.856,2.372,2.381,4.166,4.575l-2.906,2.059c-0.935-1.274-2.041-3.009-3.316-5.206c-1.194,2.275-2.244,4.013-3.147,5.206 l-2.856-2.059c1.872-2.307,3.211-3.832,4.017-4.575C3.849,8.516,1.872,8.062,0,7.562"/></svg> diff --git a/web/core/profiles/demo_umami/themes/umami/umami.libraries.yml b/web/core/profiles/demo_umami/themes/umami/umami.libraries.yml index 800006c1be10d5f2707d9a463daebc08daa5995a..fec00e792c1b718bf60803b0713ec6b4dbb9b8d5 100644 --- a/web/core/profiles/demo_umami/themes/umami/umami.libraries.yml +++ b/web/core/profiles/demo_umami/themes/umami/umami.libraries.yml @@ -13,6 +13,7 @@ global: css/components/blocks/search/search-results.css: {} css/components/blocks/articles-aside/articles-aside.css: {} css/components/forms/contact.css: {} + css/components/forms/form.css: { weight: -10 } css/components/forms/content-moderation.css: {} css/components/content/node.css: {} css/components/content/full/node-full.css: {} @@ -137,7 +138,6 @@ classy.base: css/classy/components/details.css: { weight: -10 } css/classy/components/exposed-filters.css: { weight: -10 } css/classy/components/field.css: { weight: -10 } - css/classy/components/form.css: { weight: -10 } css/classy/components/icons.css: { weight: -10 } css/classy/components/inline-form.css: { weight: -10 } css/classy/components/item-list.css: { weight: -10 } diff --git a/web/core/tests/Drupal/BuildTests/Framework/BuildTestBase.php b/web/core/tests/Drupal/BuildTests/Framework/BuildTestBase.php index d700a13f4b0d8d5775d3bdf8c0ddf847bf274687..f9ca183233a207ad73726ea66428ec05a1ed8f17 100644 --- a/web/core/tests/Drupal/BuildTests/Framework/BuildTestBase.php +++ b/web/core/tests/Drupal/BuildTests/Framework/BuildTestBase.php @@ -546,9 +546,8 @@ protected function getPortNumber() { * Use this method to copy the current codebase, including any patched * changes, into the workspace. * - * By default, the copy will exclude sites/default/settings.php, - * sites/default/files, and vendor/. Use the $iterator parameter to override - * this behavior. + * By default, the copy will exclude site-specific and build-related files and + * directories. Use the $iterator parameter to override this behavior. * * @param \Iterator|null $iterator * (optional) An iterator of all the files to copy. Default behavior is to @@ -589,6 +588,7 @@ public function getCodebaseFinder() { ->notPath('#^sites/default/files#') ->notPath('#^sites/simpletest#') ->notPath('#^vendor#') + ->notPath('#^core/node_modules#') ->notPath('#^sites/default/settings\..*php#') ->ignoreDotFiles(FALSE) ->ignoreVCS(FALSE); diff --git a/web/core/tests/Drupal/FunctionalJavascriptTests/Ajax/DialogTest.php b/web/core/tests/Drupal/FunctionalJavascriptTests/Ajax/DialogTest.php index 5ea74a35078a06a22c3b66bffb1813a829cc232e..1a537175db5c43fb991f68a57bec3a97592cb664 100644 --- a/web/core/tests/Drupal/FunctionalJavascriptTests/Ajax/DialogTest.php +++ b/web/core/tests/Drupal/FunctionalJavascriptTests/Ajax/DialogTest.php @@ -188,4 +188,38 @@ public function testDialog() { $this->assertNotNull($form_title, 'The add form title is as expected.'); } + /** + * Tests dialog link opener with different HTTP methods. + */ + public function testHttpMethod(): void { + $assert = $this->assertSession(); + $script = <<<SCRIPT + (function() { + return document.querySelector('div[aria-describedby="drupal-modal"]').offsetWidth; + }()) + SCRIPT; + + // Open the modal dialog with POST HTTP method. + $this->drupalGet('/ajax-test/http-methods'); + $this->clickLink('Link'); + $assert->assertWaitOnAjaxRequest(); + $assert->pageTextContains('Modal dialog contents'); + $width = $this->getSession()->getDriver()->evaluateScript($script); + // The theme is adding 4px as padding and border on each side. + $this->assertSame(808, $width); + + // Switch to GET HTTP method. + // @see \Drupal\ajax_test\Controller\AjaxTestController::httpMethods() + \Drupal::state()->set('ajax_test.http_method', 'GET'); + + // Open the modal dialog with GET HTTP method. + $this->drupalGet('/ajax-test/http-methods'); + $this->clickLink('Link'); + $assert->assertWaitOnAjaxRequest(); + $assert->pageTextContains('Modal dialog contents'); + $width = $this->getSession()->getDriver()->evaluateScript($script); + // The theme is adding 4px as padding and border on each side. + $this->assertSame(808, $width); + } + } diff --git a/web/core/tests/Drupal/KernelTests/Core/Condition/ConditionPluginCollectionTest.php b/web/core/tests/Drupal/KernelTests/Core/Condition/ConditionPluginCollectionTest.php new file mode 100644 index 0000000000000000000000000000000000000000..b0f1c9ebafe8d7df61a50080d85e5586239f436d --- /dev/null +++ b/web/core/tests/Drupal/KernelTests/Core/Condition/ConditionPluginCollectionTest.php @@ -0,0 +1,58 @@ +<?php + +namespace Drupal\KernelTests\Core\Condition; + +use Drupal\Core\Condition\ConditionPluginCollection; +use Drupal\KernelTests\KernelTestBase; + +/** + * @coversDefaultClass \Drupal\Core\Condition\ConditionPluginCollection + * + * @group Condition + */ +class ConditionPluginCollectionTest extends KernelTestBase { + + /** + * {@inheritdoc} + */ + protected static $modules = [ + 'system', + 'user', + 'path_alias', + ]; + + /** + * @covers ::getConfiguration + */ + public function testGetConfiguration(): void { + // Include a condition that has custom configuration and a type mismatch on + // 'negate' by using 0 instead of FALSE. + $configuration['request_path'] = [ + 'id' => 'request_path', + 'negate' => 0, + 'context_mapping' => [], + 'pages' => '/user/*', + ]; + // Include a condition that matches default values but with a type mismatch + // on 'negate' by using 0 instead of FALSE. This condition will be removed, + // because condition configurations that match default values with "==" + // comparison are not saved or exported. + $configuration['user_role'] = [ + 'id' => 'user_role', + 'negate' => '0', + 'context_mapping' => [], + 'roles' => [], + ]; + $collection = new ConditionPluginCollection(\Drupal::service('plugin.manager.condition'), $configuration); + + $expected['request_path'] = [ + 'id' => 'request_path', + 'negate' => 0, + 'context_mapping' => [], + 'pages' => '/user/*', + ]; + // NB: The 'user_role' property should not exist in expected set. + $this->assertSame($expected, $collection->getConfiguration()); + } + +} diff --git a/web/core/tests/Drupal/KernelTests/Core/Config/ConfigImporterTest.php b/web/core/tests/Drupal/KernelTests/Core/Config/ConfigImporterTest.php index 2ab3c547fdbe36fc9fb7f1f5c881cf12e61a74c6..e7f13b762552961e0ecf07b8d79d02009f6ce504 100644 --- a/web/core/tests/Drupal/KernelTests/Core/Config/ConfigImporterTest.php +++ b/web/core/tests/Drupal/KernelTests/Core/Config/ConfigImporterTest.php @@ -4,6 +4,7 @@ use Drupal\Component\Utility\Html; use Drupal\Component\Render\FormattableMarkup; +use Drupal\Core\Config\ConfigEvents; use Drupal\Core\Config\ConfigImporter; use Drupal\Core\Config\ConfigImporterException; use Drupal\KernelTests\KernelTestBase; @@ -25,7 +26,7 @@ class ConfigImporterTest extends KernelTestBase { * * @var array */ - protected static $modules = ['config_test', 'system', 'config_import_test']; + protected static $modules = ['config_test', 'system', 'config_import_test', 'config_events_test']; /** * {@inheritdoc} @@ -899,6 +900,26 @@ public function testUninstallThemeIncrementsCount(): void { $this->assertEquals(0, $this->config($cronName)->get('logging')); } + /** + * Tests config events during config import. + */ + public function testConfigEvents(): void { + $this->installConfig(['config_events_test']); + $this->config('config_events_test.test')->set('key', 'bar')->save(); + $this->copyConfig($this->container->get('config.storage'), $this->container->get('config.storage.sync')); + $this->config('config_events_test.test')->set('key', 'foo')->save(); + \Drupal::state()->set('config_events_test.event', []); + + // Import the configuration. This results in a save event with the value + // changing from foo to bar. + $this->configImporter()->import(); + $event = \Drupal::state()->get('config_events_test.event', []); + $this->assertSame(ConfigEvents::SAVE, $event['event_name']); + $this->assertSame(['key' => 'bar'], $event['current_config_data']); + $this->assertSame(['key' => 'bar'], $event['raw_config_data']); + $this->assertSame(['key' => 'foo'], $event['original_config_data']); + } + /** * Helper method to test custom config installer steps. * diff --git a/web/core/tests/Drupal/KernelTests/Core/DependencyInjection/AutowireTest.php b/web/core/tests/Drupal/KernelTests/Core/DependencyInjection/AutowireTest.php index ac8246c8ef86fdb0c4bdb90db943925c15d02bb8..4e405fd908b196855f84be642e80107084a20f22 100644 --- a/web/core/tests/Drupal/KernelTests/Core/DependencyInjection/AutowireTest.php +++ b/web/core/tests/Drupal/KernelTests/Core/DependencyInjection/AutowireTest.php @@ -101,7 +101,9 @@ public function testCoreServiceAliases(): void { } } - $this->assertSame($expected, array_intersect($expected, $aliases)); + $missing = array_diff($expected, $aliases); + $formatted = Yaml::encode(array_map(fn ($alias) => sprintf('@%s', $alias), $missing)); + $this->assertSame($expected, array_intersect($expected, $aliases), sprintf('The following core services do not have map the class name to an alias. Add the following to core.services.yml in the appropriate place: %s%s%s', \PHP_EOL, \PHP_EOL, $formatted)); } } diff --git a/web/core/tests/Drupal/KernelTests/Core/Entity/EntityTypeTest.php b/web/core/tests/Drupal/KernelTests/Core/Entity/EntityTypeTest.php index 6b47489844f6656492d57de02d05adf90eb10146..789b38caceaa7ff4561caee9bf8faab62add8dbe 100644 --- a/web/core/tests/Drupal/KernelTests/Core/Entity/EntityTypeTest.php +++ b/web/core/tests/Drupal/KernelTests/Core/Entity/EntityTypeTest.php @@ -43,7 +43,7 @@ public function __construct() { } /** - * @return array + * Always throw an exception. */ public function __serialize(): array { throw new \Exception(); diff --git a/web/core/tests/Drupal/KernelTests/Core/EventSubscriber/ExceptionLoggingSubscriberTest.php b/web/core/tests/Drupal/KernelTests/Core/EventSubscriber/ExceptionLoggingSubscriberTest.php new file mode 100644 index 0000000000000000000000000000000000000000..b15ecff3f0fee6678689f2519ed90e357583bf57 --- /dev/null +++ b/web/core/tests/Drupal/KernelTests/Core/EventSubscriber/ExceptionLoggingSubscriberTest.php @@ -0,0 +1,81 @@ +<?php + +namespace Drupal\KernelTests\Core\EventSubscriber; + +use Drupal\Core\DependencyInjection\ContainerBuilder; +use Drupal\KernelTests\KernelTestBase; +use Symfony\Component\ErrorHandler\BufferingLogger; +use Symfony\Component\HttpFoundation\Request; + +/** + * Tests that HTTP exceptions are logged correctly. + * + * @group system + */ +class ExceptionLoggingSubscriberTest extends KernelTestBase { + + /** + * The service name for a logger implementation that collects anything logged. + * + * @var string + */ + protected $testLogServiceName = 'exception_logging_subscriber_test.logger'; + + /** + * {@inheritdoc} + */ + protected static $modules = ['system', 'test_page_test']; + + /** + * Tests \Drupal\Core\EventSubscriber\ExceptionLoggingSubscriber::onException(). + */ + public function testExceptionLogging() { + $http_kernel = \Drupal::service('http_kernel'); + + $channel_map = [ + 400 => 'client error', + 401 => 'client error', + 403 => 'access denied', + 404 => 'page not found', + 405 => 'client error', + 408 => 'client error', + // Do not check the 500 status code here because it would be caught by + // Drupal\Core\EventSubscriberExceptionTestSiteSubscriber which has lower + // priority. + 501 => 'php', + 502 => 'php', + 503 => 'php', + ]; + + // Ensure that noting is logged. + $this->assertEmpty($this->container->get($this->testLogServiceName)->cleanLogs()); + + // Temporarily disable error log as the ExceptionLoggingSubscriber logs 5xx + // HTTP errors using error_log(). + $error_log = ini_set('error_log', '/dev/null'); + foreach ($channel_map as $code => $channel) { + $request = Request::create('/test-http-response-exception/' . $code); + $http_kernel->handle($request); + } + ini_set('error_log', $error_log); + + $expected_channels = array_values($channel_map); + + $logs = $this->container->get($this->testLogServiceName)->cleanLogs(); + foreach ($expected_channels as $key => $expected_channel) { + $log_message = $logs[$key][2]['channel']; + $this->assertEquals($expected_channel, $log_message); + } + } + + /** + * {@inheritdoc} + */ + public function register(ContainerBuilder $container) { + parent::register($container); + $container + ->register($this->testLogServiceName, BufferingLogger::class) + ->addTag('logger'); + } + +} diff --git a/web/core/tests/Drupal/KernelTests/Core/Field/Entity/BaseFieldOverrideTest.php b/web/core/tests/Drupal/KernelTests/Core/Field/Entity/BaseFieldOverrideTest.php index 9ddfa59acc143e3eef489c4a2b3a10161af5cba7..92c1b98cc047137499100fb9b53a612983896a9d 100644 --- a/web/core/tests/Drupal/KernelTests/Core/Field/Entity/BaseFieldOverrideTest.php +++ b/web/core/tests/Drupal/KernelTests/Core/Field/Entity/BaseFieldOverrideTest.php @@ -82,6 +82,38 @@ public function testDefaultValueCallback() { $this->assertEquals([['target_id' => 99]], $base_field_override->getDefaultValue($entity)); } + /** + * Tests that some properties are inherited from the BaseFieldDefinition. + * + * @covers ::isReadOnly + * @covers ::isComputed + * @covers ::isInternal + * @covers ::getUniqueIdentifier + */ + public function testInheritedProperties() { + $base_field = BaseFieldDefinition::create('string') + ->setName('Test Field') + ->setTargetEntityTypeId('entity_test') + ->setReadOnly(TRUE) + /** Ensure that the internal property is inherited from the base field and not the parent class. @see FieldConfigBase::isInternal */ + ->setInternal(TRUE) + ->setComputed(FALSE); + + // Getters of the properties to check. + $methods = [ + 'getUniqueIdentifier', + 'getClass', + 'isComputed', + 'isReadOnly', + 'isInternal', + ]; + + $override = BaseFieldOverride::createFromBaseFieldDefinition($base_field, 'test_bundle'); + foreach ($methods as $method) { + $this->assertEquals($base_field->$method(), $override->$method()); + } + } + /** * A default value callback which returns a primitive value. * diff --git a/web/core/tests/Drupal/Tests/Component/Datetime/TimeTest.php b/web/core/tests/Drupal/Tests/Component/Datetime/TimeTest.php index 98dc0e6b53d836733501aa4409a048eecb5754cd..83c5a3e86ad236a86778a3469e4400538edb6e9b 100644 --- a/web/core/tests/Drupal/Tests/Component/Datetime/TimeTest.php +++ b/web/core/tests/Drupal/Tests/Component/Datetime/TimeTest.php @@ -128,7 +128,7 @@ public function testGetCurrentMicroTime() { /** * Shadow time() system call. * - * @returns int + * @return int */ function time() { return 12345678; @@ -137,7 +137,7 @@ function time() { /** * Shadow microtime system call. * - * @returns float + * @return float */ function microtime() { return 1234567.89; diff --git a/web/core/tests/Drupal/Tests/Core/Asset/JsOptimizerUnitTest.php b/web/core/tests/Drupal/Tests/Core/Asset/JsOptimizerUnitTest.php index 3c4623ab228fdb1c3df9573a041dce6b8a046296..cc2596566c770ad2652c8ce074beb8ca87a718e5 100644 --- a/web/core/tests/Drupal/Tests/Core/Asset/JsOptimizerUnitTest.php +++ b/web/core/tests/Drupal/Tests/Core/Asset/JsOptimizerUnitTest.php @@ -33,7 +33,7 @@ protected function setUp(): void { * * @see \Drupal\Core\Asset\JsOptimizer::clean() * - * @returns array + * @return array * An array of test data. */ public function providerTestClean() { @@ -80,7 +80,7 @@ public function testClean($js_asset, $expected) { * * @see \Drupal\Core\Asset\JsOptimizer::optimize() * - * @returns array + * @return array * An array of test data. */ public function providerTestOptimize() { diff --git a/web/core/tests/Drupal/Tests/Core/DrupalKernel/DrupalKernelTest.php b/web/core/tests/Drupal/Tests/Core/DrupalKernel/DrupalKernelTest.php index 4efda0785bfc33bb289b8fc1e7839cdf91d9d533..cb04af7ff54405ba7b4e0fa36671f5202a2d61b5 100644 --- a/web/core/tests/Drupal/Tests/Core/DrupalKernel/DrupalKernelTest.php +++ b/web/core/tests/Drupal/Tests/Core/DrupalKernel/DrupalKernelTest.php @@ -177,8 +177,7 @@ public function unregister() { /** * Loads the given class or interface. * - * @return null - * This class never loads. + * This class never loads. */ public function loadClass() { return NULL; @@ -187,8 +186,7 @@ public function loadClass() { /** * Finds a file by class name while caching lookups to APC. * - * @return null - * This class never finds. + * This class never finds. */ public function findFile() { return NULL; diff --git a/web/core/tests/Drupal/Tests/Core/Entity/ContentEntityBaseUnitTest.php b/web/core/tests/Drupal/Tests/Core/Entity/ContentEntityBaseUnitTest.php index 5da25e326fb61ea95d26528083c2908100d7e304..8b75f404e7155aea16d364994288bb58b7dfbc85 100644 --- a/web/core/tests/Drupal/Tests/Core/Entity/ContentEntityBaseUnitTest.php +++ b/web/core/tests/Drupal/Tests/Core/Entity/ContentEntityBaseUnitTest.php @@ -526,7 +526,7 @@ public function testAccess() { /** * Data provider for testGet(). * - * @returns + * @return array * - Expected output from get(). * - Field name parameter to get(). * - Language code for $activeLanguage. @@ -586,7 +586,7 @@ public function testGet($expected, $field_name, $active_langcode, $fields) { /** * Data provider for testGetFields(). * - * @returns array + * @return array * - Expected output from getFields(). * - $include_computed value to pass to getFields(). * - Value to mock from all field definitions for isComputed(). diff --git a/web/core/tests/Drupal/Tests/Core/Entity/EntityListBuilderTest.php b/web/core/tests/Drupal/Tests/Core/Entity/EntityListBuilderTest.php index 470a2cd69573252d58152a5535afe5ea5a871149..08d8540889cc4c5ebd9687c549a4a397f1d740c0 100644 --- a/web/core/tests/Drupal/Tests/Core/Entity/EntityListBuilderTest.php +++ b/web/core/tests/Drupal/Tests/Core/Entity/EntityListBuilderTest.php @@ -12,6 +12,7 @@ use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityListBuilder; use Drupal\Core\Routing\RedirectDestinationInterface; +use Drupal\Core\Url; use Drupal\entity_test\EntityTestListBuilder; use Drupal\Tests\UnitTestCase; @@ -120,12 +121,7 @@ public function testGetOperations() { $this->role->expects($this->any()) ->method('hasLinkTemplate') ->willReturn(TRUE); - $url = $this->getMockBuilder('\Drupal\Core\Url') - ->disableOriginalConstructor() - ->getMock(); - $url->expects($this->atLeastOnce()) - ->method('mergeOptions') - ->with(['query' => ['destination' => '/foo/bar']]); + $url = Url::fromRoute('entity.user_role.collection'); $this->role->expects($this->any()) ->method('toUrl') ->willReturn($url); diff --git a/web/core/tests/Drupal/Tests/Core/Password/PhpPasswordTest.php b/web/core/tests/Drupal/Tests/Core/Password/PhpPasswordTest.php index 7d429ca3d533d5c907099498faffe820318ec534..21f7266d019ca5230b23d3f5dfa34cb6109aacdc 100644 --- a/web/core/tests/Drupal/Tests/Core/Password/PhpPasswordTest.php +++ b/web/core/tests/Drupal/Tests/Core/Password/PhpPasswordTest.php @@ -124,4 +124,14 @@ public function providerLongPasswords() { return $passwords; } + /** + * Tests password check in case provided hash is NULL. + * + * @covers ::check + */ + public function testEmptyHash(): void { + $this->assertFalse($this->passwordHasher->check($this->password, NULL)); + $this->assertFalse($this->passwordHasher->check($this->password, '')); + } + } diff --git a/web/core/tests/Drupal/Tests/Core/Session/SessionConfigurationTest.php b/web/core/tests/Drupal/Tests/Core/Session/SessionConfigurationTest.php index 55282c05483c3e945a50b4e84c8ce4ee28ecacec..3c6508806ca0fd40d4c2de462a26c97506f54f0b 100644 --- a/web/core/tests/Drupal/Tests/Core/Session/SessionConfigurationTest.php +++ b/web/core/tests/Drupal/Tests/Core/Session/SessionConfigurationTest.php @@ -14,7 +14,7 @@ class SessionConfigurationTest extends UnitTestCase { /** * Constructs a partially mocked SUT. * - * @returns \Drupal\Core\Session\SessionConfiguration|\PHPUnit\Framework\MockObject\MockObject + * @return \Drupal\Core\Session\SessionConfiguration|\PHPUnit\Framework\MockObject\MockObject */ protected function createSessionConfiguration($options = []) { return $this->getMockBuilder('Drupal\Core\Session\SessionConfiguration') @@ -42,7 +42,7 @@ public function testGeneratedCookieDomain($uri, $expected_domain) { /** * Data provider for the cookie domain test. * - * @returns array + * @return array * Test data */ public function providerTestGeneratedCookieDomain() { @@ -81,7 +81,7 @@ public function testEnforcedCookieDomain($uri, $expected_domain) { /** * Data provider for the cookie domain test. * - * @returns array + * @return array * Test data */ public function providerTestEnforcedCookieDomain() { @@ -147,7 +147,7 @@ public function testCookieSecureNotOverridable($uri, $expected_secure) { /** * Data provider for the cookie secure test. * - * @returns array + * @return array * Test data */ public function providerTestCookieSecure() { @@ -180,7 +180,7 @@ public function testGeneratedSessionName($uri, $expected_name) { /** * Data provider for the cookie name test. * - * @returns array + * @return array * Test data */ public function providerTestGeneratedSessionName() { @@ -228,7 +228,7 @@ public function testEnforcedSessionNameViaCookieDomain($uri, $expected_name) { /** * Data provider for the cookie name test. * - * @returns array + * @return array * Test data */ public function providerTestEnforcedSessionName() { @@ -274,7 +274,7 @@ public function testConstructorDefaultSettings(array $options, int $expected_sid /** * Data provider for the constructor test. * - * @returns array + * @return array * Test data */ public function providerTestConstructorDefaultSettings() { diff --git a/web/core/tests/Drupal/Tests/Core/TempStore/SharedTempStoreTest.php b/web/core/tests/Drupal/Tests/Core/TempStore/SharedTempStoreTest.php index bffe8fa0a6ce0746de703852e4f325e764f12f2d..13833a2897d43347eac2c2c57556a58280208273 100644 --- a/web/core/tests/Drupal/Tests/Core/TempStore/SharedTempStoreTest.php +++ b/web/core/tests/Drupal/Tests/Core/TempStore/SharedTempStoreTest.php @@ -379,9 +379,9 @@ public function testSerialization() { class UnserializableRequest extends Request { /** - * @return array + * Always throw an exception. */ - public function __serialize(): array { + public function __serialize() { throw new \LogicException('Oops!'); } diff --git a/web/core/themes/olivero/templates/content/comment.html.twig b/web/core/themes/olivero/templates/content/comment.html.twig index dca937fff0a542f8e257b08823f9532768068683..1306e56d72862d4e2336c78c0eaf8c0824bd4a22 100644 --- a/web/core/themes/olivero/templates/content/comment.html.twig +++ b/web/core/themes/olivero/templates/content/comment.html.twig @@ -4,7 +4,7 @@ * Olivero's theme implementation for comments. * * Available variables: - * - author: Comment author. Can be a link or plain text. + * - author: (optional) Comment author. Can be a link or plain text. * - content: The content-related items for the comment display. Use * {{ content }} to print them all, or print a subset such as * {{ content.field_example }}. Use the following code to temporarily suppress @@ -12,22 +12,24 @@ * @code * {{ content|without('field_example') }} * @endcode - * - created: Formatted date and time for when the comment was created. - * Preprocess functions can reformat it by calling DateFormatter::format() - * with the desired parameters on the 'comment.created' variable. - * - changed: Formatted date and time for when the comment was last changed. - * Preprocess functions can reformat it by calling DateFormatter::format() - * with the desired parameters on the 'comment.changed' variable. + * - created: (optional) Formatted date and time for when the comment was + * created. Preprocess functions can reformat it by calling + * DateFormatter::format() with the desired parameters on the + * 'comment.created' variable. + * - changed: (optional) Formatted date and time for when the comment was last + * changed. Preprocess functions can reformat it by calling + * DateFormatter::format() with the desired parameters on the + * 'comment.changed' variable. * - permalink: Comment permalink. - * - submitted: Submission information created from author and created - * during template_preprocess_comment(). - * - user_picture: The comment author's profile picture. + * - submitted: (optional) Submission information created from author and + * created during template_preprocess_comment(). + * - user_picture: (optional) The comment author's profile picture. * - status: Comment status. Possible values are: * unpublished, published, or preview. - * - title: Comment title, linked to the comment. + * - title: (optional) Comment title, linked to the comment. * - attributes: HTML attributes for the containing element. * The attributes.class may contain one or more of the following classes: - * - comment: The current template type; e.g., 'theming hook'. + * - comment: The current template type; for instance, 'theming hook'. * - by-anonymous: Comment by an unregistered user. * - by-{entity-type}-author: Comment by the author of the parent entity, * eg. by-node-author. @@ -38,13 +40,13 @@ * displayed in front of the main title tag that appears in the template. * - title_suffix: Additional output populated by modules, intended to be * displayed after the main title tag that appears in the template. + * - content_attributes: List of classes for the styling of the comment content. * - title_attributes: Same as attributes, except applied to the main title * tag that appears in the template. - * - content_attributes: List of classes for the styling of the comment content. * - threaded: A flag indicating whether the comments are threaded or not. * * These variables are provided to give context about the parent comment (if - * any): + * any, optional): * - parent_comment: Full parent comment entity (if any). * - parent_author: Equivalent to author for the parent comment. * - parent_created: Equivalent to created for the parent comment. @@ -83,24 +85,28 @@ #} <span class="hidden" data-comment-timestamp="{{ new_indicator_timestamp }}"></span> - <div class="comment__picture-wrapper"> - <div class="comment__picture"> - {{ user_picture }} + {% if submitted %} + <div class="comment__picture-wrapper"> + <div class="comment__picture"> + {{ user_picture }} + </div> </div> - </div> + {% endif %} <div class="comment__text-wrapper"> - <footer class="comment__meta"> - <p class="comment__author">{{ author }}</p> - <p class="comment__time">{{ created }}</p> - {# - Indicate the semantic relationship between parent and child comments - for accessibility. The list is difficult to navigate in a screen - reader without this information. - #} - {% if parent %} - <p class="visually-hidden">{{ parent }}</p> - {% endif %} - </footer> + {% if submitted %} + <footer class="comment__meta"> + <p class="comment__author">{{ author }}</p> + <p class="comment__time">{{ created }}</p> + {# + Indicate the semantic relationship between parent and child comments + for accessibility. The list is difficult to navigate in a screen + reader without this information. + #} + {% if parent %} + <p class="visually-hidden">{{ parent }}</p> + {% endif %} + </footer> + {% endif %} <div{{ content_attributes.addClass('comment__content') }}> {% if title %} {{ title_prefix }} diff --git a/web/core/themes/starterkit_theme/templates/content/comment.html.twig b/web/core/themes/starterkit_theme/templates/content/comment.html.twig index 5838c62915961753be6a55d227afe8ca499619d9..41c64901a3884823d87ea6ff926d8038860993c9 100644 --- a/web/core/themes/starterkit_theme/templates/content/comment.html.twig +++ b/web/core/themes/starterkit_theme/templates/content/comment.html.twig @@ -4,7 +4,7 @@ * Theme override for comments. * * Available variables: - * - author: Comment author. Can be a link or plain text. + * - author: (optional) Comment author. Can be a link or plain text. * - content: The content-related items for the comment display. Use * {{ content }} to print them all, or print a subset such as * {{ content.field_example }}. Use the following code to temporarily suppress @@ -12,22 +12,24 @@ * @code * {{ content|without('field_example') }} * @endcode - * - created: Formatted date and time for when the comment was created. - * Preprocess functions can reformat it by calling DateFormatter::format() - * with the desired parameters on the 'comment.created' variable. - * - changed: Formatted date and time for when the comment was last changed. - * Preprocess functions can reformat it by calling DateFormatter::format() - * with the desired parameters on the 'comment.changed' variable. + * - created: (optional) Formatted date and time for when the comment was + * created. Preprocess functions can reformat it by calling + * DateFormatter::format() with the desired parameters on the + * 'comment.created' variable. + * - changed: (optional) Formatted date and time for when the comment was last + * changed. Preprocess functions can reformat it by calling + * DateFormatter::format() with the desired parameters on the + * 'comment.changed' variable. * - permalink: Comment permalink. - * - submitted: Submission information created from author and created - * during template_preprocess_comment(). - * - user_picture: The comment author's profile picture. + * - submitted: (optional) Submission information created from author and + * created during template_preprocess_comment(). + * - user_picture: (optional) The comment author's profile picture. * - status: Comment status. Possible values are: * unpublished, published, or preview. - * - title: Comment title, linked to the comment. + * - title: (optional) Comment title, linked to the comment. * - attributes: HTML attributes for the containing element. * The attributes.class may contain one or more of the following classes: - * - comment: The current template type; e.g., 'theming hook'. + * - comment: The current template type; for instance, 'theming hook'. * - by-anonymous: Comment by an unregistered user. * - by-{entity-type}-author: Comment by the author of the parent entity, * eg. by-node-author. @@ -44,7 +46,7 @@ * - threaded: A flag indicating whether the comments are threaded or not. * * These variables are provided to give context about the parent comment (if - * any): + * any, optional): * - parent_comment: Full parent comment entity (if any). * - parent_author: Equivalent to author for the parent comment. * - parent_created: Equivalent to created for the parent comment. @@ -84,21 +86,23 @@ #} <mark class="hidden" data-comment-timestamp="{{ new_indicator_timestamp }}"></mark> - <footer class="comment__meta"> - {{ user_picture }} - <p class="comment__submitted">{{ submitted }}</p> + {% if submitted %} + <footer class="comment__meta"> + {{ user_picture }} + <p class="comment__submitted">{{ submitted }}</p> - {# - Indicate the semantic relationship between parent and child comments for - accessibility. The list is difficult to navigate in a screen reader - without this information. - #} - {% if parent %} - <p class="parent visually-hidden">{{ parent }}</p> - {% endif %} + {# + Indicate the semantic relationship between parent and child comments for + accessibility. The list is difficult to navigate in a screen reader + without this information. + #} + {% if parent %} + <p class="parent visually-hidden">{{ parent }}</p> + {% endif %} - {{ permalink }} - </footer> + {{ permalink }} + </footer> + {% endif %} <div{{ content_attributes.addClass('content') }}> {% if title %} diff --git a/web/core/yarn.lock b/web/core/yarn.lock index 47e62c1ba3a4b51c5cc7e996a44304e0b17ffe37..fbc6229283b265f526464eb71dddc724cb51ae5d 100644 --- a/web/core/yarn.lock +++ b/web/core/yarn.lock @@ -4395,19 +4395,10 @@ postcss-value-parser@^4.0.0, postcss-value-parser@^4.2.0: resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== -postcss@^8.4.21: - version "8.4.23" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.23.tgz#df0aee9ac7c5e53e1075c24a3613496f9e6552ab" - integrity sha512-bQ3qMcpF6A/YjR55xtoTr0jGOlnPOKAIMdOWiv0EIT6HVPEaJiJB4NLljSbiHoC2RX7DN5Uvjtpbg1NPdwv1oA== - dependencies: - nanoid "^3.3.6" - picocolors "^1.0.0" - source-map-js "^1.0.2" - -postcss@^8.4.24: - version "8.4.24" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.24.tgz#f714dba9b2284be3cc07dbd2fc57ee4dc972d2df" - integrity sha512-M0RzbcI0sO/XJNucsGjvWU9ERWxb/ytp1w6dKtxTKgixdtQDq4rmx/g8W1hnaheq9jgwL/oyEdH5Bc4WwJKMqg== +postcss@^8.4.21, postcss@^8.4.24, postcss@^8.4.31: + version "8.4.31" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.31.tgz#92b451050a9f914da6755af352bdc0192508656d" + integrity sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ== dependencies: nanoid "^3.3.6" picocolors "^1.0.0"