Skip to content
Snippets Groups Projects
Unverified Commit 51ae0389 authored by Alex Pott's avatar Alex Pott
Browse files

Issue #3491782 by phenaproxima, penyaskito, thejimbirch, gambry, amateescu,...

Issue #3491782 by phenaproxima, penyaskito, thejimbirch, gambry, amateescu, alexpott: When applying a recipe, we need to trigger an event pre importing content
parent ac347da7
No related branches found
No related tags found
11 merge requests!11197Issue #3506427 by eduardo morales alberti: Remove responsive_image.ajax from hook,!11131[10.4.x-only-DO-NOT-MERGE]: Issue ##2842525 Ajax attached to Views exposed filter form does not trigger callbacks,!10786Issue #3490579 by shalini_jha, mstrelan: Add void return to all views...,!5423Draft: Resolve #3329907 "Test2",!3878Removed unused condition head title for views,!3818Issue #2140179: $entity->original gets stale between updates,!3478Issue #3337882: Deleted menus are not removed from content type config,!2964Issue #2865710 : Dependencies from only one instance of a widget are used in display modes,!2062Issue #3246454: Add weekly granularity to views date sort,!10223132456: Fix issue where views instances are emptied before an ajax request is complete,!579Issue #2230909: Simple decimals fail to pass validation
Pipeline #375603 passed with warnings
Pipeline: drupal

