Commit c31704c6 authored by Ivan Doroshenko's avatar Ivan Doroshenko
Browse files

Issue #3225457 by RichardGaunt: Add additional functionality to `dom_remove`...

parent b7aaf9a3
Loading
Loading
Loading
Loading
+44 −4
Changes for src/Plugin/migrate/process/DomRemove.php: 44 added lines, 4 removed lines.
Original line number Diff line number Diff line
@@ -4,16 +4,19 @@ namespace Drupal\migrate_plus\Plugin\migrate\process;

use Drupal\migrate\MigrateExecutableInterface;
use Drupal\migrate\Row;
use Drupal\migrate_plus\Plugin\migrate\process\DomProcessBase;

/**
 * Remove nodes from a DOMDocument object.
 * Remove nodes / attributes of a node from a DOMDocument object.
 *
 * Configuration:
 * - selector: An XPath selector.
 * - limit: (optional) The maximum number of nodes to remove.
 * - limit: (optional) The maximum number of nodes / attributes to remove.
 * - mode: (optional) What to remove. Possible values:
 *   - element: An element (default option).
 *   - attribute: An element's attribute.
 * - attribute: An attribute name (required if mode is attribute)
 *
 * Usage:
 * Examples:
 *
 * @code
 * process:
@@ -34,12 +37,42 @@ use Drupal\migrate_plus\Plugin\migrate\process\DomProcessBase;
 * This example will remove the first two <img> elements from the source text
 * (if there are that many). Omit 'limit: 2' to remove all <img> elements.
 *
 * @code
 * process:
 *   bar:
 *     -
 *       plugin: dom
 *       method: import
 *       source: text_field
 *     -
 *       plugin: dom_remove
 *       mode: attribute
 *       selector: //*[@style]
 *       attribute: style
 *     -
 *       plugin: dom
 *       method: export
 * @endcode
 *
 * This example will remove "style" attributes from all tags.
 *
 * @MigrateProcessPlugin(
 *   id = "dom_remove"
 * )
 */
class DomRemove extends DomProcessBase {

  /**
   * {@inheritdoc}
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->configuration['mode'] = $this->configuration['mode'] ?? 'element';
    if ($this->configuration['mode'] === 'attribute' && !isset($this->configuration['attribute'])) {
      throw new \InvalidArgumentException('The "attribute" must be set if "mode" is set to "attribute".');
    }
  }

  /**
   * {@inheritdoc}
   */
@@ -55,7 +88,14 @@ class DomRemove extends DomProcessBase {
      $walking_dead[] = $node;
    }
    foreach ($walking_dead as $node) {
      switch ($this->configuration['mode']) {
        case 'attribute':
          $node->removeAttribute($this->configuration['attribute']);
          break;
        case 'element':
          $node->parentNode->removeChild($node);
          break;
      }
    }

    return $this->document;
+30 −0
Changes for tests/src/Unit/process/DomRemoveTest.php: 30 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ class DomRemoveTest extends MigrateProcessTestCase {
   */
  public function providerTestTransform(): array {
    $input_string = '<ul><li>Item 1</li><li>Item 2</li><li><ul><li>Item 3.1</li><li>Item 3.2</li></ul></li><li>Item 4</li><li>Item 5</li></ul>';
    $attribute_input_string = '<div style="font-size:15px;"><a class="btn-lg" href="#" style="padding: 10px;">Button</a><p class="lead-paragraph">Testing</p></div>';
    $cases = [
      'any li, no limit' => [
        $input_string,
@@ -76,9 +77,38 @@ class DomRemoveTest extends MigrateProcessTestCase {
        ['selector' => '//li[./ul]'],
        '<ul><li>Item 1</li><li>Item 2</li><li>Item 4</li><li>Item 5</li></ul>',
      ],
      'attribute, no limit' => [
        $attribute_input_string,
        ['selector' => '//*[@style]', 'mode' => 'attribute', 'attribute' => 'style'],
        '<div><a class="btn-lg" href="#">Button</a><p class="lead-paragraph">Testing</p></div>',
      ],
      'attribute, limit 1' => [
        $attribute_input_string,
        ['selector' => '//*[@style]', 'mode' => 'attribute', 'attribute' => 'style', 'limit' => 1],
        '<div><a class="btn-lg" href="#" style="padding: 10px;">Button</a><p class="lead-paragraph">Testing</p></div>',
      ],
      'attribute in specific tag' => [
        $attribute_input_string,
        ['selector' => '//p[@class]', 'mode' => 'attribute', 'attribute' => 'class'],
        '<div style="font-size:15px;"><a class="btn-lg" href="#" style="padding: 10px;">Button</a><p>Testing</p></div>',
      ],
      'attribute not found' => [
        $attribute_input_string,
        ['selector' => 'p[@class]', 'mode' => 'attribute', 'attribute' => 'data-test'],
        $attribute_input_string,
      ],
    ];

    return $cases;
  }

  /**
   * Tests running remove attribute without specifying an attribute to remove.
   */
  public function testMissingConfiguration(): void {
    $this->expectException(\InvalidArgumentException::class);
    $this->expectExceptionMessage('The "attribute" must be set if "mode" is set to "attribute".');
    (new DomRemove(['selector' => 'p', 'mode' => 'attribute'], 'dom_remove', []));
  }

}