diff modules/contrib/migrate_plus/src/Plugin/migrate/process/DomStrReplace.php @ 5:12f9dff5fda9 tip

Update to Drupal core 8.7.1
author Chris Cannam
date Thu, 09 May 2019 15:34:47 +0100
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/contrib/migrate_plus/src/Plugin/migrate/process/DomStrReplace.php	Thu May 09 15:34:47 2019 +0100
@@ -0,0 +1,207 @@
+<?php
+
+namespace Drupal\migrate_plus\Plugin\migrate\process;
+
+use Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException;
+use Drupal\migrate\MigrateExecutableInterface;
+use Drupal\migrate\Row;
+
+/**
+ * String replacements on a source dom.
+ *
+ * Analogous to str_replace process plugin, but based on a \DOMDocument instead
+ * of a string.
+ * Meant to be used after dom process plugin.
+ *
+ * Available configuration keys:
+ * - mode: What to modify. Possible values:
+ *   - attribute: One element attribute.
+ * - expression: XPath query expression that will produce the \DOMNodeList to
+ *   walk.
+ * - attribute_options: A map of options related to the attribute mode. Required
+ *   when mode is attribute. The keys can be:
+ *   - name: Name of the attribute to match and modify.
+ * - search: pattern to match.
+ * - replace: value to replace the searched pattern with.
+ * - regex: Use regular expression replacement.
+ * - case_insensitive: Case insensitive search. Only valid when regex is false.
+ *
+ * Examples:
+ *
+ * @code
+ * process:
+ *   'body/value':
+ *     -
+ *       plugin: dom
+ *       method: import
+ *       source: 'body/0/value'
+ *     -
+ *       plugin: dom_str_replace
+ *       mode: attribute
+ *       expression: '//a'
+ *       attribute_options:
+ *         name: href
+ *       search: 'foo'
+ *       replace: 'bar'
+ *     -
+ *       plugin: dom_str_replace
+ *       mode: attribute
+ *       expression: '//a'
+ *       attribute_options:
+ *         name: href
+ *       regex: true
+ *       search: '/foo/'
+ *       replace: 'bar'
+ *     -
+ *       plugin: dom
+ *       method: export
+ * @endcode
+ *
+ * @MigrateProcessPlugin(
+ *   id = "dom_str_replace"
+ * )
+ */
+class DomStrReplace extends DomProcessBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function __construct(array $configuration, $plugin_id, $plugin_definition) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition);
+    $this->configuration += [
+      'case_insensitive' => FALSE,
+      'regex' => FALSE,
+    ];
+    $options_validation = [
+      'expression' => NULL,
+      'mode' => ['attribute'],
+      // @todo Move out once another mode is supported.
+      // @see https://www.drupal.org/project/migrate_plus/issues/3042833
+      'attribute_options' => NULL,
+      'search' => NULL,
+      'replace' => NULL,
+    ];
+    foreach ($options_validation as $option_name => $possible_values) {
+      if (empty($this->configuration[$option_name])) {
+        throw new InvalidPluginDefinitionException(
+          $this->getPluginId(),
+          "Configuration option '$option_name' is required."
+        );
+      }
+      if (!is_null($possible_values) && !in_array($this->configuration[$option_name], $possible_values)) {
+        throw new InvalidPluginDefinitionException(
+          $this->getPluginId(),
+          sprintf(
+            'Configuration option "%s" only accepts the following values: %s.',
+            $option_name,
+            implode(', ', $possible_values)
+          )
+        );
+      }
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
+    $this->init($value, $destination_property);
+
+    foreach ($this->xpath->query($this->configuration['expression']) as $html_node) {
+      $subject = $this->getSubject($html_node);
+      if (empty($subject)) {
+        // Could not find subject, skip processing.
+        continue;
+      }
+      $search = $this->getSearch();
+      $replace = $this->getReplace();
+      $this->doReplace($html_node, $search, $replace, $subject);
+    }
+
+    return $this->document;
+  }
+
+  /**
+   * Retrieves the right subject string.
+   *
+   * @param \DOMElement $node
+   *   The current element from iteration.
+   *
+   * @return string
+   *   The string to use a subject on search.
+   */
+  protected function getSubject(\DOMElement $node) {
+    switch ($this->configuration['mode']) {
+      case 'attribute':
+        return $node->getAttribute($this->configuration['attribute_options']['name']);
+    }
+  }
+
+  /**
+   * Retrieves the right search string based on configuration.
+   *
+   * @return string
+   *   The value to be searched.
+   */
+  protected function getSearch() {
+    switch ($this->configuration['mode']) {
+      case 'attribute':
+        return $this->configuration['search'];
+    }
+  }
+
+  /**
+   * Retrieves the right replace string based on configuration.
+   *
+   * @return string
+   *   The value to use for replacement.
+   */
+  protected function getReplace() {
+    switch ($this->configuration['mode']) {
+      case 'attribute':
+        return $this->configuration['replace'];
+    }
+  }
+
+  /**
+   * Retrieves the right replace string based on configuration.
+   *
+   * @param \DOMElement $html_node
+   *   The current element from iteration.
+   * @param string $search
+   *   The search string or pattern.
+   * @param string $replace
+   *   The replacement string.
+   * @param string $subject
+   *   The string on which to perform the substitution.
+   */
+  protected function doReplace(\DOMElement $html_node, $search, $replace, $subject) {
+    if ($this->configuration['regex']) {
+      $function = 'preg_replace';
+    }
+    elseif ($this->configuration['case_insensitive']) {
+      $function = 'str_ireplace';
+    }
+    else {
+      $function = "str_replace";
+    }
+    $new_subject = $function($search, $replace, $subject);
+    $this->postReplace($html_node, $new_subject);
+  }
+
+  /**
+   * Performs post-replace actions.
+   *
+   * @param \DOMElement $html_node
+   *   The current element from iteration.
+   * @param string $new_subject
+   *   The new value to use.
+   */
+  protected function postReplace(\DOMElement $html_node, $new_subject) {
+    switch ($this->configuration['mode']) {
+      case 'attribute':
+        $html_node->setAttribute($this->configuration['attribute_options']['name'], $new_subject);
+    }
+  }
+
+}