diff options
64 files changed, 378 insertions, 235 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c2a64c8baa87..fbcfb8496a31 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -67,6 +67,7 @@ variables: GIT_DEPTH: "50" PARENT_PIPELINE_ID: $CI_PIPELINE_ID _TARGET_PHP: "8.3-ubuntu" + PHPUNIT_FAIL_ON_PHPUNIT_DEPRECATION: false ############# # Stages # @@ -109,6 +110,7 @@ default: before_script: - composer validate - composer install --optimize-autoloader + - composer run-script drupal-phpunit-upgrade-check - mkdir -p ./sites/simpletest ./sites/default/files ./build/logs/junit /var/www/.composer - chown -R www-data:www-data ./sites ./build/logs/junit ./vendor /var/www/ script: @@ -128,9 +130,13 @@ default: before_script: - composer validate - composer install --optimize-autoloader + - composer run-script drupal-phpunit-upgrade-check - docker-php-ext-enable pcov script: - - vendor/bin/phpunit -c core/tests/Drupal/Tests/Component --testsuite unit-component --colors=always --testdox --coverage-text=component-coverage-report.txt --coverage-cobertura=component-coverage-cobertura.xml --log-junit junit.xml --fail-on-deprecation --fail-on-phpunit-deprecation + - | + [[ $PHPUNIT_FAIL_ON_PHPUNIT_DEPRECATION == false ]] && export _FAIL_ON_PHPUNIT_DEPRECATION="" + [[ $PHPUNIT_FAIL_ON_PHPUNIT_DEPRECATION != false ]] && export _FAIL_ON_PHPUNIT_DEPRECATION="--fail-on-phpunit-deprecation" + - vendor/bin/phpunit -c core/tests/Drupal/Tests/Component --testsuite unit-component --colors=always --testdox --coverage-text=component-coverage-report.txt --coverage-cobertura=component-coverage-cobertura.xml --log-junit junit.xml --fail-on-deprecation $_FAIL_ON_PHPUNIT_DEPRECATION # Process the coverage text report to produce an OpenMetrics report. - php .gitlab-ci/scripts/component-coverage-metrics.php artifacts: @@ -390,6 +396,7 @@ default: - *phpstan-cache - composer validate - composer install --optimize-autoloader + - composer run-script drupal-phpunit-upgrade-check - if [ -n "$COMPOSER_UPDATE" ]; then composer update --optimize-autoloader; composer outdated; @@ -439,6 +446,7 @@ default: script: - composer validate - composer install --optimize-autoloader + - composer run-script drupal-phpunit-upgrade-check - if [ -n "$COMPOSER_UPDATE" ]; then composer update --optimize-autoloader; composer outdated; diff --git a/.gitlab-ci/pipeline.yml b/.gitlab-ci/pipeline.yml index d8324045c806..c311b1a03a63 100644 --- a/.gitlab-ci/pipeline.yml +++ b/.gitlab-ci/pipeline.yml @@ -72,6 +72,7 @@ variables: MINK_DRIVER_ARGS_WEBDRIVER_CHROMEDRIVER_NON_W3C: '["chrome", {"browserName":"chrome","goog:chromeOptions":{"args":["--disable-dev-shm-usage","--disable-gpu","--headless","--dns-prefetch-disable"]}}, "http://localhost:9515"]' CI_PARALLEL_NODE_INDEX: $CI_NODE_INDEX CI_PARALLEL_NODE_TOTAL: $CI_NODE_TOTAL + PHPUNIT_FAIL_ON_PHPUNIT_DEPRECATION: false .with-database: &with-database name: $_CONFIG_DOCKERHUB_ROOT/$_TARGET_DB:production @@ -101,6 +102,7 @@ variables: .run-tests: &run-tests script: + - sudo -u www-data -E -H composer run-script drupal-phpunit-upgrade-check # Need to pass this along directly. - sudo -u www-data -E -H php ./core/scripts/run-tests.sh --color --keep-results --types "$TESTSUITE" --concurrency "$CONCURRENCY" --repeat "1" --sqlite "./sites/default/files/tests.sqlite" --dburl $SIMPLETEST_DB --url $SIMPLETEST_BASE_URL --verbose --non-html --all --ci-parallel-node-index $CI_PARALLEL_NODE_INDEX --ci-parallel-node-total $CI_PARALLEL_NODE_TOTAL @@ -230,6 +232,7 @@ variables: - <<: *with-database - <<: *with-chrome script: + - sudo -u www-data -E -H composer run-script drupal-phpunit-upgrade-check # Run a small subset of tests to prove non W3C testing still works. - sudo -u www-data -E -H php ./core/scripts/run-tests.sh --color --keep-results --types "$TESTSUITE" --concurrency "$CONCURRENCY" --repeat "1" --sqlite "./sites/default/files/tests.sqlite" --dburl $SIMPLETEST_DB --url $SIMPLETEST_BASE_URL --verbose --non-html javascript diff --git a/composer.json b/composer.json index c999c6fbf271..3f1230c946e6 100644 --- a/composer.json +++ b/composer.json @@ -33,7 +33,7 @@ "phpstan/extension-installer": "^1.4.3", "phpstan/phpstan": "^1.12.4 || ^2.1.11", "phpstan/phpstan-phpunit": "^1.3.16 || ^2.0.6", - "phpunit/phpunit": "^10.5.19", + "phpunit/phpunit": "^10.5.19 || ^11.5.3", "symfony/browser-kit": "^7.2", "symfony/css-selector": "^7.2", "symfony/dom-crawler": "^7.2", @@ -128,14 +128,17 @@ "repositories": [ { "type": "path", + "canonical": false, "url": "core" }, { "type": "path", + "canonical": false, "url": "composer/Plugin/ProjectMessage" }, { "type": "path", + "canonical": false, "url": "composer/Plugin/VendorHardening" }, { diff --git a/composer.lock b/composer.lock index fa0d22b3c177..7bfd3eb9cff0 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": "7317ff2c0cfb5aed4d0df6e4b3e63c34", + "content-hash": "fbb4558bd4ae8ebb59dd3179e80083ac", "packages": [ { "name": "asm89/stack-cors", @@ -496,7 +496,7 @@ "dist": { "type": "path", "url": "core", - "reference": "7e8f42a2a16fa8db35c42d6ba0c7bcc9b3508588" + "reference": "b929d8770bd808cc3d4796cb57c0e6d186b5a010" }, "require": { "asm89/stack-cors": "^2.3", @@ -528,7 +528,7 @@ "php-tuf/composer-stager": "^2.0", "psr/log": "^3.0", "revolt/event-loop": "^1.0", - "sebastian/diff": "^4|^5", + "sebastian/diff": "^4 || ^5 || ^6 || ^7", "symfony/console": "^7.2", "symfony/dependency-injection": "^7.2", "symfony/event-dispatcher": "^7.2", diff --git a/composer/Metapackage/DevDependencies/composer.json b/composer/Metapackage/DevDependencies/composer.json index db4c17097dab..9083180e3bc6 100644 --- a/composer/Metapackage/DevDependencies/composer.json +++ b/composer/Metapackage/DevDependencies/composer.json @@ -25,7 +25,7 @@ "phpstan/extension-installer": "^1.4.3", "phpstan/phpstan": "^1.12.4 || ^2.1.11", "phpstan/phpstan-phpunit": "^1.3.16 || ^2.0.6", - "phpunit/phpunit": "^10.5.19", + "phpunit/phpunit": "^10.5.19 || ^11.5.3", "symfony/browser-kit": "^7.2", "symfony/css-selector": "^7.2", "symfony/dom-crawler": "^7.2", diff --git a/core/.cspell.json b/core/.cspell.json index 0b65759aa4f4..8baf6e3d342e 100644 --- a/core/.cspell.json +++ b/core/.cspell.json @@ -7,6 +7,7 @@ "**/.*.json", ".*ignore", "composer.lock", + "composer/Metapackage/PinnedDevDependencies/composer.json", "assets/vendor/**", "misc/jquery.form.js", "lib/Drupal/Component/Diff/**", diff --git a/core/.deprecation-ignore.txt b/core/.deprecation-ignore.txt index 0e70057ddac8..2ed21d1dfad9 100644 --- a/core/.deprecation-ignore.txt +++ b/core/.deprecation-ignore.txt @@ -29,6 +29,9 @@ # PHPUnit 10. %The "PHPUnit\\Framework\\TestCase::__construct\(\)" method is considered internal.*You should not extend it from "Drupal\\[^"]+"% +# PHPUnit 11. +%The "PHPUnit\\Framework\\TestCase::__construct\(\)" method is considered final\. It may change without further notice as of its next major version\. You should not extend it from "Drupal\\[^"]+"% + # Symfony 7.2 %Since symfony/http-foundation 7.2: NativeSessionStorage's "sid_length" option is deprecated and will be ignored in Symfony 8.0.% %Since symfony/http-foundation 7.2: NativeSessionStorage's "sid_bits_per_character" option is deprecated and will be ignored in Symfony 8.0.% diff --git a/core/.phpstan-baseline.php b/core/.phpstan-baseline.php index 588cde82f739..cbe268b00821 100644 --- a/core/.phpstan-baseline.php +++ b/core/.phpstan-baseline.php @@ -27166,28 +27166,28 @@ $ignoreErrors[] = [ 'path' => __DIR__ . '/modules/node/src/NodeAccessControlHandlerInterface.php', ]; $ignoreErrors[] = [ - 'message' => '#^Method Drupal\\\\node\\\\NodeForm\\:\\:create\\(\\) has no return type specified\\.$#', + 'message' => '#^Method Drupal\\\\node\\\\Form\\\\NodeForm\\:\\:create\\(\\) has no return type specified\\.$#', 'identifier' => 'missingType.return', 'count' => 1, - 'path' => __DIR__ . '/modules/node/src/NodeForm.php', + 'path' => __DIR__ . '/modules/node/src/Form/NodeForm.php', ]; $ignoreErrors[] = [ - 'message' => '#^Method Drupal\\\\node\\\\NodeForm\\:\\:form\\(\\) has no return type specified\\.$#', + 'message' => '#^Method Drupal\\\\node\\\\Form\\\\NodeForm\\:\\:form\\(\\) has no return type specified\\.$#', 'identifier' => 'missingType.return', 'count' => 1, - 'path' => __DIR__ . '/modules/node/src/NodeForm.php', + 'path' => __DIR__ . '/modules/node/src/Form/NodeForm.php', ]; $ignoreErrors[] = [ - 'message' => '#^Method Drupal\\\\node\\\\NodeForm\\:\\:preview\\(\\) has no return type specified\\.$#', + 'message' => '#^Method Drupal\\\\node\\\\Form\\\\NodeForm\\:\\:preview\\(\\) has no return type specified\\.$#', 'identifier' => 'missingType.return', 'count' => 1, - 'path' => __DIR__ . '/modules/node/src/NodeForm.php', + 'path' => __DIR__ . '/modules/node/src/Form/NodeForm.php', ]; $ignoreErrors[] = [ - 'message' => '#^Method Drupal\\\\node\\\\NodeForm\\:\\:save\\(\\) should return int but return statement is missing\\.$#', + 'message' => '#^Method Drupal\\\\node\\\\Form\\\\NodeForm\\:\\:save\\(\\) should return int but return statement is missing\\.$#', 'identifier' => 'return.missing', 'count' => 2, - 'path' => __DIR__ . '/modules/node/src/NodeForm.php', + 'path' => __DIR__ . '/modules/node/src/Form/NodeForm.php', ]; $ignoreErrors[] = [ 'message' => '#^Method Drupal\\\\node\\\\NodeGrantDatabaseStorage\\:\\:alterQuery\\(\\) should return int but return statement is missing\\.$#', @@ -27274,28 +27274,28 @@ $ignoreErrors[] = [ 'path' => __DIR__ . '/modules/node/src/NodeTranslationHandler.php', ]; $ignoreErrors[] = [ - 'message' => '#^Method Drupal\\\\node\\\\NodeTypeForm\\:\\:create\\(\\) has no return type specified\\.$#', + 'message' => '#^Method Drupal\\\\node\\\\Form\\\\NodeTypeForm\\:\\:create\\(\\) has no return type specified\\.$#', 'identifier' => 'missingType.return', 'count' => 1, - 'path' => __DIR__ . '/modules/node/src/NodeTypeForm.php', + 'path' => __DIR__ . '/modules/node/src/Form/NodeTypeForm.php', ]; $ignoreErrors[] = [ - 'message' => '#^Method Drupal\\\\node\\\\NodeTypeForm\\:\\:form\\(\\) has no return type specified\\.$#', + 'message' => '#^Method Drupal\\\\node\\\\Form\\\\NodeTypeForm\\:\\:form\\(\\) has no return type specified\\.$#', 'identifier' => 'missingType.return', 'count' => 1, - 'path' => __DIR__ . '/modules/node/src/NodeTypeForm.php', + 'path' => __DIR__ . '/modules/node/src/Form/NodeTypeForm.php', ]; $ignoreErrors[] = [ - 'message' => '#^Method Drupal\\\\node\\\\NodeTypeForm\\:\\:save\\(\\) should return int but return statement is missing\\.$#', + 'message' => '#^Method Drupal\\\\node\\\\Form\\\\NodeTypeForm\\:\\:save\\(\\) should return int but return statement is missing\\.$#', 'identifier' => 'return.missing', 'count' => 1, - 'path' => __DIR__ . '/modules/node/src/NodeTypeForm.php', + 'path' => __DIR__ . '/modules/node/src/Form/NodeTypeForm.php', ]; $ignoreErrors[] = [ - 'message' => '#^Method Drupal\\\\node\\\\NodeTypeForm\\:\\:validateForm\\(\\) has no return type specified\\.$#', + 'message' => '#^Method Drupal\\\\node\\\\Form\\\\NodeTypeForm\\:\\:validateForm\\(\\) has no return type specified\\.$#', 'identifier' => 'missingType.return', 'count' => 1, - 'path' => __DIR__ . '/modules/node/src/NodeTypeForm.php', + 'path' => __DIR__ . '/modules/node/src/Form/NodeTypeForm.php', ]; $ignoreErrors[] = [ 'message' => '#^Method Drupal\\\\node\\\\NodeTypeInterface\\:\\:setDisplaySubmitted\\(\\) has no return type specified\\.$#', diff --git a/core/assets/scaffold/files/default.settings.php b/core/assets/scaffold/files/default.settings.php index 666a39643736..d4ba8a91829a 100644 --- a/core/assets/scaffold/files/default.settings.php +++ b/core/assets/scaffold/files/default.settings.php @@ -476,30 +476,6 @@ $settings['update_free_access'] = FALSE; # $settings['class_loader_auto_detect'] = FALSE; /** - * Authorized file system operations: - * - * The Update Manager module included with Drupal provides a mechanism for - * site administrators to securely install missing updates for the site - * directly through the web user interface. On securely-configured servers, - * the Update manager will require the administrator to provide SSH or FTP - * credentials before allowing the installation to proceed; this allows the - * site to update the new files as the user who owns all the Drupal files, - * instead of as the user the webserver is running as. On servers where the - * webserver user is itself the owner of the Drupal files, the administrator - * will not be prompted for SSH or FTP credentials (note that these server - * setups are common on shared hosting, but are inherently insecure). - * - * Some sites might wish to disable the above functionality, and only update - * the code directly via SSH or FTP themselves. This setting completely - * disables all functionality related to these authorized file operations. - * - * @see https://www.drupal.org/node/244924 - * - * Remove the leading hash signs to disable. - */ -# $settings['allow_authorize_operations'] = FALSE; - -/** * Default mode for directories and files written by Drupal. * * Value should be in PHP Octal Notation, with leading zero. diff --git a/core/assets/vendor/htmx/debug.js b/core/assets/vendor/htmx/debug.js deleted file mode 100644 index 15378ccc0777..000000000000 --- a/core/assets/vendor/htmx/debug.js +++ /dev/null @@ -1,11 +0,0 @@ -htmx.defineExtension('debug', { - onEvent: function(name, evt) { - if (console.debug) { - console.debug(name, evt) - } else if (console) { - console.log('DEBUG:', name, evt) - } else { - throw new Error('NO CONSOLE SUPPORTED') - } - } -}) diff --git a/core/composer.json b/core/composer.json index 2ce89dd0c0e9..8ece7d84bdd7 100644 --- a/core/composer.json +++ b/core/composer.json @@ -49,7 +49,7 @@ "pear/archive_tar": "^1.4.14", "psr/log": "^3.0", "mck89/peast": "^1.14", - "sebastian/diff": "^4|^5", + "sebastian/diff": "^4 || ^5 || ^6 || ^7", "php-tuf/composer-stager": "^2.0" }, "conflict": { diff --git a/core/core.libraries.yml b/core/core.libraries.yml index 5ec851e898e7..76aaa3965f01 100644 --- a/core/core.libraries.yml +++ b/core/core.libraries.yml @@ -791,18 +791,6 @@ htmx: js: assets/vendor/htmx/htmx.min.js: { minified: true } -htmx.debug: - remote: https://github.com/bigskysoftware/htmx-extensions - version: "2.0.1" - license: - name: Zero-Clause BSD - url: https://raw.githubusercontent.com/bigskysoftware/htmx-extensions/refs/heads/main/src/debug/LICENSE - gpl-compatible: true - js: - assets/vendor/htmx/debug.js: {} - dependencies: - - core/htmx - internal.floating-ui: remote: https://github.com/floating-ui/floating-ui version: "1.6.12" diff --git a/core/includes/theme.maintenance.inc b/core/includes/theme.maintenance.inc index 2a37fbc9ffdc..4438d058499b 100644 --- a/core/includes/theme.maintenance.inc +++ b/core/includes/theme.maintenance.inc @@ -108,8 +108,14 @@ function _drupal_maintenance_theme(): void { * @param array $variables * An associative array containing: * - messages: An array of result messages. + * + * @deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no + * replacement. Use composer to manage the code for your site. + * + * @see https://www.drupal.org/node/3522119 */ function template_preprocess_authorize_report(&$variables): void { + @trigger_error(__FUNCTION__ . '() is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no replacement. Use composer to manage the code for your site. See https://www.drupal.org/node/3522119', E_USER_DEPRECATED); $messages = []; if (!empty($variables['messages'])) { foreach ($variables['messages'] as $heading => $logs) { diff --git a/core/lib/Drupal/Component/Diff/composer.json b/core/lib/Drupal/Component/Diff/composer.json index 3fd31e6c78fb..f4bc60d21bcb 100644 --- a/core/lib/Drupal/Component/Diff/composer.json +++ b/core/lib/Drupal/Component/Diff/composer.json @@ -8,7 +8,7 @@ "license": "GPL-2.0-or-later", "require": { "php": ">=8.3.0", - "sebastian/diff": "^4|^5" + "sebastian/diff": "^4 || ^5 || ^6 || ^7" }, "autoload": { "psr-4": { diff --git a/core/lib/Drupal/Component/Utility/Html.php b/core/lib/Drupal/Component/Utility/Html.php index 38b328a4c61c..1a53a8de0e88 100644 --- a/core/lib/Drupal/Component/Utility/Html.php +++ b/core/lib/Drupal/Component/Utility/Html.php @@ -128,13 +128,13 @@ class Html { // - 0-9 (U+0061 - U+007A) // - ISO 10646 characters U+00A1 and higher // We strip out any character not in the above list. - $identifier = preg_replace('/[^\x{002D}\x{0030}-\x{0039}\x{0041}-\x{005A}\x{005F}\x{0061}-\x{007A}\x{00A1}-\x{FFFF}]/u', '', $identifier); + $identifier = preg_replace('/[^\x{002D}\x{0030}-\x{0039}\x{0041}-\x{005A}\x{005F}\x{0061}-\x{007A}\x{00A1}-\x{FFFF}]/u', '', (string) $identifier); // Identifiers cannot start with a digit, two hyphens, or a hyphen followed // by a digit. $identifier = preg_replace([ '/^[0-9]/', '/^(-[0-9])|^(--)/', - ], ['_', '__'], $identifier); + ], ['_', '__'], (string) $identifier); return $identifier; } diff --git a/core/lib/Drupal/Core/Composer/Composer.php b/core/lib/Drupal/Core/Composer/Composer.php index 6f2391885499..87b494e98421 100644 --- a/core/lib/Drupal/Core/Composer/Composer.php +++ b/core/lib/Drupal/Core/Composer/Composer.php @@ -91,7 +91,7 @@ class Composer { return; } - // If the PHP version is 7.4 or above and PHPUnit is less than version 9 + // If the PHP version is 8.4 or above and PHPUnit is less than version 11 // call the drupal-phpunit-upgrade script to upgrade PHPUnit. if (!static::upgradePHPUnitCheck($phpunit_package->getVersion())) { $event->getComposer() @@ -115,7 +115,7 @@ class Composer { * @internal */ public static function upgradePHPUnitCheck($phpunit_version) { - return !(version_compare(PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION, '7.4') >= 0 && version_compare($phpunit_version, '9.0') < 0); + return !(version_compare(PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION, '8.4') >= 0 && version_compare($phpunit_version, '11.0') < 0); } } diff --git a/core/lib/Drupal/Core/Hook/Attribute/FormAlter.php b/core/lib/Drupal/Core/Hook/Attribute/FormAlter.php index 95a8ed14768b..158010463d2a 100644 --- a/core/lib/Drupal/Core/Hook/Attribute/FormAlter.php +++ b/core/lib/Drupal/Core/Hook/Attribute/FormAlter.php @@ -4,6 +4,8 @@ declare(strict_types=1); namespace Drupal\Core\Hook\Attribute; +use Drupal\Core\Hook\Order\OrderInterface; + /** * Hook attribute for FormAlter. * @@ -37,13 +39,16 @@ class FormAlter extends Hook { * (optional) The module this implementation is for. This allows one module * to implement a hook on behalf of another module. Defaults to the module * the implementation is in. + * @param \Drupal\Core\Hook\Order\OrderInterface|null $order + * (optional) Set the order of the implementation. */ public function __construct( string $form_id = '', public string $method = '', public ?string $module = NULL, + public ?OrderInterface $order = NULL, ) { - parent::__construct($form_id, $method, $module); + parent::__construct($form_id, $method, $module, $order); } } diff --git a/core/lib/Drupal/Core/Render/Placeholder/CachedStrategy.php b/core/lib/Drupal/Core/Render/Placeholder/CachedStrategy.php index 941c11ac27eb..757f647e5f0a 100644 --- a/core/lib/Drupal/Core/Render/Placeholder/CachedStrategy.php +++ b/core/lib/Drupal/Core/Render/Placeholder/CachedStrategy.php @@ -21,7 +21,41 @@ class CachedStrategy implements PlaceholderStrategyInterface { * {@inheritdoc} */ public function processPlaceholders(array $placeholders) { - return $this->renderCache->getMultiple($placeholders); + $return = $this->renderCache->getMultiple($placeholders); + if ($return) { + $return = $this->processNestedPlaceholders($return); + } + + return $return; + } + + /** + * Fetch any nested placeholders from cache. + * + * Placeholders returned from cache may have placeholders in #attached, which + * can themselves be fetched from the cache. By recursively processing the + * placeholders here, we're able to use multiple cache get to fetch the cache + * items at each level of recursion. + */ + private function processNestedPlaceholders(array $placeholders): array { + $sets = []; + foreach ($placeholders as $key => $placeholder) { + if (!empty($placeholder['#attached']['placeholders'])) { + $sets[] = $placeholder['#attached']['placeholders']; + } + } + if ($sets) { + $cached = $this->renderCache->getMultiple(...array_merge($sets)); + if ($cached) { + $cached = $this->processNestedPlaceholders($cached); + foreach ($placeholders as $key => $placeholder) { + if (!empty($placeholder['#attached']['placeholders'])) { + $placeholders[$key]['#attached']['placeholders'] = array_replace($placeholder['#attached']['placeholders'], $cached); + } + } + } + } + return $placeholders; } } diff --git a/core/lib/Drupal/Core/Test/PhpUnitTestRunner.php b/core/lib/Drupal/Core/Test/PhpUnitTestRunner.php index 3293b07b44bf..3f3a5ee9a96d 100644 --- a/core/lib/Drupal/Core/Test/PhpUnitTestRunner.php +++ b/core/lib/Drupal/Core/Test/PhpUnitTestRunner.php @@ -160,8 +160,12 @@ class PhpUnitTestRunner implements ContainerInjectionInterface { // If the deprecation handler bridge is active, we need to fail when there // are deprecations that get reported (i.e. not ignored or expected). - if (DeprecationHandler::getConfiguration() !== FALSE) { + $deprecationConfiguration = DeprecationHandler::getConfiguration(); + if ($deprecationConfiguration !== FALSE) { $command[] = '--fail-on-deprecation'; + if ($deprecationConfiguration['failOnPhpunitDeprecation']) { + $command[] = '--fail-on-phpunit-deprecation'; + } } // Add to the command the file containing the test class to be run. diff --git a/core/lib/Drupal/Core/Theme/ThemeCommonElements.php b/core/lib/Drupal/Core/Theme/ThemeCommonElements.php index 03e143662558..5ddf58fd6f22 100644 --- a/core/lib/Drupal/Core/Theme/ThemeCommonElements.php +++ b/core/lib/Drupal/Core/Theme/ThemeCommonElements.php @@ -176,6 +176,7 @@ class ThemeCommonElements { ], 'includes' => ['core/includes/theme.maintenance.inc'], 'template' => 'authorize-report', + 'deprecated' => 'The "authorize-report" template is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no replacement. Use composer to manage the code for your site. See https://www.drupal.org/node/3522119', ], 'pager' => [ 'render element' => 'pager', diff --git a/core/modules/ckeditor5/tests/src/Unit/HTMLRestrictionsTest.php b/core/modules/ckeditor5/tests/src/Unit/HTMLRestrictionsTest.php index f512c008ceeb..dfd6c1db1da8 100644 --- a/core/modules/ckeditor5/tests/src/Unit/HTMLRestrictionsTest.php +++ b/core/modules/ckeditor5/tests/src/Unit/HTMLRestrictionsTest.php @@ -1131,8 +1131,8 @@ class HTMLRestrictionsTest extends UnitTestCase { 'expected_union' => 'a', ]; yield 'attribute restrictions are different: <ol type=*> vs <ol type="A"> — vice versa' => [ - 'b' => new HTMLRestrictions(['ol' => ['type' => ['A' => TRUE]]]), - 'a' => new HTMLRestrictions(['ol' => ['type' => TRUE]]), + 'a' => new HTMLRestrictions(['ol' => ['type' => ['A' => TRUE]]]), + 'b' => new HTMLRestrictions(['ol' => ['type' => TRUE]]), 'expected_diff' => HTMLRestrictions::emptySet(), 'expected_intersection' => 'a', 'expected_union' => 'b', @@ -1145,8 +1145,8 @@ class HTMLRestrictionsTest extends UnitTestCase { 'expected_union' => 'a', ]; yield 'attribute restrictions are different: <ol type=*> vs <ol type="1"> — vice versa' => [ - 'b' => new HTMLRestrictions(['ol' => ['type' => ['1' => TRUE]]]), - 'a' => new HTMLRestrictions(['ol' => ['type' => TRUE]]), + 'a' => new HTMLRestrictions(['ol' => ['type' => ['1' => TRUE]]]), + 'b' => new HTMLRestrictions(['ol' => ['type' => TRUE]]), 'expected_diff' => HTMLRestrictions::emptySet(), 'expected_intersection' => 'a', 'expected_union' => 'b', diff --git a/core/modules/content_moderation/src/Plugin/Field/ModerationStateFieldItemList.php b/core/modules/content_moderation/src/Plugin/Field/ModerationStateFieldItemList.php index 41174b60490b..eadb49642080 100644 --- a/core/modules/content_moderation/src/Plugin/Field/ModerationStateFieldItemList.php +++ b/core/modules/content_moderation/src/Plugin/Field/ModerationStateFieldItemList.php @@ -56,7 +56,7 @@ class ModerationStateFieldItemList extends FieldItemList { // It is possible that the bundle does not exist at this point. For example, // the node type form creates a fake Node entity to get default values. - // @see \Drupal\node\NodeTypeForm::form() + // @see \Drupal\node\Form\NodeTypeForm::form() $workflow = $moderation_info->getWorkFlowForEntity($entity); return $workflow ? $workflow->getTypePlugin()->getInitialState($entity)->id() : NULL; } diff --git a/core/modules/field_ui/src/Hook/FieldUiHooks.php b/core/modules/field_ui/src/Hook/FieldUiHooks.php index 06434e2ec4df..3210e2f7c5b4 100644 --- a/core/modules/field_ui/src/Hook/FieldUiHooks.php +++ b/core/modules/field_ui/src/Hook/FieldUiHooks.php @@ -249,7 +249,7 @@ class FieldUiHooks { * * Adds a button 'Save and manage fields' to forms. * - * @see \Drupal\node\NodeTypeForm + * @see \Drupal\node\Form\NodeTypeForm * @see \Drupal\comment\CommentTypeForm * @see \Drupal\media\MediaTypeForm * @see \Drupal\block_content\BlockContentTypeForm diff --git a/core/modules/media_library/tests/modules/media_library_test/src/Form/TestNodeFormOverride.php b/core/modules/media_library/tests/modules/media_library_test/src/Form/TestNodeFormOverride.php index 4dda6ff75444..50305332a25d 100644 --- a/core/modules/media_library/tests/modules/media_library_test/src/Form/TestNodeFormOverride.php +++ b/core/modules/media_library/tests/modules/media_library_test/src/Form/TestNodeFormOverride.php @@ -5,7 +5,7 @@ declare(strict_types=1); namespace Drupal\media_library_test\Form; use Drupal\Core\Form\FormStateInterface; -use Drupal\node\NodeForm; +use Drupal\node\Form\NodeForm; /** * Override NodeForm to test media library form submission semantics. diff --git a/core/modules/menu_ui/src/Hook/MenuUiHooks.php b/core/modules/menu_ui/src/Hook/MenuUiHooks.php index 9b32ffa18247..46f2c85d1d76 100644 --- a/core/modules/menu_ui/src/Hook/MenuUiHooks.php +++ b/core/modules/menu_ui/src/Hook/MenuUiHooks.php @@ -121,7 +121,7 @@ class MenuUiHooks { } /** - * Implements hook_form_BASE_FORM_ID_alter() for \Drupal\node\NodeForm. + * Implements hook_form_BASE_FORM_ID_alter() for \Drupal\node\Form\NodeForm. * * Adds menu item fields to the node form. * @@ -231,7 +231,7 @@ class MenuUiHooks { } /** - * Implements hook_form_FORM_ID_alter() for \Drupal\node\NodeTypeForm. + * Implements hook_form_FORM_ID_alter() for \Drupal\node\Form\NodeTypeForm. * * Adds menu options to the node type form. * diff --git a/core/modules/migrate/tests/src/Kernel/MigrateSourceTestBase.php b/core/modules/migrate/tests/src/Kernel/MigrateSourceTestBase.php index 1999e3ad86f4..9e508da9b225 100644 --- a/core/modules/migrate/tests/src/Kernel/MigrateSourceTestBase.php +++ b/core/modules/migrate/tests/src/Kernel/MigrateSourceTestBase.php @@ -85,9 +85,9 @@ abstract class MigrateSourceTestBase extends KernelTestBase { * The fully qualified class name of the plugin to be tested. */ protected function getPluginClass() { - $covers = $this->getTestClassCovers(); - if (!empty($covers)) { - return $covers[0]; + $covers = $this->valueObjectForEvents()->metadata()->isCovers()->isClassLevel()->asArray(); + if (isset($covers[0])) { + return $covers[0]->target(); } else { $this->fail('No plugin class was specified'); diff --git a/core/modules/navigation/tests/src/FunctionalJavascript/PerformanceTest.php b/core/modules/navigation/tests/src/FunctionalJavascript/PerformanceTest.php index 3264d769c195..f1ca3242a2a8 100644 --- a/core/modules/navigation/tests/src/FunctionalJavascript/PerformanceTest.php +++ b/core/modules/navigation/tests/src/FunctionalJavascript/PerformanceTest.php @@ -73,14 +73,14 @@ class PerformanceTest extends PerformanceTestBase { $expected = [ 'QueryCount' => 4, - 'CacheGetCount' => 49, + 'CacheGetCount' => 48, 'CacheGetCountByBin' => [ 'config' => 11, 'data' => 4, 'discovery' => 10, 'bootstrap' => 6, 'dynamic_page_cache' => 1, - 'render' => 16, + 'render' => 15, 'menu' => 1, ], 'CacheSetCount' => 2, diff --git a/core/modules/node/config/schema/node.schema.yml b/core/modules/node/config/schema/node.schema.yml index 08fe92cc401e..8c81f68ae604 100644 --- a/core/modules/node/config/schema/node.schema.yml +++ b/core/modules/node/config/schema/node.schema.yml @@ -24,7 +24,7 @@ node.type.*: label: 'Machine-readable name' constraints: # Node type machine names are specifically limited to 32 characters. - # @see \Drupal\node\NodeTypeForm::form() + # @see \Drupal\node\Form\NodeTypeForm::form() Length: max: 32 description: @@ -50,7 +50,7 @@ node.type.*: constraints: # These are the values of the DRUPAL_DISABLED, DRUPAL_OPTIONAL, and # DRUPAL_REQUIRED constants. - # @see \Drupal\node\NodeTypeForm::form() + # @see \Drupal\node\Form\NodeTypeForm::form() Choice: [0, 1, 2] display_submitted: type: boolean diff --git a/core/modules/node/node.services.yml b/core/modules/node/node.services.yml index a70ae7faa576..83eb19f7355d 100644 --- a/core/modules/node/node.services.yml +++ b/core/modules/node/node.services.yml @@ -1,3 +1,16 @@ +parameters: + node.moved_classes: + 'Drupal\node\NodeForm': + class: 'Drupal\node\Form\NodeForm' + deprecation_version: drupal:11.2.0 + removed_version: drupal:12.0.0 + change_record: https://www.drupal.org/node/3517871 + 'Drupal\node\NodeTypeForm': + class: 'Drupal\node\Form\NodeTypeForm' + deprecation_version: drupal:11.2.0 + removed_version: drupal:12.0.0 + change_record: https://www.drupal.org/node/3517871 + services: _defaults: autoconfigure: true diff --git a/core/modules/node/src/Entity/Node.php b/core/modules/node/src/Entity/Node.php index f4c519a43c8a..0f61a74f1c01 100644 --- a/core/modules/node/src/Entity/Node.php +++ b/core/modules/node/src/Entity/Node.php @@ -11,8 +11,8 @@ use Drupal\Core\Session\AccountInterface; use Drupal\Core\StringTranslation\TranslatableMarkup; use Drupal\node\Form\DeleteMultiple; use Drupal\node\Form\NodeDeleteForm; +use Drupal\node\Form\NodeForm; use Drupal\node\NodeAccessControlHandler; -use Drupal\node\NodeForm; use Drupal\node\NodeInterface; use Drupal\node\NodeListBuilder; use Drupal\node\NodeStorage; diff --git a/core/modules/node/src/Entity/NodeType.php b/core/modules/node/src/Entity/NodeType.php index 35b911d7ffb7..48d295635f3d 100644 --- a/core/modules/node/src/Entity/NodeType.php +++ b/core/modules/node/src/Entity/NodeType.php @@ -9,7 +9,7 @@ use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\StringTranslation\TranslatableMarkup; use Drupal\node\Form\NodeTypeDeleteConfirm; use Drupal\node\NodeTypeAccessControlHandler; -use Drupal\node\NodeTypeForm; +use Drupal\node\Form\NodeTypeForm; use Drupal\node\NodeTypeInterface; use Drupal\node\NodeTypeListBuilder; use Drupal\user\Entity\EntityPermissionsRouteProvider; diff --git a/core/modules/node/src/NodeForm.php b/core/modules/node/src/Form/NodeForm.php index ab81a4e3f928..d5afa396568c 100644 --- a/core/modules/node/src/NodeForm.php +++ b/core/modules/node/src/Form/NodeForm.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\node; +namespace Drupal\node\Form; use Drupal\Component\Datetime\TimeInterface; use Drupal\Core\Datetime\DateFormatterInterface; @@ -163,7 +163,7 @@ class NodeForm extends ContentEntityForm { $form['meta']['author'] = [ '#type' => 'item', '#title' => $this->t('Author'), - '#markup' => $node->getOwner()->getAccountName(), + '#markup' => $node->getOwner()?->getAccountName(), '#wrapper_attributes' => ['class' => ['entity-meta__author']], ]; diff --git a/core/modules/node/src/NodeTypeForm.php b/core/modules/node/src/Form/NodeTypeForm.php index 3328ade970da..93d510d4387e 100644 --- a/core/modules/node/src/NodeTypeForm.php +++ b/core/modules/node/src/Form/NodeTypeForm.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\node; +namespace Drupal\node\Form; use Drupal\Core\Entity\BundleEntityFormBase; use Drupal\Core\Entity\EntityFieldManagerInterface; diff --git a/core/modules/node/tests/modules/node_no_default_author/node_no_default_author.info.yml b/core/modules/node/tests/modules/node_no_default_author/node_no_default_author.info.yml new file mode 100644 index 000000000000..c4f56344370f --- /dev/null +++ b/core/modules/node/tests/modules/node_no_default_author/node_no_default_author.info.yml @@ -0,0 +1,5 @@ +name: 'Node no default author' +type: module +description: 'Disables the default value callback for the uid field on node.' +package: Testing +version: VERSION diff --git a/core/modules/node/tests/modules/node_no_default_author/src/Hook/NodeNoDefaultAuthorHooks.php b/core/modules/node/tests/modules/node_no_default_author/src/Hook/NodeNoDefaultAuthorHooks.php new file mode 100644 index 000000000000..700e82236adc --- /dev/null +++ b/core/modules/node/tests/modules/node_no_default_author/src/Hook/NodeNoDefaultAuthorHooks.php @@ -0,0 +1,31 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\node_no_default_author\Hook; + +use Drupal\Core\Entity\EntityTypeInterface; +use Drupal\Core\Hook\Attribute\Hook; + +/** + * Hook implementations for node_no_default_author. + */ +class NodeNoDefaultAuthorHooks { + + /** + * Implements hook_entity_base_field_info_alter(). + */ + #[Hook('entity_base_field_info_alter')] + public function entityBaseFieldInfoAlter(&$fields, EntityTypeInterface $entity_type): void { + if ($entity_type->id() === 'node') { + $fields['uid']->setDefaultValueCallback(static::class . '::noDefaultAuthor'); + } + } + + /** + * An empty callback to set for the default value callback of uid. + */ + public static function noDefaultAuthor(): void { + } + +} diff --git a/core/modules/node/tests/src/Functional/NodeEditFormTest.php b/core/modules/node/tests/src/Functional/NodeEditFormTest.php index bc8cfa927e43..dc47998c9093 100644 --- a/core/modules/node/tests/src/Functional/NodeEditFormTest.php +++ b/core/modules/node/tests/src/Functional/NodeEditFormTest.php @@ -258,6 +258,16 @@ class NodeEditFormTest extends NodeTestBase { } /** + * Tests the node form when the author is NULL. + */ + public function testNodeFormNullAuthor(): void { + \Drupal::service('module_installer')->install(['node_no_default_author']); + $this->drupalLogin($this->adminUser); + $this->drupalGet('node/add/page'); + $this->assertSession()->statusCodeEquals(200); + } + + /** * Checks that the "authored by" works correctly with various values. * * @param \Drupal\node\NodeInterface $node diff --git a/core/modules/system/templates/authorize-report.html.twig b/core/modules/system/templates/authorize-report.html.twig index 914458684775..f6f443c58075 100644 --- a/core/modules/system/templates/authorize-report.html.twig +++ b/core/modules/system/templates/authorize-report.html.twig @@ -12,6 +12,11 @@ * @see template_preprocess_authorize_report() * * @ingroup themeable + * + * @deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no + * replacement. Use composer to manage the code for your site. + * + * @see https://www.drupal.org/node/3522119 */ #} {% if messages %} diff --git a/core/modules/update/src/Hook/UpdateHooks.php b/core/modules/update/src/Hook/UpdateHooks.php index 293882f01246..49cb455a8430 100644 --- a/core/modules/update/src/Hook/UpdateHooks.php +++ b/core/modules/update/src/Hook/UpdateHooks.php @@ -178,8 +178,6 @@ class UpdateHooks { \Drupal::moduleHandler()->loadInclude('update', 'inc', 'update.fetch'); _update_cron_notify(); } - // Clear garbage from disk. - update_clear_update_disk_cache(); } /** diff --git a/core/modules/update/src/UpdateRoot.php b/core/modules/update/src/UpdateRoot.php index a2f1619d6ea6..abcf499d5b4b 100644 --- a/core/modules/update/src/UpdateRoot.php +++ b/core/modules/update/src/UpdateRoot.php @@ -6,7 +6,12 @@ use Drupal\Core\DrupalKernelInterface; use Symfony\Component\HttpFoundation\RequestStack; /** - * Gets the root path used by the Update Manager to install or update projects. + * Gets the root path used by the legacy Update Manager to install or update projects. + * + * @deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no + * replacement. Use composer to manage the code for your site. + * + * @see https://www.drupal.org/node/3522119 */ class UpdateRoot { @@ -32,7 +37,7 @@ class UpdateRoot { protected $updateRoot; /** - * Constructs an UpdateRootFactory instance. + * Constructs an UpdateRoot instance. * * @param \Drupal\Core\DrupalKernelInterface $drupal_kernel * The Drupal kernel. @@ -40,6 +45,7 @@ class UpdateRoot { * The request stack. */ public function __construct(DrupalKernelInterface $drupal_kernel, RequestStack $request_stack) { + @trigger_error(__CLASS__ . ' is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no replacement. Use composer to manage the code for your site. See https://www.drupal.org/node/3522119', E_USER_DEPRECATED); $this->drupalKernel = $drupal_kernel; $this->requestStack = $request_stack; } diff --git a/core/modules/update/tests/src/Functional/UpdateManagerTest.php b/core/modules/update/tests/src/Functional/UpdateManagerTest.php new file mode 100644 index 000000000000..a69e06a72fdd --- /dev/null +++ b/core/modules/update/tests/src/Functional/UpdateManagerTest.php @@ -0,0 +1,37 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\Tests\update\Functional; + +/** + * Tests legacy Update Manager functionality of the Update Status module. + * + * @group legacy + * @group update + */ +class UpdateManagerTest extends UpdateTestBase { + + /** + * {@inheritdoc} + */ + protected $defaultTheme = 'stark'; + + /** + * Checks that clearing the disk cache works. + */ + public function testClearDiskCache(): void { + $directories = [ + _update_manager_cache_directory(FALSE), + _update_manager_extract_directory(FALSE), + ]; + // Check that update directories does not exists. + foreach ($directories as $directory) { + $this->assertDirectoryDoesNotExist($directory); + } + + // Method must not fail if update directories do not exists. + update_clear_update_disk_cache(); + } + +} diff --git a/core/modules/update/tests/src/Functional/UpdateMiscTest.php b/core/modules/update/tests/src/Functional/UpdateMiscTest.php index 5b544ea36b0e..3a06d965ee5e 100644 --- a/core/modules/update/tests/src/Functional/UpdateMiscTest.php +++ b/core/modules/update/tests/src/Functional/UpdateMiscTest.php @@ -41,23 +41,6 @@ class UpdateMiscTest extends UpdateTestBase { } /** - * Checks that clearing the disk cache works. - */ - public function testClearDiskCache(): void { - $directories = [ - _update_manager_cache_directory(FALSE), - _update_manager_extract_directory(FALSE), - ]; - // Check that update directories does not exists. - foreach ($directories as $directory) { - $this->assertDirectoryDoesNotExist($directory); - } - - // Method must not fail if update directories do not exists. - update_clear_update_disk_cache(); - } - - /** * Tests the Update Status module when the update server returns 503 errors. */ public function testServiceUnavailable(): void { diff --git a/core/modules/update/tests/src/Kernel/UpdateDeleteFileIfStaleTest.php b/core/modules/update/tests/src/Kernel/UpdateDeleteFileIfStaleTest.php index ff5a8b02d457..1e33d81d6141 100644 --- a/core/modules/update/tests/src/Kernel/UpdateDeleteFileIfStaleTest.php +++ b/core/modules/update/tests/src/Kernel/UpdateDeleteFileIfStaleTest.php @@ -10,6 +10,7 @@ use Drupal\KernelTests\KernelTestBase; * Tests the update_delete_file_if_stale() function. * * @group update + * @group legacy */ class UpdateDeleteFileIfStaleTest extends KernelTestBase { diff --git a/core/modules/update/update.authorize.inc b/core/modules/update/update.authorize.inc index 64f8fe7b014a..59bcd97f2325 100644 --- a/core/modules/update/update.authorize.inc +++ b/core/modules/update/update.authorize.inc @@ -107,6 +107,7 @@ function update_authorize_batch_copy_project($project, $updater_name, $local_url return; } + // @phpstan-ignore getDeprecatedService.deprecated $updater = new $updater_name($local_url, \Drupal::getContainer()->get('update.root')); try { diff --git a/core/modules/update/update.manager.inc b/core/modules/update/update.manager.inc index f4b18321002b..e76854ae8de9 100644 --- a/core/modules/update/update.manager.inc +++ b/core/modules/update/update.manager.inc @@ -172,9 +172,11 @@ function update_manager_file_get($url) { } // Check the cache and download the file if needed. + // @phpstan-ignore function.deprecated $cache_directory = _update_manager_cache_directory(); $local = $cache_directory . '/' . \Drupal::service('file_system')->basename($parsed_url['path']); + // @phpstan-ignore function.deprecated if (!file_exists($local) || update_delete_file_if_stale($local)) { try { $data = (string) \Drupal::httpClient()->get($url)->getBody(); @@ -229,6 +231,7 @@ function update_manager_batch_project_get($project, $url, &$context): void { } // Extract it. + // @phpstan-ignore function.deprecated $extract_directory = _update_manager_extract_directory(); try { update_manager_archive_extract($local_cache, $extract_directory); diff --git a/core/modules/update/update.module b/core/modules/update/update.module index e06ac21ea317..89e94fe7b1d7 100644 --- a/core/modules/update/update.module +++ b/core/modules/update/update.module @@ -276,8 +276,15 @@ function update_storage_clear(): void { * * @return string * An eight character string uniquely identifying this Drupal installation. + * + * @deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no + * replacement. Use composer to manage the code for your site. + * + * @see https://www.drupal.org/node/3522119 */ function _update_manager_unique_identifier() { + @trigger_error(__FUNCTION__ . '() is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no replacement. Use composer to manage the code for your site. See https://www.drupal.org/node/3522119', E_USER_DEPRECATED); + static $id; if (!isset($id)) { $id = substr(hash('sha256', Settings::getHashSalt()), 0, 8); @@ -295,8 +302,15 @@ function _update_manager_unique_identifier() { * @return string * The full path to the temporary directory where update file archives should * be extracted. + * + * @deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no + * replacement. Use composer to manage the code for your site. + * + * @see https://www.drupal.org/node/3522119 */ function _update_manager_extract_directory($create = TRUE) { + @trigger_error(__FUNCTION__ . '() is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no replacement. Use composer to manage the code for your site. See https://www.drupal.org/node/3522119', E_USER_DEPRECATED); + static $directory; if (!isset($directory)) { $directory = 'temporary://update-extraction-' . _update_manager_unique_identifier(); @@ -317,8 +331,15 @@ function _update_manager_extract_directory($create = TRUE) { * @return string * The full path to the temporary directory where update file archives should * be cached. + * + * @deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no + * replacement. Use composer to manage the code for your site. + * + * @see https://www.drupal.org/node/3522119 */ function _update_manager_cache_directory($create = TRUE) { + @trigger_error(__FUNCTION__ . '() is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no replacement. Use composer to manage the code for your site. See https://www.drupal.org/node/3522119', E_USER_DEPRECATED); + static $directory; if (!isset($directory)) { $directory = 'temporary://update-cache-' . _update_manager_unique_identifier(); @@ -331,8 +352,15 @@ function _update_manager_cache_directory($create = TRUE) { /** * Clears the temporary files and directories based on file age from disk. + * + * @deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no + * replacement. Use composer to manage the code for your site. + * + * @see https://www.drupal.org/node/3522119 */ function update_clear_update_disk_cache(): void { + @trigger_error(__FUNCTION__ . '() is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no replacement. Use composer to manage the code for your site. See https://www.drupal.org/node/3522119', E_USER_DEPRECATED); + // List of update module cache directories. Do not create the directories if // they do not exist. $directories = [ @@ -368,8 +396,15 @@ function update_clear_update_disk_cache(): void { * * @return bool * TRUE if the file is stale and deleted successfully, FALSE otherwise. + * + * @deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no + * replacement. Use composer to manage the code for your site. + * + * @see https://www.drupal.org/node/3522119 */ function update_delete_file_if_stale($path) { + @trigger_error(__FUNCTION__ . '() is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no replacement. Use composer to manage the code for your site. See https://www.drupal.org/node/3522119', E_USER_DEPRECATED); + if (file_exists($path)) { $filectime = filectime($path); $max_age = \Drupal::config('system.file')->get('temporary_maximum_age'); diff --git a/core/modules/update/update.post_update.php b/core/modules/update/update.post_update.php index 3462899d989b..34ddba396858 100644 --- a/core/modules/update/update.post_update.php +++ b/core/modules/update/update.post_update.php @@ -5,6 +5,8 @@ * Post update functions for Update Status. */ +use Drupal\Core\Site\Settings; + /** * Implements hook_removed_post_updates(). */ @@ -14,3 +16,24 @@ function update_remove_post_updates() { 'update_post_update_set_blank_fetch_url_to_null' => '11.0.0', ]; } + +/** + * Removes the legacy 'Update Manager' disk cache. + */ +function update_post_update_clear_disk_cache(): void { + // @see _update_manager_unique_id() + $id = substr(hash('sha256', Settings::getHashSalt()), 0, 8); + // List of legacy 'Update Manager' cache directories. + $directories = [ + // @see _update_manager_cache_directory() + "temporary://update-cache-$id", + // @see _update_manager_extract_directory() + "temporary://update-extraction-$id", + ]; + foreach ($directories as $directory) { + if (is_dir($directory)) { + \Drupal::service('file_system')->deleteRecursive($directory); + } + } + +} diff --git a/core/modules/update/update.services.yml b/core/modules/update/update.services.yml index 465df135529a..bebf0398151c 100644 --- a/core/modules/update/update.services.yml +++ b/core/modules/update/update.services.yml @@ -21,6 +21,7 @@ services: update.root: class: Drupal\update\UpdateRoot arguments: ['@kernel', '@request_stack'] + deprecated: The "%service_id%" service is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no replacement. Use composer to manage the code for your site. See https://www.drupal.org/node/3522119 logger.channel.update: parent: logger.channel_base arguments: [ 'update' ] diff --git a/core/modules/views/src/Hook/ViewsViewsHooks.php b/core/modules/views/src/Hook/ViewsViewsHooks.php index 531f6c754fa2..a54decce9e62 100644 --- a/core/modules/views/src/Hook/ViewsViewsHooks.php +++ b/core/modules/views/src/Hook/ViewsViewsHooks.php @@ -183,6 +183,7 @@ class ViewsViewsHooks { if (is_array($result)) { $data = NestedArray::mergeDeep($result, $data); } + \Drupal::moduleHandler()->invoke($field_storage->getTypeProvider(), 'field_views_data_views_data_alter', [&$data, $field_storage]); } } } @@ -190,28 +191,6 @@ class ViewsViewsHooks { } /** - * Implements hook_views_data_alter(). - * - * Field modules can implement hook_field_views_data_views_data_alter() to - * alter the views data on a per field basis. This is weirdly named so as not - * to conflict with the \Drupal::moduleHandler()->alter('field_views_data') in - * views_views_data(). - */ - #[Hook('views_data_alter')] - public function viewsDataAlter(&$data): void { - $entity_type_manager = \Drupal::entityTypeManager(); - if (!$entity_type_manager->hasDefinition('field_storage_config')) { - return; - } - /** @var \Drupal\field\FieldStorageConfigInterface $field_storage */ - foreach ($entity_type_manager->getStorage('field_storage_config')->loadMultiple() as $field_storage) { - if (\Drupal::service('views.field_data_provider')->getSqlStorageForField($field_storage)) { - \Drupal::moduleHandler()->invoke($field_storage->getTypeProvider(), 'field_views_data_views_data_alter', [&$data, $field_storage]); - } - } - } - - /** * Implements hook_field_views_data(). * * The function implements the hook on behalf of 'core' because it adds a diff --git a/core/phpunit.xml.dist b/core/phpunit.xml.dist index 8915265e148e..c858081cad26 100644 --- a/core/phpunit.xml.dist +++ b/core/phpunit.xml.dist @@ -100,25 +100,35 @@ <directory>modules/**/tests/src/Kernel</directory> <directory>recipes/*/tests/src/Kernel</directory> <directory>profiles/**/tests/src/Kernel</directory> - <directory>profiles/tests/testing/modules/*/tests/src/Kernel</directory> <directory>themes/**/tests/src/Kernel</directory> <directory>../modules/**/tests/src/Kernel</directory> <directory>../profiles/**/tests/src/Kernel</directory> <directory>../themes/**/tests/src/Kernel</directory> + <!-- @todo remove line(s) below once PHPUnit 10 is no longer used; they + are redundant in PHPUnit 11+ that fully implements globstar (**) + pattern. + @see https://www.drupal.org/project/drupal/issues/3497116 + --> + <directory>profiles/tests/testing/modules/*/tests/src/Kernel</directory> </testsuite> <testsuite name="functional"> <directory>tests/Drupal/FunctionalTests</directory> <directory>modules/**/tests/src/Functional</directory> - <directory>modules/config/tests/config_test/tests/src/Functional</directory> - <directory>modules/system/tests/modules/entity_test/tests/src/Functional</directory> - <directory>modules/layout_builder/modules/layout_builder_expose_all_field_blocks/tests/src/Functional</directory> <directory>profiles/**/tests/src/Functional</directory> - <directory>profiles/demo_umami/modules/demo_umami_content/tests/src/Functional</directory> <directory>recipes/*/tests/src/Functional</directory> <directory>themes/**/tests/src/Functional</directory> <directory>../modules/**/tests/src/Functional</directory> <directory>../profiles/**/tests/src/Functional</directory> <directory>../themes/**/tests/src/Functional</directory> + <!-- @todo remove line(s) below once PHPUnit 10 is no longer used; they + are redundant in PHPUnit 11+ that fully implements globstar (**) + pattern. + @see https://www.drupal.org/project/drupal/issues/3497116 + --> + <directory>modules/config/tests/config_test/tests/src/Functional</directory> + <directory>modules/system/tests/modules/entity_test/tests/src/Functional</directory> + <directory>modules/layout_builder/modules/layout_builder_expose_all_field_blocks/tests/src/Functional</directory> + <directory>profiles/demo_umami/modules/demo_umami_content/tests/src/Functional</directory> </testsuite> <testsuite name="functional-javascript"> <directory>tests/Drupal/FunctionalJavascriptTests</directory> @@ -152,9 +162,6 @@ <directory>../modules/*/tests</directory> <directory>../modules/*/*/src/Tests</directory> <directory>../modules/*/*/tests</directory> - <directory suffix=".api.php">./lib/**</directory> - <directory suffix=".api.php">./modules/**</directory> - <directory suffix=".api.php">../modules/**</directory> </exclude> </source> </phpunit> diff --git a/core/scripts/js/vendor-update.js b/core/scripts/js/vendor-update.js index 1b5de61fa36d..4a6f2ef91c69 100644 --- a/core/scripts/js/vendor-update.js +++ b/core/scripts/js/vendor-update.js @@ -81,11 +81,11 @@ const assetsFolder = `${coreFolder}/assets/vendor`; }, { pack: 'htmx.org', + folder: 'htmx', library: 'htmx', files: [ { from: 'dist/htmx.min.js', to: 'htmx.min.js' }, { from: 'dist/htmx.js', to: 'htmx.js' }, - { from: 'dist/ext/debug.js', to: 'debug.js' }, ], }, { diff --git a/core/scripts/run-tests.sh b/core/scripts/run-tests.sh index c1ca97703df8..4545a00cc3ac 100755 --- a/core/scripts/run-tests.sh +++ b/core/scripts/run-tests.sh @@ -173,7 +173,7 @@ if ($args['clean']) { } if (!Composer::upgradePHPUnitCheck(Version::id())) { - simpletest_script_print_error("PHPUnit testing framework version 9 or greater is required when running on PHP 7.4 or greater. Run the command 'composer run-script drupal-phpunit-upgrade' in order to fix this."); + simpletest_script_print_error("PHPUnit testing framework version 11 or greater is required when running on PHP 8.4 or greater. Run the command 'composer run-script drupal-phpunit-upgrade' in order to fix this."); exit(SIMPLETEST_SCRIPT_EXIT_FAILURE); } diff --git a/core/tests/Drupal/KernelTests/Core/Test/PhpUnitTestDiscoveryTest.php b/core/tests/Drupal/KernelTests/Core/Test/PhpUnitTestDiscoveryTest.php index 6d7fcaeed9ae..705981f75079 100644 --- a/core/tests/Drupal/KernelTests/Core/Test/PhpUnitTestDiscoveryTest.php +++ b/core/tests/Drupal/KernelTests/Core/Test/PhpUnitTestDiscoveryTest.php @@ -6,6 +6,7 @@ namespace Drupal\KernelTests\Core\Test; use Drupal\Core\Test\TestDiscovery; use Drupal\KernelTests\KernelTestBase; +use Drupal\TestTools\PhpUnitCompatibility\RunnerVersion; use PHPUnit\TextUI\Configuration\Builder; use PHPUnit\TextUI\Configuration\TestSuiteBuilder; use Symfony\Component\Process\Process; @@ -96,14 +97,28 @@ class PhpUnitTestDiscoveryTest extends KernelTestBase { $phpUnitXmlList = new \DOMDocument(); $phpUnitXmlList->loadXML(file_get_contents($this->xmlOutputFile)); $phpUnitClientList = []; + // Try PHPUnit 10 format first. + // @todo remove once PHPUnit 10 is no longer used. foreach ($phpUnitXmlList->getElementsByTagName('testCaseClass') as $node) { $phpUnitClientList[] = $node->getAttribute('name'); } + // If empty, try PHPUnit 11+ format. + if (empty($phpUnitClientList)) { + foreach ($phpUnitXmlList->getElementsByTagName('testClass') as $node) { + $phpUnitClientList[] = $node->getAttribute('name'); + } + } asort($phpUnitClientList); // Check against Drupal's discovery. $this->assertEquals(implode("\n", $phpUnitClientList), implode("\n", $internalList), self::TEST_LIST_MISMATCH_MESSAGE); + // @todo once PHPUnit 10 is no longer used re-enable the rest of the test. + // @see https://www.drupal.org/project/drupal/issues/3497116 + if (RunnerVersion::getMajor() >= 11) { + $this->markTestIncomplete('On PHPUnit 11+ the test triggers warnings due to phpunit.xml setup. Re-enable in https://www.drupal.org/project/drupal/issues/3497116.'); + } + // PHPUnit's test discovery - via API. $phpUnitConfiguration = (new Builder())->build(['--configuration', 'core']); $phpUnitTestSuite = (new TestSuiteBuilder())->build($phpUnitConfiguration); diff --git a/core/tests/Drupal/TestTools/Extension/DeprecationBridge/DeprecationHandler.php b/core/tests/Drupal/TestTools/Extension/DeprecationBridge/DeprecationHandler.php index c176980bae27..f66ef7c8c947 100644 --- a/core/tests/Drupal/TestTools/Extension/DeprecationBridge/DeprecationHandler.php +++ b/core/tests/Drupal/TestTools/Extension/DeprecationBridge/DeprecationHandler.php @@ -76,6 +76,11 @@ final class DeprecationHandler { $environmentVariable = "ignoreFile=$deprecationIgnoreFilename"; } parse_str($environmentVariable, $configuration); + + $environmentVariable = getenv('PHPUNIT_FAIL_ON_PHPUNIT_DEPRECATION'); + $phpUnitDeprecationVariable = $environmentVariable !== FALSE ? $environmentVariable : TRUE; + $configuration['failOnPhpunitDeprecation'] = filter_var($phpUnitDeprecationVariable, \FILTER_VALIDATE_BOOLEAN); + return $configuration; } diff --git a/core/tests/Drupal/TestTools/PhpUnitCompatibility/PhpUnit11/TestCompatibilityTrait.php b/core/tests/Drupal/TestTools/PhpUnitCompatibility/PhpUnit11/TestCompatibilityTrait.php new file mode 100644 index 000000000000..84638f9f0f57 --- /dev/null +++ b/core/tests/Drupal/TestTools/PhpUnitCompatibility/PhpUnit11/TestCompatibilityTrait.php @@ -0,0 +1,13 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\TestTools\PhpUnitCompatibility\PhpUnit11; + +/** + * Drupal's forward compatibility layer with multiple versions of PHPUnit. + * + * @internal + */ +trait TestCompatibilityTrait { +} diff --git a/core/tests/Drupal/Tests/Component/Datetime/DateTimePlusTest.php b/core/tests/Drupal/Tests/Component/Datetime/DateTimePlusTest.php index 8dd4d8fb5948..ae46c3cc5a56 100644 --- a/core/tests/Drupal/Tests/Component/Datetime/DateTimePlusTest.php +++ b/core/tests/Drupal/Tests/Component/Datetime/DateTimePlusTest.php @@ -671,16 +671,16 @@ class DateTimePlusTest extends TestCase { // There should be a 19 hour time interval between // new years in Sydney and new years in LA in year 2000. [ - 'input2' => DateTimePlus::createFromFormat('Y-m-d H:i:s', '2000-01-01 00:00:00', new \DateTimeZone('Australia/Sydney')), - 'input1' => DateTimePlus::createFromFormat('Y-m-d H:i:s', '2000-01-01 00:00:00', new \DateTimeZone('America/Los_Angeles')), + 'input1' => DateTimePlus::createFromFormat('Y-m-d H:i:s', '2000-01-01 00:00:00', new \DateTimeZone('Australia/Sydney')), + 'input2' => DateTimePlus::createFromFormat('Y-m-d H:i:s', '2000-01-01 00:00:00', new \DateTimeZone('America/Los_Angeles')), 'absolute' => FALSE, 'expected' => $positive_19_hours, ], // In 1970 Sydney did not observe daylight savings time // So there is only an 18 hour time interval. [ - 'input2' => DateTimePlus::createFromFormat('Y-m-d H:i:s', '1970-01-01 00:00:00', new \DateTimeZone('Australia/Sydney')), - 'input1' => DateTimePlus::createFromFormat('Y-m-d H:i:s', '1970-01-01 00:00:00', new \DateTimeZone('America/Los_Angeles')), + 'input1' => DateTimePlus::createFromFormat('Y-m-d H:i:s', '1970-01-01 00:00:00', new \DateTimeZone('Australia/Sydney')), + 'input2' => DateTimePlus::createFromFormat('Y-m-d H:i:s', '1970-01-01 00:00:00', new \DateTimeZone('America/Los_Angeles')), 'absolute' => FALSE, 'expected' => $positive_18_hours, ], diff --git a/core/tests/Drupal/Tests/Component/Utility/HtmlTest.php b/core/tests/Drupal/Tests/Component/Utility/HtmlTest.php index b2c459e06a78..800483fab501 100644 --- a/core/tests/Drupal/Tests/Component/Utility/HtmlTest.php +++ b/core/tests/Drupal/Tests/Component/Utility/HtmlTest.php @@ -65,6 +65,7 @@ class HtmlTest extends TestCase { $id1 = 'abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789'; $id2 = '¡¢£¤¥'; $id3 = 'css__identifier__with__double__underscores'; + $id4 = "\x80\x81"; return [ // Verify that no valid ASCII characters are stripped from the identifier. [$id1, $id1, []], @@ -73,6 +74,8 @@ class HtmlTest extends TestCase { [$id2, $id2, []], // Verify that double underscores are not stripped from the identifier. [$id3, $id3], + // Confirm that NULL identifier does not trigger PHP 8.1 deprecation message. + ['', $id4], // Verify that invalid characters (including non-breaking space) are // stripped from the identifier. ['invalid_identifier', 'invalid_ !"#$%&\'()*+,./:;<=>?@[\\]^`{|}~ identifier', []], diff --git a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php index 2b4d2990d52e..76f5cc118ae6 100644 --- a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php +++ b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php @@ -172,25 +172,17 @@ class ConfigEntityStorageTest extends UnitTestCase { */ public function testCreateWithPredefinedUuid(): void { $this->cacheTagsInvalidator->invalidateTags(Argument::cetera())->shouldNotBeCalled(); - - $entity = $this->getMockEntity(); - $entity->set('id', 'foo'); - $entity->set('langcode', 'hu'); - $entity->set('uuid', 'baz'); - $entity->setOriginalId('foo'); - $entity->enforceIsNew(); - - $this->moduleHandler->invokeAll('test_entity_type_create', [$entity]) - ->shouldBeCalled(); - $this->moduleHandler->invokeAll('entity_create', [$entity, 'test_entity_type']) - ->shouldBeCalled(); - $this->uuidService->generate()->shouldNotBeCalled(); $entity = $this->entityStorage->create(['id' => 'foo', 'uuid' => 'baz']); $this->assertInstanceOf(EntityInterface::class, $entity); $this->assertSame('foo', $entity->id()); $this->assertSame('baz', $entity->uuid()); + + $this->moduleHandler->invokeAll('test_entity_type_create', [$entity]) + ->shouldBeCalled(); + $this->moduleHandler->invokeAll('entity_create', [$entity, 'test_entity_type']) + ->shouldBeCalled(); } /** @@ -202,25 +194,18 @@ class ConfigEntityStorageTest extends UnitTestCase { */ public function testCreate() { $this->cacheTagsInvalidator->invalidateTags(Argument::cetera())->shouldNotBeCalled(); + $this->uuidService->generate()->willReturn('bar'); - $entity = $this->getMockEntity(); - $entity->set('id', 'foo'); - $entity->set('langcode', 'hu'); - $entity->set('uuid', 'bar'); - $entity->setOriginalId('foo'); - $entity->enforceIsNew(); + $entity = $this->entityStorage->create(['id' => 'foo']); + $this->assertInstanceOf(EntityInterface::class, $entity); + $this->assertSame('foo', $entity->id()); + $this->assertSame('bar', $entity->uuid()); $this->moduleHandler->invokeAll('test_entity_type_create', [$entity]) ->shouldBeCalled(); $this->moduleHandler->invokeAll('entity_create', [$entity, 'test_entity_type']) ->shouldBeCalled(); - $this->uuidService->generate()->willReturn('bar'); - - $entity = $this->entityStorage->create(['id' => 'foo']); - $this->assertInstanceOf(EntityInterface::class, $entity); - $this->assertSame('foo', $entity->id()); - $this->assertSame('bar', $entity->uuid()); return $entity; } diff --git a/core/tests/Drupal/Tests/Core/Datetime/DrupalDateTimeTest.php b/core/tests/Drupal/Tests/Core/Datetime/DrupalDateTimeTest.php index e1ec84395f9d..40b94bd046bf 100644 --- a/core/tests/Drupal/Tests/Core/Datetime/DrupalDateTimeTest.php +++ b/core/tests/Drupal/Tests/Core/Datetime/DrupalDateTimeTest.php @@ -84,16 +84,16 @@ class DrupalDateTimeTest extends UnitTestCase { // There should be a 19 hour time interval between // new years in Sydney and new years in LA in year 2000. [ - 'input2' => DrupalDateTime::createFromFormat('Y-m-d H:i:s', '2000-01-01 00:00:00', new \DateTimeZone('Australia/Sydney'), $settings), - 'input1' => DrupalDateTime::createFromFormat('Y-m-d H:i:s', '2000-01-01 00:00:00', new \DateTimeZone('America/Los_Angeles'), $settings), + 'input1' => DrupalDateTime::createFromFormat('Y-m-d H:i:s', '2000-01-01 00:00:00', new \DateTimeZone('Australia/Sydney'), $settings), + 'input2' => DrupalDateTime::createFromFormat('Y-m-d H:i:s', '2000-01-01 00:00:00', new \DateTimeZone('America/Los_Angeles'), $settings), 'absolute' => FALSE, 'expected' => $positive_19_hours, ], // In 1970 Sydney did not observe daylight savings time // So there is only an 18 hour time interval. [ - 'input2' => DrupalDateTime::createFromFormat('Y-m-d H:i:s', '1970-01-01 00:00:00', new \DateTimeZone('Australia/Sydney'), $settings), - 'input1' => DrupalDateTime::createFromFormat('Y-m-d H:i:s', '1970-01-01 00:00:00', new \DateTimeZone('America/Los_Angeles'), $settings), + 'input1' => DrupalDateTime::createFromFormat('Y-m-d H:i:s', '1970-01-01 00:00:00', new \DateTimeZone('Australia/Sydney'), $settings), + 'input2' => DrupalDateTime::createFromFormat('Y-m-d H:i:s', '1970-01-01 00:00:00', new \DateTimeZone('America/Los_Angeles'), $settings), 'absolute' => FALSE, 'expected' => $positive_18_hours, ], diff --git a/core/tests/Drupal/Tests/Core/Entity/KeyValueStore/KeyValueEntityStorageTest.php b/core/tests/Drupal/Tests/Core/Entity/KeyValueStore/KeyValueEntityStorageTest.php index f57a80d1393c..2381b64b83a5 100644 --- a/core/tests/Drupal/Tests/Core/Entity/KeyValueStore/KeyValueEntityStorageTest.php +++ b/core/tests/Drupal/Tests/Core/Entity/KeyValueStore/KeyValueEntityStorageTest.php @@ -206,11 +206,8 @@ class KeyValueEntityStorageTest extends UnitTestCase { /** * @covers ::create * @covers ::doCreate - * - * @return \Drupal\Core\Entity\EntityInterface - * The newly created entity instance with the specified ID and generated UUID. */ - public function testCreate() { + public function testCreate(): void { $entity = $this->getMockEntity(EntityBaseTest::class, [], ['toArray']); $this->entityType->expects($this->once()) ->method('getClass') @@ -231,24 +228,18 @@ class KeyValueEntityStorageTest extends UnitTestCase { $this->assertInstanceOf('Drupal\Core\Entity\EntityInterface', $entity); $this->assertSame('foo', $entity->id()); $this->assertSame('bar', $entity->uuid()); - return $entity; } /** * @covers ::save * @covers ::doSave - * - * @param \Drupal\Core\Entity\EntityInterface $entity - * The entity. - * - * @return \Drupal\Core\Entity\EntityInterface - * The saved entity instance after insertion. - * - * @depends testCreate */ - public function testSaveInsert(EntityInterface $entity) { + public function testSaveInsert(): EntityInterface&MockObject { $this->setUpKeyValueEntityStorage(); + $entity = $this->getMockEntity(EntityBaseTest::class, [['id' => 'foo']], ['toArray']); + $entity->enforceIsNew(); + $expected = ['id' => 'foo']; $this->keyValueStore->expects($this->exactly(2)) ->method('has') @@ -285,12 +276,9 @@ class KeyValueEntityStorageTest extends UnitTestCase { * @param \Drupal\Core\Entity\EntityInterface $entity * The entity. * - * @return \Drupal\Core\Entity\EntityInterface - * The updated entity instance after saving. - * * @depends testSaveInsert */ - public function testSaveUpdate(EntityInterface $entity) { + public function testSaveUpdate(EntityInterface $entity): void { $this->entityType->expects($this->once()) ->method('getClass') ->willReturn(get_class($entity)); @@ -320,7 +308,6 @@ class KeyValueEntityStorageTest extends UnitTestCase { ->with('foo', $expected); $return = $this->entityStorage->save($entity); $this->assertSame(SAVED_UPDATED, $return); - return $entity; } /** diff --git a/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageTest.php b/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageTest.php index 37cede409b88..5653e8a356b0 100644 --- a/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageTest.php +++ b/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageTest.php @@ -1105,12 +1105,7 @@ class SqlContentEntityStorageTest extends UnitTestCase { $this->setUpEntityStorage(); $entity = $this->entityStorage->create(); - $entity->expects($this->atLeastOnce()) - ->method('id') - ->willReturn('foo'); - $this->assertInstanceOf(EntityInterface::class, $entity); - $this->assertSame('foo', $entity->id()); $this->assertTrue($entity->isNew()); } diff --git a/core/tests/PHPStan/composer.json b/core/tests/PHPStan/composer.json index ab10409fcbff..f6fb20053884 100644 --- a/core/tests/PHPStan/composer.json +++ b/core/tests/PHPStan/composer.json @@ -2,7 +2,7 @@ "name": "drupal/phpstan-testing", "description": "Tests Drupal core's PHPStan rules", "require-dev": { - "phpunit/phpunit": "^10", + "phpunit/phpunit": "^11", "phpstan/phpstan": "2.1.12" }, "license": "GPL-2.0-or-later", diff --git a/core/themes/claro/claro.theme b/core/themes/claro/claro.theme index c406fed47c22..a031dc860c35 100644 --- a/core/themes/claro/claro.theme +++ b/core/themes/claro/claro.theme @@ -665,7 +665,7 @@ function _claro_convert_link_to_action_link(array $link, $icon_name = NULL, $siz } /** - * Implements hook_form_BASE_FORM_ID_alter() for \Drupal\node\NodeForm. + * Implements hook_form_BASE_FORM_ID_alter() for \Drupal\node\Form\NodeForm. * * Changes vertical tabs to container. */ diff --git a/core/themes/stable9/templates/admin/authorize-report.html.twig b/core/themes/stable9/templates/admin/authorize-report.html.twig index 2e5a59c0c03b..8784ca30cd89 100644 --- a/core/themes/stable9/templates/admin/authorize-report.html.twig +++ b/core/themes/stable9/templates/admin/authorize-report.html.twig @@ -10,6 +10,11 @@ * - attributes: HTML attributes for the element. * * @see template_preprocess_authorize_report() + * + * @deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no + * replacement. Use composer to manage the code for your site. + * + * @see https://www.drupal.org/node/3522119 */ #} {% if messages %} diff --git a/sites/default/default.settings.php b/sites/default/default.settings.php index 666a39643736..d4ba8a91829a 100644 --- a/sites/default/default.settings.php +++ b/sites/default/default.settings.php @@ -476,30 +476,6 @@ $settings['update_free_access'] = FALSE; # $settings['class_loader_auto_detect'] = FALSE; /** - * Authorized file system operations: - * - * The Update Manager module included with Drupal provides a mechanism for - * site administrators to securely install missing updates for the site - * directly through the web user interface. On securely-configured servers, - * the Update manager will require the administrator to provide SSH or FTP - * credentials before allowing the installation to proceed; this allows the - * site to update the new files as the user who owns all the Drupal files, - * instead of as the user the webserver is running as. On servers where the - * webserver user is itself the owner of the Drupal files, the administrator - * will not be prompted for SSH or FTP credentials (note that these server - * setups are common on shared hosting, but are inherently insecure). - * - * Some sites might wish to disable the above functionality, and only update - * the code directly via SSH or FTP themselves. This setting completely - * disables all functionality related to these authorized file operations. - * - * @see https://www.drupal.org/node/244924 - * - * Remove the leading hash signs to disable. - */ -# $settings['allow_authorize_operations'] = FALSE; - -/** * Default mode for directories and files written by Drupal. * * Value should be in PHP Octal Notation, with leading zero. |