Commit 96473925 authored by Nia Kathoni's avatar Nia Kathoni Committed by Youri van Koppen
Browse files

Issue #2926744 by nikathone, mikran, MegaChriz, bibo, darvanen, danharper,...

Issue #2926744 by nikathone, mikran, MegaChriz, bibo, darvanen, danharper, joshua.boltz: Allow revisionable entities to be saved as new revisions.
parent 01a79a31
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -53,7 +53,6 @@ feeds.feed_type.*:
          unique:
            type: ignore


action.configuration.feeds_feed_delete_action:
  type: action_configuration_default
  label: 'Delete feeds configuration'
@@ -188,6 +187,8 @@ feeds.processor.entity:
      type: boolean
    authorize:
      type: boolean
    revision:
      type: boolean
    expire:
      type: integer
    owner_feed_author:
+7 −0
Original line number Diff line number Diff line
@@ -234,6 +234,12 @@ abstract class EntityProcessorBase extends ProcessorBase implements EntityProces
      $feeds_item = $entity->get('feeds_item')->getItemByFeed($feed, TRUE);
      $feeds_item->hash = $hash;

      // Set new revision if needed.
      if ($this->configuration['revision']) {
        $entity->setNewRevision(TRUE);
        $entity->setRevisionCreationTime($this->dateTime->getRequestTime());
      }

      // Set field values.
      $this->map($feed, $entity, $item);

@@ -748,6 +754,7 @@ abstract class EntityProcessorBase extends ProcessorBase implements EntityProces
      'skip_hash_check' => FALSE,
      'values' => [],
      'authorize' => $this->entityType->entityClassImplements('Drupal\user\EntityOwnerInterface'),
      'revision' => FALSE,
      'expire' => static::EXPIRE_NEVER,
      'owner_id' => 0,
      'owner_feed_author' => 0,
