Skip to content
Snippets Groups Projects
Unverified Commit c813f52a 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

(cherry picked from commit 51ae0389)
parent 379ebd46
No related branches found
No related tags found
21 merge requests!12227Issue #3181946 by jonmcl, mglaman,!12079Issue #3523476 by matthiasm11: Add empty check on operator,!12024Fix: DocBlock comment for return value of Drupal\Core\Database\Connection::transactionManager(),!11974Draft: Issue #3495165 by catch, joeyroth, berdir, texas-bronius: Better warning...,!11934Issue #3520997: DefaultLazyPluginCollection unnecessarily instantiates plugins when sorting collection,!11887Issue #3520065: The migrate Row class API is incomplete,!11636Draft: Issue #3515643 by macsim: fieldNameExists method is inconsistent,!11515Issue #3480419 by mondrake, smustgrave, catch: Method...,!11380Issue #3490698 by catch, spokje: Bump MINIMUM_STABILITY back to 'stable' when...,!11281Use Drupal Core Leadership terminology in MAINTAINERS.txt,!11239Issue #3507548: Allow workspace changes listing to show all items, without a pager,!11238Fix issue #3051797,!11213Issue #3506743 by tomislav.matokovic: Increasing the color contrast for the navigation block title against the background of the navigation sidebar to at least 4.5:1,!11147Draft: Try to avoid manually setting required cache contexts,!11108Issue #3490298 by nicxvan: Profiles can be missed in OOP hooks,!11093Drupal on MongoDB 11.1.x,!11017Issue #3502540: Add date filter for moderated content.,!11009Issue #3486972 migrate feed icon,!10999Cleaning up Taxonomy hooks and updating baseline.,!10977Issue #3501457: Fix path used in a A11y Test Admin,!10881Issue #3489329 by mfb, casey: symfony/http-foundation commit 32310ff breaks PathValidator
Pipeline #377004 passed
Pipeline: drupal

#377006

    ......@@ -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