comparison 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
comparison
equal deleted inserted replaced
4:a9cd425dd02b 5:12f9dff5fda9
1 <?php
2
3 namespace Drupal\migrate_plus\Plugin\migrate\process;
4
5 use Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException;
6 use Drupal\migrate\MigrateExecutableInterface;
7 use Drupal\migrate\Row;
8
9 /**
10 * String replacements on a source dom.
11 *
12 * Analogous to str_replace process plugin, but based on a \DOMDocument instead
13 * of a string.
14 * Meant to be used after dom process plugin.
15 *
16 * Available configuration keys:
17 * - mode: What to modify. Possible values:
18 * - attribute: One element attribute.
19 * - expression: XPath query expression that will produce the \DOMNodeList to
20 * walk.
21 * - attribute_options: A map of options related to the attribute mode. Required
22 * when mode is attribute. The keys can be:
23 * - name: Name of the attribute to match and modify.
24 * - search: pattern to match.
25 * - replace: value to replace the searched pattern with.
26 * - regex: Use regular expression replacement.
27 * - case_insensitive: Case insensitive search. Only valid when regex is false.
28 *
29 * Examples:
30 *
31 * @code
32 * process:
33 * 'body/value':
34 * -
35 * plugin: dom
36 * method: import
37 * source: 'body/0/value'
38 * -
39 * plugin: dom_str_replace
40 * mode: attribute
41 * expression: '//a'
42 * attribute_options:
43 * name: href
44 * search: 'foo'
45 * replace: 'bar'
46 * -
47 * plugin: dom_str_replace
48 * mode: attribute
49 * expression: '//a'
50 * attribute_options:
51 * name: href
52 * regex: true
53 * search: '/foo/'
54 * replace: 'bar'
55 * -
56 * plugin: dom
57 * method: export
58 * @endcode
59 *
60 * @MigrateProcessPlugin(
61 * id = "dom_str_replace"
62 * )
63 */
64 class DomStrReplace extends DomProcessBase {
65
66 /**
67 * {@inheritdoc}
68 */
69 public function __construct(array $configuration, $plugin_id, $plugin_definition) {
70 parent::__construct($configuration, $plugin_id, $plugin_definition);
71 $this->configuration += [
72 'case_insensitive' => FALSE,
73 'regex' => FALSE,
74 ];
75 $options_validation = [
76 'expression' => NULL,
77 'mode' => ['attribute'],
78 // @todo Move out once another mode is supported.
79 // @see https://www.drupal.org/project/migrate_plus/issues/3042833
80 'attribute_options' => NULL,
81 'search' => NULL,
82 'replace' => NULL,
83 ];
84 foreach ($options_validation as $option_name => $possible_values) {
85 if (empty($this->configuration[$option_name])) {
86 throw new InvalidPluginDefinitionException(
87 $this->getPluginId(),
88 "Configuration option '$option_name' is required."
89 );
90 }
91 if (!is_null($possible_values) && !in_array($this->configuration[$option_name], $possible_values)) {
92 throw new InvalidPluginDefinitionException(
93 $this->getPluginId(),
94 sprintf(
95 'Configuration option "%s" only accepts the following values: %s.',
96 $option_name,
97 implode(', ', $possible_values)
98 )
99 );
100 }
101 }
102 }
103
104 /**
105 * {@inheritdoc}
106 */
107 public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
108 $this->init($value, $destination_property);
109
110 foreach ($this->xpath->query($this->configuration['expression']) as $html_node) {
111 $subject = $this->getSubject($html_node);
112 if (empty($subject)) {
113 // Could not find subject, skip processing.
114 continue;
115 }
116 $search = $this->getSearch();
117 $replace = $this->getReplace();
118 $this->doReplace($html_node, $search, $replace, $subject);
119 }
120
121 return $this->document;
122 }
123
124 /**
125 * Retrieves the right subject string.
126 *
127 * @param \DOMElement $node
128 * The current element from iteration.
129 *
130 * @return string
131 * The string to use a subject on search.
132 */
133 protected function getSubject(\DOMElement $node) {
134 switch ($this->configuration['mode']) {
135 case 'attribute':
136 return $node->getAttribute($this->configuration['attribute_options']['name']);
137 }
138 }
139
140 /**
141 * Retrieves the right search string based on configuration.
142 *
143 * @return string
144 * The value to be searched.
145 */
146 protected function getSearch() {
147 switch ($this->configuration['mode']) {
148 case 'attribute':
149 return $this->configuration['search'];
150 }
151 }
152
153 /**
154 * Retrieves the right replace string based on configuration.
155 *
156 * @return string
157 * The value to use for replacement.
158 */
159 protected function getReplace() {
160 switch ($this->configuration['mode']) {
161 case 'attribute':
162 return $this->configuration['replace'];
163 }
164 }
165
166 /**
167 * Retrieves the right replace string based on configuration.
168 *
169 * @param \DOMElement $html_node
170 * The current element from iteration.
171 * @param string $search
172 * The search string or pattern.
173 * @param string $replace
174 * The replacement string.
175 * @param string $subject
176 * The string on which to perform the substitution.
177 */
178 protected function doReplace(\DOMElement $html_node, $search, $replace, $subject) {
179 if ($this->configuration['regex']) {
180 $function = 'preg_replace';
181 }
182 elseif ($this->configuration['case_insensitive']) {
183 $function = 'str_ireplace';
184 }
185 else {
186 $function = "str_replace";
187 }
188 $new_subject = $function($search, $replace, $subject);
189 $this->postReplace($html_node, $new_subject);
190 }
191
192 /**
193 * Performs post-replace actions.
194 *
195 * @param \DOMElement $html_node
196 * The current element from iteration.
197 * @param string $new_subject
198 * The new value to use.
199 */
200 protected function postReplace(\DOMElement $html_node, $new_subject) {
201 switch ($this->configuration['mode']) {
202 case 'attribute':
203 $html_node->setAttribute($this->configuration['attribute_options']['name'], $new_subject);
204 }
205 }
206
207 }