Mercurial > hg > isophonics-drupal-site
comparison modules/contrib/migrate_tools/src/MigrateExecutable.php @ 0:4c8ae668cc8c
Initial import (non-working)
author | Chris Cannam |
---|---|
date | Wed, 29 Nov 2017 16:09:58 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4c8ae668cc8c |
---|---|
1 <?php | |
2 | |
3 /** | |
4 * @file | |
5 * Contains \Drupal\migrate_tools\MigrateExecutable. | |
6 */ | |
7 | |
8 namespace Drupal\migrate_tools; | |
9 | |
10 use Drupal\migrate\Event\MigratePreRowSaveEvent; | |
11 use Drupal\migrate\Event\MigrateRollbackEvent; | |
12 use Drupal\migrate\Event\MigrateRowDeleteEvent; | |
13 use Drupal\migrate\MigrateExecutable as MigrateExecutableBase; | |
14 use Drupal\migrate\MigrateMessageInterface; | |
15 use Drupal\migrate\Plugin\MigrationInterface; | |
16 use Drupal\migrate\MigrateSkipRowException; | |
17 use Drupal\migrate\Plugin\MigrateIdMapInterface; | |
18 use Drupal\migrate\Event\MigrateEvents; | |
19 use Drupal\migrate_plus\Event\MigrateEvents as MigratePlusEvents; | |
20 use Drupal\migrate\Event\MigrateMapSaveEvent; | |
21 use Drupal\migrate\Event\MigrateMapDeleteEvent; | |
22 use Drupal\migrate\Event\MigrateImportEvent; | |
23 use Drupal\migrate_plus\Event\MigratePrepareRowEvent; | |
24 | |
25 class MigrateExecutable extends MigrateExecutableBase { | |
26 | |
27 /** | |
28 * Counters of map statuses. | |
29 * | |
30 * @var array | |
31 * Set of counters, keyed by MigrateIdMapInterface::STATUS_* constant. | |
32 */ | |
33 protected $saveCounters = array( | |
34 MigrateIdMapInterface::STATUS_FAILED => 0, | |
35 MigrateIdMapInterface::STATUS_IGNORED => 0, | |
36 MigrateIdMapInterface::STATUS_IMPORTED => 0, | |
37 MigrateIdMapInterface::STATUS_NEEDS_UPDATE => 0, | |
38 ); | |
39 | |
40 /** | |
41 * Counter of map deletions. | |
42 * | |
43 * @var int | |
44 */ | |
45 protected $deleteCounter = 0; | |
46 | |
47 /** | |
48 * Maximum number of items to process in this migration. 0 indicates no limit | |
49 * is to be applied. | |
50 * | |
51 * @var int | |
52 */ | |
53 protected $itemLimit = 0; | |
54 | |
55 /** | |
56 * Frequency (in items) at which progress messages should be emitted. | |
57 * | |
58 * @var int | |
59 */ | |
60 protected $feedback = 0; | |
61 | |
62 /** | |
63 * List of specific source IDs to import. | |
64 * | |
65 * @var array | |
66 */ | |
67 protected $idlist = []; | |
68 | |
69 /** | |
70 * Count of number of items processed so far in this migration. | |
71 * @var int | |
72 */ | |
73 protected $counter = 0; | |
74 | |
75 /** | |
76 * Whether the destination item exists before saving. | |
77 * | |
78 * @var bool | |
79 */ | |
80 protected $preExistingItem = FALSE; | |
81 | |
82 /** | |
83 * List of event listeners we have registered. | |
84 * | |
85 * @var array | |
86 */ | |
87 protected $listeners = []; | |
88 | |
89 /** | |
90 * {@inheritdoc} | |
91 */ | |
92 public function __construct(MigrationInterface $migration, MigrateMessageInterface $message, array $options = []) { | |
93 parent::__construct($migration, $message); | |
94 if (isset($options['limit'])) { | |
95 $this->itemLimit = $options['limit']; | |
96 } | |
97 if (isset($options['feedback'])) { | |
98 $this->feedback = $options['feedback']; | |
99 } | |
100 if (isset($options['idlist'])) { | |
101 $this->idlist = explode(',', $options['idlist']); | |
102 } | |
103 | |
104 $this->listeners[MigrateEvents::MAP_SAVE] = [$this, 'onMapSave']; | |
105 $this->listeners[MigrateEvents::MAP_DELETE] = [$this, 'onMapDelete']; | |
106 $this->listeners[MigrateEvents::POST_IMPORT] = [$this, 'onPostImport']; | |
107 $this->listeners[MigrateEvents::POST_ROLLBACK] = [$this, 'onPostRollback']; | |
108 $this->listeners[MigrateEvents::PRE_ROW_SAVE] = [$this, 'onPreRowSave']; | |
109 $this->listeners[MigrateEvents::POST_ROW_DELETE] = [$this, 'onPostRowDelete']; | |
110 $this->listeners[MigratePlusEvents::PREPARE_ROW] = [$this, 'onPrepareRow']; | |
111 foreach ($this->listeners as $event => $listener) { | |
112 \Drupal::service('event_dispatcher')->addListener($event, $listener); | |
113 } | |
114 } | |
115 | |
116 /** | |
117 * Count up any map save events. | |
118 * | |
119 * @param \Drupal\migrate\Event\MigrateMapSaveEvent $event | |
120 * The map event. | |
121 */ | |
122 public function onMapSave(MigrateMapSaveEvent $event) { | |
123 // Only count saves for this migration. | |
124 if ($event->getMap()->getQualifiedMapTableName() == $this->migration->getIdMap()->getQualifiedMapTableName()) { | |
125 $fields = $event->getFields(); | |
126 // Distinguish between creation and update. | |
127 if ($fields['source_row_status'] == MigrateIdMapInterface::STATUS_IMPORTED && | |
128 $this->preExistingItem | |
129 ) { | |
130 $this->saveCounters[MigrateIdMapInterface::STATUS_NEEDS_UPDATE]++; | |
131 } | |
132 else { | |
133 $this->saveCounters[$fields['source_row_status']]++; | |
134 } | |
135 } | |
136 } | |
137 | |
138 /** | |
139 * Count up any rollback events. | |
140 * | |
141 * @param \Drupal\migrate\Event\MigrateMapDeleteEvent $event | |
142 * The map event. | |
143 */ | |
144 public function onMapDelete(MigrateMapDeleteEvent $event) { | |
145 $this->deleteCounter++; | |
146 } | |
147 | |
148 /** | |
149 * Return the number of items created. | |
150 * | |
151 * @return int | |
152 */ | |
153 public function getCreatedCount() { | |
154 return $this->saveCounters[MigrateIdMapInterface::STATUS_IMPORTED]; | |
155 } | |
156 | |
157 /** | |
158 * Return the number of items updated. | |
159 * | |
160 * @return int | |
161 */ | |
162 public function getUpdatedCount() { | |
163 return $this->saveCounters[MigrateIdMapInterface::STATUS_NEEDS_UPDATE]; | |
164 } | |
165 | |
166 /** | |
167 * Return the number of items ignored. | |
168 * | |
169 * @return int | |
170 */ | |
171 public function getIgnoredCount() { | |
172 return $this->saveCounters[MigrateIdMapInterface::STATUS_IGNORED]; | |
173 } | |
174 | |
175 /** | |
176 * Return the number of items that failed. | |
177 * | |
178 * @return int | |
179 */ | |
180 public function getFailedCount() { | |
181 return $this->saveCounters[MigrateIdMapInterface::STATUS_FAILED]; | |
182 } | |
183 | |
184 /** | |
185 * Return the total number of items processed. Note that STATUS_NEEDS_UPDATE | |
186 * is not counted, since this is typically set on stubs created as side | |
187 * effects, not on the primary item being imported. | |
188 * | |
189 * @return int | |
190 */ | |
191 public function getProcessedCount() { | |
192 return $this->saveCounters[MigrateIdMapInterface::STATUS_IMPORTED] + | |
193 $this->saveCounters[MigrateIdMapInterface::STATUS_NEEDS_UPDATE] + | |
194 $this->saveCounters[MigrateIdMapInterface::STATUS_IGNORED] + | |
195 $this->saveCounters[MigrateIdMapInterface::STATUS_FAILED]; | |
196 } | |
197 | |
198 /** | |
199 * Return the number of items rolled back. | |
200 * | |
201 * @return int | |
202 */ | |
203 public function getRollbackCount() { | |
204 return $this->deleteCounter; | |
205 } | |
206 | |
207 /** | |
208 * Reset all the per-status counters to 0. | |
209 */ | |
210 protected function resetCounters() { | |
211 foreach ($this->saveCounters as $status => $count) { | |
212 $this->saveCounters[$status] = 0; | |
213 } | |
214 $this->deleteCounter = 0; | |
215 } | |
216 | |
217 /** | |
218 * React to migration completion. | |
219 * | |
220 * @param \Drupal\migrate\Event\MigrateImportEvent $event | |
221 * The map event. | |
222 */ | |
223 public function onPostImport(MigrateImportEvent $event) { | |
224 $migrate_last_imported_store = \Drupal::keyValue('migrate_last_imported'); | |
225 $migrate_last_imported_store->set($event->getMigration()->id(), round(microtime(TRUE) * 1000)); | |
226 $this->progressMessage(); | |
227 $this->removeListeners(); | |
228 } | |
229 | |
230 /** | |
231 * Clean up all our event listeners. | |
232 */ | |
233 protected function removeListeners() { | |
234 foreach ($this->listeners as $event => $listener) { | |
235 \Drupal::service('event_dispatcher')->removeListener($event, $listener); | |
236 } | |
237 } | |
238 | |
239 /** | |
240 * Emit information on what we've done since the last feedback (or the | |
241 * beginning of this migration). | |
242 * | |
243 * @param bool $done | |
244 */ | |
245 protected function progressMessage($done = TRUE) { | |
246 $processed = $this->getProcessedCount(); | |
247 if ($done) { | |
248 $singular_message = "Processed 1 item (@created created, @updated updated, @failures failed, @ignored ignored) - done with '@name'"; | |
249 $plural_message = "Processed @numitems items (@created created, @updated updated, @failures failed, @ignored ignored) - done with '@name'"; | |
250 } | |
251 else { | |
252 $singular_message = "Processed 1 item (@created created, @updated updated, @failures failed, @ignored ignored) - continuing with '@name'"; | |
253 $plural_message = "Processed @numitems items (@created created, @updated updated, @failures failed, @ignored ignored) - continuing with '@name'"; | |
254 } | |
255 $this->message->display(\Drupal::translation()->formatPlural($processed, | |
256 $singular_message, $plural_message, | |
257 array('@numitems' => $processed, | |
258 '@created' => $this->getCreatedCount(), | |
259 '@updated' => $this->getUpdatedCount(), | |
260 '@failures' => $this->getFailedCount(), | |
261 '@ignored' => $this->getIgnoredCount(), | |
262 '@name' => $this->migration->id()))); | |
263 } | |
264 | |
265 /** | |
266 * React to rollback completion. | |
267 * | |
268 * @param \Drupal\migrate\Event\MigrateRollbackEvent $event | |
269 * The map event. | |
270 */ | |
271 public function onPostRollback(MigrateRollbackEvent $event) { | |
272 $this->rollbackMessage(); | |
273 $this->removeListeners(); | |
274 } | |
275 | |
276 /** | |
277 * Emit information on what we've done since the last feedback (or the | |
278 * beginning of this migration). | |
279 * | |
280 * @param bool $done | |
281 */ | |
282 protected function rollbackMessage($done = TRUE) { | |
283 $rolled_back = $this->getRollbackCount(); | |
284 if ($done) { | |
285 $singular_message = "Rolled back 1 item - done with '@name'"; | |
286 $plural_message = "Rolled back @numitems items - done with '@name'"; | |
287 } | |
288 else { | |
289 $singular_message = "Rolled back 1 item - continuing with '@name'"; | |
290 $plural_message = "Rolled back @numitems items - continuing with '@name'"; | |
291 } | |
292 $this->message->display(\Drupal::translation()->formatPlural($rolled_back, | |
293 $singular_message, $plural_message, | |
294 array('@numitems' => $rolled_back, | |
295 '@name' => $this->migration->id()))); | |
296 } | |
297 | |
298 /** | |
299 * React to an item about to be imported. | |
300 * | |
301 * @param \Drupal\migrate\Event\MigratePreRowSaveEvent $event | |
302 * The pre-save event. | |
303 */ | |
304 public function onPreRowSave(MigratePreRowSaveEvent $event) { | |
305 $id_map = $event->getRow()->getIdMap(); | |
306 if (!empty($id_map['destid1'])) { | |
307 $this->preExistingItem = TRUE; | |
308 } | |
309 else { | |
310 $this->preExistingItem = FALSE; | |
311 } | |
312 } | |
313 | |
314 /** | |
315 * React to item rollback. | |
316 * | |
317 * @param \Drupal\migrate\Event\MigrateRowDeleteEvent $event | |
318 * The post-save event. | |
319 */ | |
320 public function onPostRowDelete(MigrateRowDeleteEvent $event) { | |
321 if ($this->feedback && ($this->deleteCounter) && $this->deleteCounter % $this->feedback == 0) { | |
322 $this->rollbackMessage(FALSE); | |
323 $this->resetCounters(); | |
324 } | |
325 } | |
326 | |
327 /** | |
328 * React to a new row. | |
329 * | |
330 * @param \Drupal\migrate_plus\Event\MigratePrepareRowEvent $event | |
331 * The prepare-row event. | |
332 * | |
333 * @throws \Drupal\migrate\MigrateSkipRowException | |
334 * | |
335 */ | |
336 public function onPrepareRow(MigratePrepareRowEvent $event) { | |
337 if ($this->idlist) { | |
338 $row = $event->getRow(); | |
339 $source_id = $row->getSourceIdValues(); | |
340 if (!in_array(reset($source_id), $this->idlist)) { | |
341 throw new MigrateSkipRowException(NULL, FALSE); | |
342 } | |
343 } | |
344 if ($this->feedback && ($this->counter) && $this->counter % $this->feedback == 0) { | |
345 $this->progressMessage(FALSE); | |
346 $this->resetCounters(); | |
347 } | |
348 $this->counter++; | |
349 if ($this->itemLimit && $this->counter >= $this->itemLimit) { | |
350 $event->getMigration()->interruptMigration(MigrationInterface::RESULT_COMPLETED); | |
351 } | |
352 | |
353 } | |
354 | |
355 } |