#375626

    Pipeline: drupal

    #375619

      Pipeline: drupal

      #375617

        +4
        ......@@ -18,6 +18,7 @@
        use Drupal\user\EntityOwnerInterface;
        use Psr\Log\LoggerAwareInterface;
        use Psr\Log\LoggerAwareTrait;
        use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
        /**
        * A service for handling import of content.
        ......@@ -45,6 +46,7 @@ public function __construct(
        private readonly FileSystemInterface $fileSystem,
        private readonly LanguageManagerInterface $languageManager,
        private readonly EntityRepositoryInterface $entityRepository,
        private readonly EventDispatcherInterface $eventDispatcher,
        ) {}
        /**
        ......@@ -70,6 +72,9 @@ public function importContent(Finder $content, Existing $existing = Existing::Er
        return;
        }
        $event = new PreImportEvent($content, $existing);
        $skip = $this->eventDispatcher->dispatch($event)->getSkipList();
        $account = $this->accountSwitcher->switchToAdministrator();
        try {
        ......@@ -80,6 +85,19 @@ public function importContent(Finder $content, Existing $existing = Existing::Er
        assert(is_string($entity_type_id));
        assert(is_string($path));
        // The event subscribers asked to skip importing this entity. If they
        // explained why, log that.
        if (array_key_exists($uuid, $skip)) {
        if ($skip[$uuid]) {
        $this->logger?->info('Skipped importing @entity_type @uuid because: %reason', [
        '@entity_type' => $entity_type_id,
        '@uuid' => $uuid,
        '%reason' => $skip[$uuid],
        ]);
        }
        continue;
        }
        $entity_type = $this->entityTypeManager->getDefinition($entity_type_id);
        /** @var \Drupal\Core\Entity\EntityTypeInterface $entity_type */
        if (!$entity_type->entityClassImplements(ContentEntityInterface::class)) {
        ......
        <?php
        declare(strict_types=1);
        namespace Drupal\Core\DefaultContent;
        use Symfony\Contracts\EventDispatcher\Event;
        /**
        * Event dispatched before default content is imported.
        *
        * Subscribers to this event should avoid modifying content, because it is
        * probably about to change again. This event is best used for tasks like
        * notifications, logging, or updating a value in state. It can also be used
        * to skip importing certain entities, identified by their UUID.
        */
        final class PreImportEvent extends Event {
        /**
        * Entity UUIDs that should not be imported.
        *
        * @var string[]
        */
        private array $skip = [];
        /**
        * Constructs a PreImportEvent object.
        *
        * @param \Drupal\Core\DefaultContent\Finder $finder
        * The content finder, which has information on the entities to create
        * in the necessary dependency order.
        * @param \Drupal\Core\DefaultContent\Existing $existing
        * What the importer will do when importing an entity that already exists.
        */
        public function __construct(
        public readonly Finder $finder,
        public readonly Existing $existing,
        ) {}
        /**
        * Adds an entity UUID to the skip list.
        *
        * @param string $uuid
        * The UUID of an entity that should not be imported.
        * @param string|\Stringable|null $reason
        * (optional) A reason why the entity is being skipped. Defaults to NULL.
        *
        * @throws \InvalidArgumentException
        * If the given UUID is not one of the ones being imported.
        */
        public function skip(string $uuid, string|\Stringable|null $reason = NULL): void {
        if (array_key_exists($uuid, $this->finder->data)) {
        $this->skip[$uuid] = $reason;
        }
        else {
        throw new \InvalidArgumentException("Content entity '$uuid' cannot be skipped, because it is not one of the entities being imported.");
        }
        }
        /**
        * Returns the list of entity UUIDs that should not be imported.
        *
        * @return string|\Stringable|null[]
        * An array whose keys are the UUIDs of the entities that should not be
        * imported, and the values are either a short explanation of why that
        * entity was skipped, or NULL if no explanation was given.
        */
        public function getSkipList(): array {
        return $this->skip;
        }
        }
        ......@@ -8,6 +8,7 @@
        use Drupal\block_content\BlockContentInterface;
        use Drupal\block_content\Entity\BlockContentType;
        use Drupal\Component\Serialization\Yaml;
        use Drupal\Core\DefaultContent\PreImportEvent;
        use Drupal\Core\DefaultContent\Existing;
        use Drupal\Core\DefaultContent\Finder;
        use Drupal\Core\DefaultContent\Importer;
        ......@@ -33,6 +34,7 @@
        use Drupal\Tests\media\Traits\MediaTypeCreationTrait;
        use Drupal\Tests\taxonomy\Traits\TaxonomyTestTrait;
        use Psr\Log\LogLevel;
        use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
        /**
        * @covers \Drupal\Core\DefaultContent\Importer
        ......@@ -277,7 +279,50 @@ private function assertContentWasImported(): void {
        $this->assertInstanceOf(Section::class, $section);
        $this->assertCount(2, $section->getComponents());
        $this->assertSame('system_powered_by_block', $section->getComponent('03b45f14-cf74-469a-8398-edf3383ce7fa')->getPluginId());
        }
        /**
        * Tests that the pre-import event allows skipping certain entities.
        */
        public function testPreImportEvent(): void {
        $invalid_uuid_detected = FALSE;
        $listener = function (PreImportEvent $event) use (&$invalid_uuid_detected): void {
        $event->skip('3434bd5a-d2cd-4f26-bf79-a7f6b951a21b', 'Decided not to!');
        try {
        $event->skip('not-a-thing');
        }
        catch (\InvalidArgumentException) {
        $invalid_uuid_detected = TRUE;
        }
        };
        \Drupal::service(EventDispatcherInterface::class)
        ->addListener(PreImportEvent::class, $listener);
        $finder = new Finder($this->contentDir);
        $this->assertSame('menu_link_content', $finder->data['3434bd5a-d2cd-4f26-bf79-a7f6b951a21b']['_meta']['entity_type']);
        /** @var \Drupal\Core\DefaultContent\Importer $importer */
        $importer = \Drupal::service(Importer::class);
        $logger = new TestLogger();
        $importer->setLogger($logger);
        $importer->importContent($finder, Existing::Error);
        // The entity we skipped should not be here, and the reason why should have
        // been logged.
        $menu_link = \Drupal::service(EntityRepositoryInterface::class)
        ->loadEntityByUuid('menu_link_content', '3434bd5a-d2cd-4f26-bf79-a7f6b951a21b');
        $this->assertNull($menu_link);
        $this->assertTrue($logger->hasInfo([
        'message' => 'Skipped importing @entity_type @uuid because: %reason',
        'context' => [
        '@entity_type' => 'menu_link_content',
        '@uuid' => '3434bd5a-d2cd-4f26-bf79-a7f6b951a21b',
        '%reason' => 'Decided not to!',
        ],
        ]));
        // We should have caught an exception for trying to skip an invalid UUID.
        $this->assertTrue($invalid_uuid_detected);
        }
        }
        0% Loading or .
        You are about to add 0 people to the discussion. Proceed with caution.
        Please register or to comment