From 08096932199eb48884f1cae32f9e6f7f776e9c63 Mon Sep 17 00:00:00 2001 From: Matroskeen <matroskeen@3426249.no-reply.drupal.org> Date: Fri, 15 Apr 2022 13:30:28 +0000 Subject: [PATCH] Issue #3225457 by RichardGaunt: Add additional functionality to `dom_remove`... --- src/Plugin/migrate/process/DomRemove.php | 51 +++++++++++++++++++++--- tests/src/Unit/process/DomRemoveTest.php | 30 ++++++++++++++ 2 files changed, 76 insertions(+), 5 deletions(-) diff --git a/src/Plugin/migrate/process/DomRemove.php b/src/Plugin/migrate/process/DomRemove.php index 42085998..11a61058 100644 --- a/src/Plugin/migrate/process/DomRemove.php +++ b/src/Plugin/migrate/process/DomRemove.php @@ -8,13 +8,17 @@ use Drupal\migrate\MigrateExecutableInterface; use Drupal\migrate\Row; /** - * 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: @@ -33,7 +37,26 @@ use Drupal\migrate\Row; * @endcode * * 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. + * (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" @@ -41,6 +64,17 @@ use Drupal\migrate\Row; */ 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} */ @@ -56,7 +90,14 @@ class DomRemove extends DomProcessBase { $walking_dead[] = $node; } foreach ($walking_dead as $node) { - $node->parentNode->removeChild($node); + switch ($this->configuration['mode']) { + case 'attribute': + $node->removeAttribute($this->configuration['attribute']); + break; + case 'element': + $node->parentNode->removeChild($node); + break; + } } return $this->document; diff --git a/tests/src/Unit/process/DomRemoveTest.php b/tests/src/Unit/process/DomRemoveTest.php index 94b47338..46ce2c7d 100644 --- a/tests/src/Unit/process/DomRemoveTest.php +++ b/tests/src/Unit/process/DomRemoveTest.php @@ -34,6 +34,7 @@ final 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, @@ -78,9 +79,38 @@ final 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', [])); + } + } -- GitLab