summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--.gitlab-ci.yml1
-rw-r--r--.gitlab-ci/pipeline.yml2
-rw-r--r--core/.phpstan-baseline.php12
-rw-r--r--core/lib/Drupal/Core/Extension/ModuleHandler.php4
-rw-r--r--core/lib/Drupal/Core/Hook/HookCollectorPass.php8
-rw-r--r--core/modules/ckeditor5/tests/src/Unit/CKEditor5ImageControllerTest.php85
-rw-r--r--core/modules/file/tests/file_test/src/Form/FileRequiredTestForm.php4
-rw-r--r--core/modules/file/tests/file_test/src/Form/FileTestForm.php15
-rw-r--r--core/modules/layout_builder/src/InlineBlockEntityOperations.php2
-rw-r--r--core/modules/node/node.module4
-rw-r--r--core/modules/system/tests/modules/container_initialize/container_initialize.info.yml5
-rw-r--r--core/modules/system/tests/modules/container_initialize/container_initialize.module10
-rw-r--r--core/modules/system/tests/src/Functional/Hook/HookCollectorPassTest.php61
-rw-r--r--core/tests/Drupal/BuildTests/Composer/Plugin/Unpack/Functional/UnpackRecipeTest.php (renamed from core/tests/Drupal/Tests/Composer/Plugin/Unpack/Functional/UnpackRecipeTest.php)2
14 files changed, 180 insertions, 35 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 58f39c03ac17..936401851968 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -234,6 +234,7 @@ default:
_TARGET_DB_DRIVER: "mysql"
_TARGET_DB_DRIVER_MODULE: "mysql"
PERFORMANCE_TEST: $PERFORMANCE_TEST
+ OPENTELEMETRY_COLLECTOR: $OPENTELEMETRY_COLLECTOR
# Run on MR, schedule, push, parent pipeline and performance test.
rules:
- if: $CI_PIPELINE_SOURCE == "push" && $CI_PROJECT_ROOT_NAMESPACE == "project"
diff --git a/.gitlab-ci/pipeline.yml b/.gitlab-ci/pipeline.yml
index 88a60ff66594..4efc20087814 100644
--- a/.gitlab-ci/pipeline.yml
+++ b/.gitlab-ci/pipeline.yml
@@ -273,7 +273,7 @@ variables:
[[ $_TARGET_DB == mariadb* ]] && export SIMPLETEST_DB=$_TARGET_DB_DRIVER://$MYSQL_USER:$MYSQL_PASSWORD@database/$MYSQL_DATABASE?module=$_TARGET_DB_DRIVER_MODULE
[[ $_TARGET_DB == pgsql* ]] && export SIMPLETEST_DB=pgsql://$POSTGRES_USER:$POSTGRES_PASSWORD@database/$POSTGRES_DB?module=pgsql
- composer install --optimize-autoloader
- - export OTEL_COLLECTOR="$OTEL_COLLECTOR"
+ - export OTEL_COLLECTOR="$OPENTELEMETRY_COLLECTOR"
- 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/
- sudo -u www-data git config --global --add safe.directory $CI_PROJECT_DIR
diff --git a/core/.phpstan-baseline.php b/core/.phpstan-baseline.php
index e0660c7dc93e..4b4b01e4701b 100644
--- a/core/.phpstan-baseline.php
+++ b/core/.phpstan-baseline.php
@@ -17462,18 +17462,6 @@ $ignoreErrors[] = [
'path' => __DIR__ . '/modules/file/tests/file_module_test/src/Form/FileModuleTestForm.php',
];
$ignoreErrors[] = [
- 'message' => '#^Method Drupal\\\\file_test\\\\Form\\\\FileTestForm\\:\\:submitForm\\(\\) has no return type specified\\.$#',
- 'identifier' => 'missingType.return',
- 'count' => 1,
- 'path' => __DIR__ . '/modules/file/tests/file_test/src/Form/FileTestForm.php',
-];
-$ignoreErrors[] = [
- 'message' => '#^Method Drupal\\\\file_test\\\\Form\\\\FileTestForm\\:\\:validateForm\\(\\) has no return type specified\\.$#',
- 'identifier' => 'missingType.return',
- 'count' => 1,
- 'path' => __DIR__ . '/modules/file/tests/file_test/src/Form/FileTestForm.php',
-];
-$ignoreErrors[] = [
'message' => '#^Method Drupal\\\\file_test\\\\Form\\\\FileTestSaveUploadFromForm\\:\\:create\\(\\) has no return type specified\\.$#',
'identifier' => 'missingType.return',
'count' => 1,
diff --git a/core/lib/Drupal/Core/Extension/ModuleHandler.php b/core/lib/Drupal/Core/Extension/ModuleHandler.php
index ad361d3fe669..b187560c10fb 100644
--- a/core/lib/Drupal/Core/Extension/ModuleHandler.php
+++ b/core/lib/Drupal/Core/Extension/ModuleHandler.php
@@ -230,7 +230,9 @@ class ModuleHandler implements ModuleHandlerInterface {
protected function add($type, $name, $path) {
$pathname = "$path/$name.info.yml";
$php_file_path = $this->root . "/$path/$name.$type";
- $filename = file_exists($php_file_path) ? "$name.$type" : NULL;
+ if ($filename = file_exists($php_file_path) ? "$name.$type" : NULL) {
+ include_once $php_file_path;
+ }
$this->moduleList[$name] = new Extension($this->root, $type, $pathname, $filename);
$this->resetImplementations();
$hook_collector = HookCollectorPass::collectAllHookImplementations([$name => ['pathname' => $pathname]]);
diff --git a/core/lib/Drupal/Core/Hook/HookCollectorPass.php b/core/lib/Drupal/Core/Hook/HookCollectorPass.php
index 7c0f913ca219..75bbb039414e 100644
--- a/core/lib/Drupal/Core/Hook/HookCollectorPass.php
+++ b/core/lib/Drupal/Core/Hook/HookCollectorPass.php
@@ -403,12 +403,6 @@ class HookCollectorPass implements CompilerPassInterface {
$extension = $fileinfo->getExtension();
$filename = $fileinfo->getPathname();
- if (($extension === 'module' || $extension === 'profile') && !$iterator->getDepth() && !$skip_procedural) {
- // There is an expectation for all modules and profiles to be loaded.
- // .module and .profile files are not supposed to be in subdirectories.
- // These need to be loaded even if the module has no procedural hooks.
- include_once $filename;
- }
if ($extension === 'php') {
$cached = $hook_file_cache->get($filename);
if ($cached) {
@@ -512,11 +506,13 @@ class HookCollectorPass implements CompilerPassInterface {
$function = $module . '_' . $hook;
if ($hook === 'hook_info') {
$this->hookInfo[] = $function;
+ include_once $fileinfo->getPathname();
}
elseif ($hook === 'module_implements_alter') {
$message = "$function without a #[LegacyModuleImplementsAlter] attribute is deprecated in drupal:11.2.0 and removed in drupal:12.0.0. See https://www.drupal.org/node/3496788";
@trigger_error($message, E_USER_DEPRECATED);
$this->moduleImplementsAlters[] = $function;
+ include_once $fileinfo->getPathname();
}
$this->proceduralImplementations[$hook][] = $module;
if ($fileinfo->getExtension() !== 'module') {
diff --git a/core/modules/ckeditor5/tests/src/Unit/CKEditor5ImageControllerTest.php b/core/modules/ckeditor5/tests/src/Unit/CKEditor5ImageControllerTest.php
new file mode 100644
index 000000000000..bb69c28c6fbf
--- /dev/null
+++ b/core/modules/ckeditor5/tests/src/Unit/CKEditor5ImageControllerTest.php
@@ -0,0 +1,85 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\Tests\ckeditor5\Unit;
+
+use Drupal\ckeditor5\Controller\CKEditor5ImageController;
+use Drupal\ckeditor5\Plugin\CKEditor5PluginManagerInterface;
+use Drupal\Core\Entity\EntityConstraintViolationList;
+use Drupal\Core\Entity\EntityStorageInterface;
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Entity\EntityTypeRepositoryInterface;
+use Drupal\Core\File\FileSystemInterface;
+use Drupal\Core\Lock\LockBackendInterface;
+use Drupal\editor\EditorInterface;
+use Drupal\file\Entity\File;
+use Drupal\file\FileInterface;
+use Drupal\file\Upload\FileUploadHandlerInterface;
+use Drupal\Tests\UnitTestCase;
+use Prophecy\Argument;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpKernel\Exception\HttpException;
+
+/**
+ * Tests CKEditor5ImageController.
+ *
+ * @group ckeditor5
+ * @coversDefaultClass \Drupal\ckeditor5\Controller\CKEditor5ImageController
+ */
+final class CKEditor5ImageControllerTest extends UnitTestCase {
+
+ /**
+ * Tests that upload fails correctly when the file is too large.
+ */
+ public function testInvalidFile(): void {
+ $file_system = $this->prophesize(FileSystemInterface::class);
+ $file_system->move(Argument::any())->shouldNotBeCalled();
+ $directory = 'public://';
+ $file_system->prepareDirectory($directory, FileSystemInterface::CREATE_DIRECTORY)->willReturn(TRUE);
+ $file_system->getDestinationFilename(Argument::cetera())->willReturn('/tmp/foo.txt');
+ $lock = $this->prophesize(LockBackendInterface::class);
+ $lock->acquire(Argument::any())->willReturn(TRUE);
+ $container = $this->prophesize(ContainerInterface::class);
+ $file_storage = $this->prophesize(EntityStorageInterface::class);
+ $file = $this->prophesize(FileInterface::class);
+ $violations = $this->prophesize(EntityConstraintViolationList::class);
+ $violations->count()->willReturn(0);
+ $file->validate()->willReturn($violations->reveal());
+ $file_storage->create(Argument::any())->willReturn($file->reveal());
+ $entity_type_manager = $this->prophesize(EntityTypeManagerInterface::class);
+ $entity_type_manager->getStorage('file')->willReturn($file_storage->reveal());
+ $container->get('entity_type.manager')->willReturn($entity_type_manager->reveal());
+ $entity_type_repository = $this->prophesize(EntityTypeRepositoryInterface::class);
+ $entity_type_repository->getEntityTypeFromClass(File::class)->willReturn('file');
+ $container->get('entity_type.repository')->willReturn($entity_type_repository->reveal());
+ \Drupal::setContainer($container->reveal());
+ $controller = new CKEditor5ImageController(
+ $file_system->reveal(),
+ $this->prophesize(FileUploadHandlerInterface::class)->reveal(),
+ $lock->reveal(),
+ $this->prophesize(CKEditor5PluginManagerInterface::class)->reveal(),
+ );
+ // We can't use vfsstream here because of how Symfony request works.
+ $file_uri = tempnam(sys_get_temp_dir(), 'tmp');
+ $fp = fopen($file_uri, 'w');
+ fwrite($fp, 'foo');
+ fclose($fp);
+ $request = Request::create('/', files: [
+ 'upload' => [
+ 'name' => 'foo.txt',
+ 'type' => 'text/plain',
+ 'size' => 42,
+ 'tmp_name' => $file_uri,
+ 'error' => \UPLOAD_ERR_FORM_SIZE,
+ ],
+ ]);
+ $editor = $this->prophesize(EditorInterface::class);
+ $request->attributes->set('editor', $editor->reveal());
+ $this->expectException(HttpException::class);
+ $this->expectExceptionMessage('The file "foo.txt" exceeds the upload limit defined in your form.');
+ $controller->upload($request);
+ }
+
+}
diff --git a/core/modules/file/tests/file_test/src/Form/FileRequiredTestForm.php b/core/modules/file/tests/file_test/src/Form/FileRequiredTestForm.php
index 1491510fd648..4bdcf5455f9d 100644
--- a/core/modules/file/tests/file_test/src/Form/FileRequiredTestForm.php
+++ b/core/modules/file/tests/file_test/src/Form/FileRequiredTestForm.php
@@ -14,14 +14,14 @@ class FileRequiredTestForm extends FileTestForm {
/**
* {@inheritdoc}
*/
- public function getFormId() {
+ public function getFormId(): string {
return '_file_required_test_form';
}
/**
* {@inheritdoc}
*/
- public function buildForm(array $form, FormStateInterface $form_state) {
+ public function buildForm(array $form, FormStateInterface $form_state): array {
$form = parent::buildForm($form, $form_state);
$form['file_test_upload']['#required'] = TRUE;
return $form;
diff --git a/core/modules/file/tests/file_test/src/Form/FileTestForm.php b/core/modules/file/tests/file_test/src/Form/FileTestForm.php
index d021a538f44c..902c675cdcf4 100644
--- a/core/modules/file/tests/file_test/src/Form/FileTestForm.php
+++ b/core/modules/file/tests/file_test/src/Form/FileTestForm.php
@@ -6,28 +6,28 @@ namespace Drupal\file_test\Form;
use Drupal\Core\File\FileExists;
use Drupal\Core\File\FileSystemInterface;
-use Drupal\Core\Form\FormInterface;
+use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
/**
* File test form class.
*/
-class FileTestForm implements FormInterface {
+class FileTestForm extends FormBase {
use FileTestFormTrait;
use StringTranslationTrait;
/**
* {@inheritdoc}
*/
- public function getFormId() {
+ public function getFormId(): string {
return '_file_test_form';
}
/**
* {@inheritdoc}
*/
- public function buildForm(array $form, FormStateInterface $form_state) {
+ public function buildForm(array $form, FormStateInterface $form_state): array {
$form = $this->baseForm($form, $form_state);
@@ -42,12 +42,7 @@ class FileTestForm implements FormInterface {
/**
* {@inheritdoc}
*/
- public function validateForm(array &$form, FormStateInterface $form_state) {}
-
- /**
- * {@inheritdoc}
- */
- public function submitForm(array &$form, FormStateInterface $form_state) {
+ public function submitForm(array &$form, FormStateInterface $form_state): void {
// Process the upload and perform validation. Note: we're using the
// form value for the $replace parameter.
if (!$form_state->isValueEmpty('file_subdir')) {
diff --git a/core/modules/layout_builder/src/InlineBlockEntityOperations.php b/core/modules/layout_builder/src/InlineBlockEntityOperations.php
index 16bda99a45cd..7a832ad284c6 100644
--- a/core/modules/layout_builder/src/InlineBlockEntityOperations.php
+++ b/core/modules/layout_builder/src/InlineBlockEntityOperations.php
@@ -134,8 +134,6 @@ class InlineBlockEntityOperations implements ContainerInjectionInterface {
* The parent entity.
*/
public function handleEntityDelete(EntityInterface $entity) {
- // @todo In https://www.drupal.org/node/3008943 call
- // \Drupal\layout_builder\LayoutEntityHelperTrait::isLayoutCompatibleEntity().
$this->usage->removeByLayoutEntity($entity);
}
diff --git a/core/modules/node/node.module b/core/modules/node/node.module
index f14d843faa10..1fb4071ba47d 100644
--- a/core/modules/node/node.module
+++ b/core/modules/node/node.module
@@ -36,8 +36,12 @@ use Drupal\node\NodeTypeInterface;
* @return array|false
* A renderable array containing a list of linked node titles fetched from
* $result, or FALSE if there are no rows in $result.
+ *
+ * @deprecated in drupal:11.3.0 and is removed from drupal:12.0.0. There is no replacement.
+ * @see https://www.drupal.org/node/3531959
*/
function node_title_list(StatementInterface $result, $title = NULL) {
+ @trigger_error(__FUNCTION__ . '() is deprecated in drupal:11.3.0 and is removed from drupal:12.0.0. There is no replacement. See https://www.drupal.org/node/3531959', E_USER_DEPRECATED);
$items = [];
$num_rows = FALSE;
$nids = [];
diff --git a/core/modules/system/tests/modules/container_initialize/container_initialize.info.yml b/core/modules/system/tests/modules/container_initialize/container_initialize.info.yml
new file mode 100644
index 000000000000..46411d2ea544
--- /dev/null
+++ b/core/modules/system/tests/modules/container_initialize/container_initialize.info.yml
@@ -0,0 +1,5 @@
+name: 'Container initialize'
+type: module
+description: 'Support module for HookCollectorPass testing.'
+package: Testing
+version: VERSION
diff --git a/core/modules/system/tests/modules/container_initialize/container_initialize.module b/core/modules/system/tests/modules/container_initialize/container_initialize.module
new file mode 100644
index 000000000000..5c8e0aff74ea
--- /dev/null
+++ b/core/modules/system/tests/modules/container_initialize/container_initialize.module
@@ -0,0 +1,10 @@
+<?php
+
+/**
+ * @file
+ * Used to test bare container calls in .module files.
+ */
+
+declare(strict_types=1);
+
+\Drupal::getContainer()->getParameter('site.path');
diff --git a/core/modules/system/tests/src/Functional/Hook/HookCollectorPassTest.php b/core/modules/system/tests/src/Functional/Hook/HookCollectorPassTest.php
new file mode 100644
index 000000000000..59d69d1242cb
--- /dev/null
+++ b/core/modules/system/tests/src/Functional/Hook/HookCollectorPassTest.php
@@ -0,0 +1,61 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\Tests\system\Functional\Hook;
+
+use Drupal\Tests\BrowserTestBase;
+use Drupal\Core\Url;
+
+/**
+ * Tests services in .module files.
+ *
+ * @group Hook
+ */
+class HookCollectorPassTest extends BrowserTestBase {
+
+ /**
+ * {@inheritdoc}
+ */
+ protected static $modules = ['container_initialize'];
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $defaultTheme = 'stark';
+
+ /**
+ * Tests installing a module with a Drupal container call outside functions.
+ *
+ * If this is removed then it needs to be moved to a test that installs modules through
+ * admin/modules.
+ */
+ public function testContainerOutsideFunction(): void {
+ $settings['settings']['rebuild_access'] = (object) [
+ 'value' => TRUE,
+ 'required' => TRUE,
+ ];
+
+ // This simulates installing the module and running a cache rebuild in a
+ // separate request.
+ $this->writeSettings($settings);
+ $this->rebuildAll();
+ $this->drupalGet(Url::fromUri('base:core/rebuild.php'));
+ $this->assertSession()->pageTextNotContains('ContainerNotInitializedException');
+ // Successful response from rebuild.php should redirect to the front page.
+ $this->assertSession()->addressEquals('/');
+
+ // If this file is removed then this test needs to be updated to trigger
+ // the container rebuild error from https://www.drupal.org/i/3505049
+ $config_module_file = $this->root . '/core/modules/system/tests/modules/container_initialize/container_initialize.module';
+ $this->assertFileExists($config_module_file, 'This test depends on a container call in a .module file');
+ // Confirm that the file still has a bare container call.
+ $bare_container = "declare(strict_types=1);
+
+\Drupal::getContainer()->getParameter('site.path');
+";
+ $file_content = file_get_contents($config_module_file);
+ $this->assertStringContainsString($bare_container, $file_content, 'container_initialize.module container test feature is missing.');
+ }
+
+}
diff --git a/core/tests/Drupal/Tests/Composer/Plugin/Unpack/Functional/UnpackRecipeTest.php b/core/tests/Drupal/BuildTests/Composer/Plugin/Unpack/Functional/UnpackRecipeTest.php
index b74349256892..1397a78cf694 100644
--- a/core/tests/Drupal/Tests/Composer/Plugin/Unpack/Functional/UnpackRecipeTest.php
+++ b/core/tests/Drupal/BuildTests/Composer/Plugin/Unpack/Functional/UnpackRecipeTest.php
@@ -2,7 +2,7 @@
declare(strict_types=1);
-namespace Drupal\Tests\Composer\Plugin\Unpack\Functional;
+namespace Drupal\BuildTests\Composer\Plugin\Unpack\Functional;
use Composer\InstalledVersions;
use Composer\Util\Filesystem;