+10 −0
Original line number Diff line number Diff line
@@ -222,6 +222,16 @@ class DefaultEntityProcessorForm extends ExternalPluginFormBase implements Conta
      ];
    }

    if ($entity_type->entityClassImplements('\Drupal\Core\Entity\RevisionableInterface')) {
      $form['advanced']['revision'] = [
        '#type' => 'checkbox',
        '#title' => $this->t('New revision'),
        '#description' => $this->t('Save as new revision.'),
        '#default_value' => $this->plugin->getConfiguration('revision'),
        '#parents' => ['processor_configuration', 'revision'],
      ];
    }

    $form['advanced']['skip_hash_check'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Force update'),
+206 −0
Original line number Diff line number Diff line
<?php

namespace Drupal\Tests\feeds\Kernel;

use Drupal\feeds\Plugin\Type\Processor\ProcessorInterface;
use Drupal\node\Entity\Node;
use Drupal\node\Entity\NodeType;

/**
 * Tests the feature of save a new revision.
 *
 * @group feeds
 */
class RevisionableEntityTest extends FeedsKernelTestBase {

  /**
   * {@inheritdoc}
   */
  protected function setUp() {
    parent::setUp();
    $this->setUpBodyField();
  }

  /**
   * {@inheritdoc}
   */
  protected function setUpNodeType() {
    // Create a content type.
    $this->nodeType = NodeType::create([
      'type' => 'article',
      'name' => 'Article',
      // Ensure that this node type is revisionable.
      'new_revision' => TRUE,
    ]);
    $this->nodeType->save();
  }

  /**
   * Tests the revision toggle configuration.
   *
   * @dataProvider provideToggleRevision
   */
  public function testRevisionToggle($is_enabled) {
    $feed_type = $this->createFeedType([
      'fetcher' => 'directory',
      'fetcher_configuration' => [
        'allowed_extensions' => 'csv',
      ],
      'parser' => 'csv',
      'processor_configuration' => [
        'update_existing' => ProcessorInterface::UPDATE_EXISTING,
        'authorize' => FALSE,
        // Using the data provider, enable or disable the revision accordingly.
        'revision' => $is_enabled,
        'values' => [
          'type' => 'article',
        ],
      ],
      'custom_sources' => [
        'title' => [
          'label' => 'title',
          'value' => 'title',
          'machine_name' => 'title',
        ],
        'body' => [
          'label' => 'body',
          'value' => 'body',
          'machine_name' => 'body',
        ],
      ],
      'mappings' => [
        [
          'target' => 'title',
          'map' => ['value' => 'title'],
          'unique' => ['value' => TRUE],
          'settings' => [
            'language' => NULL,
          ],
        ],
        [
          'target' => 'body',
          'map' => ['value' => 'body', 'summary' => ''],
          'settings' => ['format' => 'plain_text'],
        ],
      ],
    ]);

    // Import first feed to create the first revision.
    $feed = $this->createFeed($feed_type->id(), [
      'source' => $this->resourcesPath() . '/csv/content.csv',
    ]);
    $feed->import();

    $node = Node::load(1);
    $first_revision_id = $node->getRevisionId();

    // Now import updated feed to trigger a second revision to be created.
    $feed->setSource($this->resourcesPath() . '/csv/content_updated.csv');
    $feed->save();
    $feed->import();

    $node = Node::load(1);
    $second_revision_id = $node->getRevisionId();

    if ($is_enabled) {
      // When revision is enabled the first revision should not be the same as
      // the second one.
      $this->assertNotSame($first_revision_id, $second_revision_id);
    }
    else {
      // When revision is disabled the first revision should be the same as
      // second one.
      $this->assertSame($first_revision_id, $second_revision_id);
    }
  }

  /**
   * Data provider for ::testRevisionToggle().
   */
  public function provideToggleRevision() {
    return [
      'enable revision' => [TRUE],
      'disable revision' => [FALSE],
    ];
  }

  /**
   * Tests importing new revisions with mapping to revision fields.
   */
  public function testWithMappingToRevisionFields() {
    // Create a user with ID 42.
    $this->createUser([
      'uid' => 42,
    ]);

    // Create a feed type, map to body field. Set it to update existing items
    // and enable revision setting.
    $feed_type = $this->createFeedTypeForCsv([
      'guid' => 'guid',
      'title' => 'title',
      'created' => 'created',
      'alpha' => 'alpha',
      'beta' => 'beta',
      'body' => 'body',
    ], [
      'processor_configuration' => [
        'update_existing' => ProcessorInterface::UPDATE_EXISTING,
        'authorize' => FALSE,
        'revision' => TRUE,
        'values' => [
          'type' => 'article',
        ],
      ],
      'mappings' => array_merge($this->getDefaultMappings(), [
        [
          'target' => 'body',
          'map' => ['value' => 'body'],
          'settings' => ['format' => 'plain_text'],
        ],
      ]),
    ]);

    // Import first feed to create the first revision.
    $feed = $this->createFeed($feed_type->id(), [
      'source' => $this->resourcesPath() . '/csv/content.csv',
    ]);
    $feed->import();

    // Now map to certain fields related to the revision.
    $feed_type->addMapping([
      'target' => 'revision_timestamp',
      'map' => ['value' => 'created'],
    ])->addMapping([
      'target' => 'revision_log',
      'map' => ['value' => 'alpha'],
    ])->addMapping([
      'target' => 'revision_uid',
      'map' => ['target_id' => 'beta'],
      'settings' => [
        'reference_by' => 'uid',
        'autocreate' => FALSE,
      ],
    ])->save();

    // Reload feed and import again. Mapping has changed, so an update should
    // happen.
    $feed = $this->reloadEntity($feed);
    $feed->import();

    // Assert values of revision 2.
    $node = Node::load(1);
    $this->assertEquals(3, $node->getRevisionId());
    $this->assertEquals(1251936720, $node->revision_timestamp->value);
    $this->assertEquals('Lorem', $node->revision_log->value);
    $this->assertEquals(42, $node->revision_uid->target_id);

    // And assert values of revision 1.
    $revision1 = $this->container->get('entity_type.manager')
      ->getStorage('node')
      ->loadRevision(1);
    $this->assertNotEquals(1251936720, $revision1->revision_timestamp->value);
    $this->assertEquals('', $revision1->revision_log->value);
    $this->assertEquals(0, $revision1->revision_uid->target_id);
  }

}