Completed
Pull Request — master (#498)
by
unknown
02:15
created

CalMigrationUpdate::getIdentifier()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
/**
4
 * CalMigrationUpdate.
5
 */
6
declare(strict_types=1);
7
8
namespace HDNET\Calendarize\Updates;
9
10
use HDNET\Autoloader\Annotation\SignalClass;
11
use HDNET\Autoloader\Annotation\SignalName;
12
use HDNET\Calendarize\Service\IndexerService;
13
use HDNET\Calendarize\Utility\HelperUtility;
14
use TYPO3\CMS\Core\Database\ConnectionPool;
15
use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
16
use TYPO3\CMS\Core\Utility\GeneralUtility;
17
use TYPO3\CMS\Install\Updates\DatabaseUpdatedPrerequisite;
18
19
/**
20
 * CalMigrationUpdate.
21
 *
22
 * If using the slots please use the m with func_get_args!
23
 * Example:
24
 * /**
25
 *  * @SignalClass("HDNET\Calendarize\Updates\CalMigrationUpdate")
26
 *  * @SignalName("getCalendarizeEventUid")
27
 *
28
 *  *@return array
29
 *  *
30
 * public function getCalendarizeEventUid()
31
 * {
32
 *    $args = func_get_args();
33
 *    list($table, $dbQueries, $call) = $args;
34
 *
35
 *    $variables = [
36
 *        'table'     => self::EVENT_TABLE,
37
 *        'dbQueries' => $dbQueries
38
 *    ];
39
 *
40
 *    return $variables;
41
 * }
42
 */
43
class CalMigrationUpdate extends AbstractUpdate
44
{
45
    /**
46
     * Import prefix.
47
     */
48
    const IMPORT_PREFIX = 'calMigration:';
49
50
    /**
51
     * Event table.
52
     */
53
    const EVENT_TABLE = 'tx_calendarize_domain_model_event';
54
55
    /**
56
     * Configuration table.
57
     */
58
    const CONFIGURATION_TABLE = 'tx_calendarize_domain_model_configuration';
59
60
    /**
61
     * ConfigurationGroup table.
62
     */
63
    const CONFIGURATION_GROUP_TABLE = 'tx_calendarize_domain_model_configurationgroup';
64
65
    /**
66
     * The human-readable title of the upgrade wizard.
67
     *
68
     * @var string
69
     */
70
    protected $title = 'Migrate cal event structures to the new calendarize event structures.
71
    Try to migrate all cal information and place the new calendarize event models in the same folder
72
    as the cal-records. Please note: the migration will be create calendarize default models.';
73
74
    public function getIdentifier(): string
75
    {
76
        return 'calMigration';
77
    }
78
79
    /**
80
     * Checks whether updates are required.
81
     *
82
     * @param string &$description The description for the update
83
     *
84
     * @return bool Whether an update is required (TRUE) or not (FALSE)
85
     */
86
    public function checkForUpdate(&$description)
87
    {
88
        $nonMigratedCalIds = $this->getNonMigratedCalIds();
89
        $count = \count($nonMigratedCalIds);
90
        if (0 === $count) {
91
            return false;
92
        }
93
        $description = 'There ' . ($count > 1 ? 'are ' . $count : 'is ' . $count) . ' non migrated EXT:cal event
94
        ' . ($count > 1 ? 's' : '') . '. Run the update process to migrate the events to EXT:calendarize events.';
95
96
        return true;
97
    }
98
99
    /**
100
     * Performs the accordant updates.
101
     *
102
     * @param array &$dbQueries      Queries done in this update
103
     * @param mixed &$customMessages Custom messages
104
     *
105
     * @return bool Whether everything went smoothly or not
106
     */
107
    public function executeUpdate(): bool
108
    {
109
        $calIds = $this->getNonMigratedCalIds();
110
        if (empty($calIds)) {
111
            return true;
112
        }
113
        $dbQueries = [];
114
        $this->performSysCategoryUpdate($calIds, $dbQueries, $customMessages);
115
        $this->performSysFileReferenceUpdate($calIds, $dbQueries, $customMessages);
116
        $this->performExceptionEventUpdate($calIds, $dbQueries, $customMessages);
117
        $this->performCalEventUpdate($calIds, $dbQueries, $customMessages);
118
        $this->performLinkEventToCategory($calIds, $dbQueries, $customMessages);
119
        $this->performLinkEventToConfigurationGroup($calIds, $dbQueries, $customMessages);
120
121
        return true;
122
    }
123
124
    /**
125
     * Perform CAL event update.
126
     *
127
     * @param       $calIds
128
     * @param array $dbQueries
129
     * @param       $customMessages
130
     *
131
     * @return bool
132
     */
133
    public function performCalEventUpdate($calIds, array &$dbQueries, &$customMessages)
134
    {
135
        $table = 'tx_cal_event';
136
        $db = HelperUtility::getDatabaseConnection($table);
137
        $q = $db->createQueryBuilder();
138
        $q->getRestrictions()
139
            ->removeAll()
140
            ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
141
142
        $locationTable = 'tx_cal_location';
143
        $locations = HelperUtility::getDatabaseConnection($locationTable)
144
            ->createQueryBuilder()
145
            ->select('*')
146
            ->from($locationTable)
147
            ->execute()
148
            ->fetchAll();
149
        $locationByUid = [];
150
        foreach ($locations as $location) {
151
            $locationByUid[$location['uid']] = $location['name'];
152
        }
153
154
        $events = $q->select('*')->from($table)->where(
155
            $q->expr()->in('uid', $calIds)
156
        )->execute()->fetchAll();
157
158
        foreach ($events as $event) {
159
            $calendarizeEventRecord = [
160
                'pid' => $event['pid'],
161
                'import_id' => self::IMPORT_PREFIX . (int)$event['uid'],
162
                'tstamp' => $event['tstamp'],
163
                'crdate' => $event['crdate'],
164
                'hidden' => $event['hidden'],
165
                'starttime' => $event['starttime'],
166
                'endtime' => $event['endtime'],
167
                'title' => $event['title'],
168
                'organizer' => $event['organizer'],
169
                'location' => $event['location_id'] > 0 ? $locationByUid[$event['location_id']] : $event['location'],
170
                'abstract' => $event['teaser'],
171
                'description' => $event['description'],
172
                'images' => (int)$event['image'],
173
                'downloads' => (int)$event['attachment'],
174
                'calendarize' => $this->buildConfigurations($event, $dbQueries),
175
            ];
176
177
            $variables = [
178
                'calendarizeEventRecord' => $calendarizeEventRecord,
179
                'event' => $event,
180
                'table' => self::EVENT_TABLE,
181
                'dbQueries' => $dbQueries,
182
            ];
183
184
            $dispatcher = HelperUtility::getSignalSlotDispatcher();
185
            $variables = $dispatcher->dispatch(__CLASS__, __FUNCTION__ . 'PreInsert', $variables);
186
187
            $q->insert($variables['table'])->values($variables['calendarizeEventRecord']);
188
            $dbQueries[] = $q->getSQL();
189
190
            $q->execute();
191
192
            $variablesPostInsert = [
193
                'calendarizeEventRecord' => $calendarizeEventRecord,
194
                'event' => $event,
195
                'table' => $variables['table'],
196
                'recordId' => $db->lastInsertId($variables['table']),
197
                'dbQueries' => $dbQueries,
198
            ];
199
200
            $dispatcher = HelperUtility::getSignalSlotDispatcher();
201
            $dispatcher->dispatch(__CLASS__, __FUNCTION__ . 'PostInsert', $variablesPostInsert);
202
        }
203
204
        $indexer = GeneralUtility::makeInstance(IndexerService::class);
205
        $indexer->reindexAll();
206
207
        return true;
208
    }
209
210
    /**
211
     * Perform exception event update.
212
     *
213
     * @param       $calIds
214
     * @param array $dbQueries
215
     * @param array $customMessages
216
     *
217
     * @return bool
218
     */
219
    public function performExceptionEventUpdate($calIds, &$dbQueries, &$customMessages)
220
    {
221
        $table = 'tx_cal_exception_event_group';
222
        // ConfigurationGroup für jede ExceptionGroup
223
        $db = HelperUtility::getDatabaseConnection($table);
224
        $q = $db->createQueryBuilder();
225
226
        $variables = [
227
            'table' => $table,
228
            'dbQueries' => $dbQueries,
229
            'calIds' => $calIds,
230
        ];
231
232
        $q->getRestrictions()
233
            ->removeAll()
234
            ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
235
236
        $q->select('*')->from($variables['table']);
237
238
        $selectResults = $q->execute()->fetchAll();
239
        $dbQueries[] = $q->getSQL();
240
241
        foreach ($selectResults as $selectResult) {
242
            $group = [
243
                'pid' => $selectResult['pid'],
244
                'tstamp' => $selectResult['tstamp'],
245
                'crdate' => $selectResult['crdate'],
246
                'cruser_id' => $selectResult['cruser_id'],
247
                'title' => $selectResult['title'],
248
                'configurations' => $this->getExceptionConfigurationForExceptionGroup($selectResult['uid'], $dbQueries),
249
                'hidden' => $selectResult['hidden'],
250
                'import_id' => self::IMPORT_PREFIX . $selectResult['uid'],
251
            ];
252
253
            $q->insert(self::CONFIGURATION_GROUP_TABLE)->values($group);
254
            $dbQueries[] = $q->getSQL();
255
256
            $q->execute();
257
        }
258
259
        return true;
260
    }
261
262
    /**
263
     * Perform link event to configuration group.
264
     *
265
     * @param $calIds
266
     * @param $dbQueries
267
     * @param $customMessages
268
     *
269
     * @return bool
270
     */
271
    public function performLinkEventToConfigurationGroup($calIds, &$dbQueries, &$customMessages)
272
    {
273
        $db = HelperUtility::getDatabaseConnection(self::CONFIGURATION_GROUP_TABLE);
274
        $q = $db->createQueryBuilder();
275
        $now = new \DateTime();
276
277
        $variables = [
278
            'table' => self::CONFIGURATION_GROUP_TABLE,
279
            'dbQueries' => $dbQueries,
280
            'calIds' => $calIds,
281
        ];
282
283
        $selectResults = $q->select('*')->from($variables['table'])->execute()->fetchAll();
284
        $dbQueries[] = $q->getSQL();
285
286
        foreach ($selectResults as $group) {
287
            $importId = explode(':', $group['import_id']);
288
            $groupId = (int)$importId[1];
289
290
            $variables = [
291
                'table' => 'tx_cal_exception_event_mm',
292
                'dbQueries' => $dbQueries,
293
                'calIds' => $calIds,
294
            ];
295
296
            $q->resetQueryParts()->resetRestrictions();
297
298
            $q->select('uid_local')
299
                ->from($variables['table'])
300
                ->where(
301
                    $q->expr()->andX(
302
                        $q->expr()->eq('tablenames', $q->createNamedParameter('tx_cal_exception_event_group')),
303
                        $q->expr()->eq('uid_foreign', $q->createNamedParameter((int)$groupId, \PDO::PARAM_INT))
304
                    )
305
                );
306
307
            $dbQueries[] = $q->getSQL();
308
            $selectResults = $q->execute()->fetchAll();
309
310
            foreach ($selectResults as $eventUid) {
311
                $eventImportId = self::IMPORT_PREFIX . (int)$eventUid['uid_local'];
312
                $configurationRow = [
313
                    'pid' => (int)$group['pid'],
314
                    'tstamp' => $now->getTimestamp(),
315
                    'crdate' => $now->getTimestamp(),
316
                    'type' => 'group',
317
                    'handling' => 'exclude',
318
                    'groups' => $group['uid'],
319
                ];
320
321
                $this->updateEventWithConfiguration($eventImportId, $configurationRow, $dbQueries, $customMessages);
322
            }
323
        }
324
325
        return true;
326
    }
327
328
    /**
329
     * Migrate the 'sys_file_reference' entries from 'tx_cal_event' to 'tx_calendarize_domain_model_event'.
330
     * Mark the imported entries with the import-id.
331
     *
332
     * @param       $calIds
333
     * @param array $dbQueries
334
     * @param       $customMessages
335
     */
336
    public function performSysFileReferenceUpdate($calIds, array &$dbQueries, &$customMessages)
337
    {
338
        $db = HelperUtility::getDatabaseConnection('tx_cal_event');
339
        $q = $db->createQueryBuilder();
340
341
        $variables = [
342
            'table' => 'tx_cal_event',
343
            'fieldnames' => ['image', 'attachment'],
344
            'dbQueries' => $dbQueries,
345
            'calIds' => $calIds,
346
        ];
347
348
        // select all not migrated entries
349
        $fieldnames = 'fieldname = \'' . implode('\' OR fieldname = \'', $variables['fieldnames']) . '\'';
350
        $selectWhere = 'tablenames = \'' . $variables['table'] . '\' AND (' . $fieldnames . ')';
351
        $selectWhere .= ' AND NOT EXISTS (SELECT NULL FROM sys_file_reference sfr2 WHERE sfr2.import_id = CONCAT(\'' . self::IMPORT_PREFIX . '\', sfr1.uid))';
352
353
        $q->select('*')
354
            ->from('sys_file_reference', 'sfr1')
355
            ->where($selectWhere);
356
357
        $dbQueries[] = $q->getSQL();
358
        $selectResults = $q->execute()->fetchAll();
359
360
        $variables = [
361
            'table' => self::EVENT_TABLE,
362
            'fieldnames' => $variables['fieldnames'],
363
            'dbQueries' => $dbQueries,
364
            'calIds' => $calIds,
365
            'selectResults' => $selectResults,
366
        ];
367
368
        // create new entry with import_id
369
        foreach ($variables['selectResults'] as $selectResult) {
370
            $selectResult['tablenames'] = $variables['table'];
371
            $selectResult['import_id'] = self::IMPORT_PREFIX . $selectResult['uid'];
372
            $selectResult['fieldname'] = ('image' === $selectResult['fieldname']) ? 'images' : 'downloads';
373
            unset($selectResult['uid_foreign'], $selectResult['uid']);
374
375
            $q->resetQueryParts()->resetRestrictions();
376
            $q->insert('sys_file_reference')->values($selectResult);
377
378
            $dbQueries[] = $q->getSQL();
379
380
            $q->execute();
381
        }
382
    }
383
384
    /**
385
     * Link the Events to the migrated Categories.
386
     * This build up the 'sys_category_record_mm' table on base of the 'tx_cal_event_category_mm' table.
387
     *
388
     * @param       $calIds
389
     * @param array $dbQueries
390
     * @param array $customMessages
391
     */
392
    public function performLinkEventToCategory($calIds, &$dbQueries, &$customMessages)
393
    {
394
        $table = 'tx_cal_event_category_mm';
395
396
        $db = HelperUtility::getDatabaseConnection($table);
397
        $q = $db->createQueryBuilder();
398
399
        $q->select('*')->from($table);
400
        $dbQueries[] = $q->getSQL();
401
402
        $selectResults = $q->execute()->fetchAll();
403
404
        $variables = [
405
            'tablenames' => self::EVENT_TABLE,
406
            'fieldname' => 'categories',
407
            'dbQueries' => $dbQueries,
408
        ];
409
410
        $dispatcher = HelperUtility::getSignalSlotDispatcher();
411
        $variables = $dispatcher->dispatch(__CLASS__, __FUNCTION__, $variables);
412
413
        foreach ($selectResults as $mm) {
414
            $eventUid = (int)$this->getCalendarizeEventUid(self::IMPORT_PREFIX . $mm['uid_local'], $dbQueries, $customMessages);
415
            $categoryUid = (int)$this->getCalendarizeCategoryUid(
416
                self::IMPORT_PREFIX . $mm['uid_foreign'],
417
                $dbQueries,
418
                $customMessages
419
            );
420
421
            if (0 !== $eventUid && 0 !== $categoryUid) {
422
                $insertValues = [
423
                    'uid_local' => $categoryUid,
424
                    'uid_foreign' => $eventUid,
425
                    'tablenames' => $variables['tablenames'],
426
                    'fieldname' => $variables['fieldname'],
427
                ];
428
429
                $q->insert('sys_category_record_mm')->values($insertValues);
430
                $dbQueries[] = $q->getSQL();
431
432
                $q->execute();
433
            }
434
        }
435
    }
436
437
    /**
438
     * Update event with configuration.
439
     *
440
     * @param $eventImportId
441
     * @param $configuration
442
     * @param $dbQueries
443
     * @param $customMessages
444
     *
445
     * @return array
446
     */
447
    protected function updateEventWithConfiguration($eventImportId, $configuration, &$dbQueries, &$customMessages)
448
    {
449
        $db = HelperUtility::getDatabaseConnection(self::CONFIGURATION_TABLE);
450
        $q = $db->createQueryBuilder();
451
452
        $configurationRow = $this->findEventExcludeConfiguration($eventImportId, $dbQueries, $customMessages);
453
        if ($configurationRow) {
454
            $configurationRow['groups'] = $this->addValueToCsv($configurationRow['groups'], $configuration['groups']);
455
456
            unset($configurationRow['uid']);
457
458
            $q->update(self::CONFIGURATION_GROUP_TABLE)
459
                ->where('uid', $q->createNamedParameter((int)$configuration['uid'], \PDO::PARAM_INT));
460
            foreach ($configurationRow as $key => $value) {
0 ignored issues
show
Bug introduced by
The expression $configurationRow of type array|boolean is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
461
                $q->set($key, $value);
462
            }
463
464
            $dbQueries[] = $q->getSQL();
465
            $results = $q->execute();
466
        } else {
467
            $q->insert(self::CONFIGURATION_TABLE)->values($configuration);
468
            $dbQueries[] = $q->getSQL();
469
470
            $configurationId = $db->lastInsertId(self::CONFIGURATION_TABLE);
471
472
            $results = $this->addConfigurationIdToEvent($eventImportId, $configurationId, $dbQueries, $customMessages);
473
        }
474
475
        return $results;
476
    }
477
478
    /**
479
     * Add Value to CSV.
480
     *
481
     * @param string $csv
482
     * @param string $value
483
     *
484
     * @return string
485
     */
486
    protected function addValueToCsv($csv, $value)
487
    {
488
        $csvArray = GeneralUtility::trimExplode(',', $csv);
489
490
        // check for doubles
491
        $values = array_flip($csvArray);
492
        if (isset($values[$value])) {
493
            return $csv;
494
        }
495
        $csvArray[] = $value;
496
        $csv = implode(',', $csvArray);
497
498
        return $csv;
499
    }
500
501
    /**
502
     * Add configuration ID to event.
503
     *
504
     * @param string $eventImportId
505
     * @param int    $configurationId
506
     * @param array  $dbQueries
507
     * @param array  $customMessages
508
     *
509
     * @return array|bool
510
     */
511
    protected function addConfigurationIdToEvent($eventImportId, $configurationId, &$dbQueries, &$customMessages)
512
    {
513
        $event = $this->findEventByImportId($eventImportId, $dbQueries, $customMessages);
514
        if (!$event) {
515
            return false;
516
        }
517
518
        $event['calendarize'] = $this->addValueToCsv($event['calendarize'], $configurationId);
519
520
        return $this->updateEvent($event['uid'], $event, $dbQueries, $customMessages);
521
    }
522
523
    /**
524
     * Update event.
525
     *
526
     * @param int   $eventId
527
     * @param array $values
528
     * @param array $dbQueries
529
     * @param array $customMessages
530
     *
531
     * @return array
532
     */
533
    protected function updateEvent($eventId, $values, &$dbQueries, &$customMessages)
534
    {
535
        $db = HelperUtility::getDatabaseConnection(self::EVENT_TABLE);
536
        $q = $db->createQueryBuilder();
537
538
        $variables = [
539
            'table' => self::EVENT_TABLE,
540
            'eventId' => (int)$eventId,
541
            'values' => $values,
542
            'dbQueries' => $dbQueries,
543
        ];
544
545
        $dispatcher = HelperUtility::getSignalSlotDispatcher();
546
        $variables = $dispatcher->dispatch(__CLASS__, __FUNCTION__, $variables);
547
548
        $q->update($variables['table'])
549
            ->where(
550
                $q->expr()->eq('uid', $q->createNamedParameter((int)$eventId, \PDO::PARAM_INT))
551
            );
552
        foreach ($variables['values'] as $key => $value) {
553
            $q->set($key, $value);
554
        }
555
556
        unset($values['uid']);
557
558
        $dbQueries[] = $q->getSQL();
559
560
        return $q->execute()->fetchAll();
561
    }
562
563
    /**
564
     * Find event by import ID.
565
     *
566
     * @param $eventImportId
567
     * @param $dbQueries
568
     * @param $customMessages
569
     *
570
     * @return array|bool
571
     */
572
    protected function findEventByImportId($eventImportId, &$dbQueries, &$customMessages)
573
    {
574
        $db = HelperUtility::getDatabaseConnection(self::EVENT_TABLE);
575
        $q = $db->createQueryBuilder();
576
577
        $variables = [
578
            'table' => self::EVENT_TABLE,
579
            'dbQueries' => $dbQueries,
580
            'eventImportId' => $eventImportId,
581
        ];
582
583
        $dispatcher = HelperUtility::getSignalSlotDispatcher();
584
        $variables = $dispatcher->dispatch(__CLASS__, __FUNCTION__, $variables);
585
586
        $q->select('*')->from($variables['table'])
587
            ->where(
588
                $q->expr()->eq('import_id', $q->createNamedParameter($eventImportId))
589
            );
590
591
        $dbQueries[] = $q->getSQL();
592
593
        return $q->execute()->fetchAll();
594
    }
595
596
    /**
597
     * Find event exclude configuration.
598
     *
599
     * @param string $eventImportId
600
     * @param array  $dbQueries
601
     * @param array  $customMessages
602
     *
603
     * @return array|bool
604
     */
605
    protected function findEventExcludeConfiguration($eventImportId, &$dbQueries, &$customMessages)
606
    {
607
        $event = $this->findEventByImportId($eventImportId, $dbQueries, $customMessages);
608
609
        if (!$event) {
610
            return false;
611
        }
612
613
        $variables = [
614
            'table' => self::CONFIGURATION_TABLE,
615
            'dbQueries' => $dbQueries,
616
            'event' => $event,
617
        ];
618
619
        $db = HelperUtility::getDatabaseConnection($variables['table']);
620
        $q = $db->createQueryBuilder();
621
622
        $q->select('*')
623
            ->from($variables['table'])
624
            ->where(
625
                $q->expr()->andX(
626
                    $q->expr()->eq('type', 'group'),
627
                    $q->expr()->eq('handling', 'exclude'),
628
                    $q->expr()->in('uid', $variables['event']['calendarize'])
629
                )
630
            );
631
632
        $dbQueries[] = $q->getSQL();
633
634
        return $q->execute()->fetchAll();
635
    }
636
637
    /**
638
     * Get exception configuration for exception group.
639
     *
640
     * @param       $groupId
641
     * @param array $dbQueries
642
     *
643
     * @return string
644
     */
645
    protected function getExceptionConfigurationForExceptionGroup($groupId, &$dbQueries)
646
    {
647
        $recordIds = [];
648
        $variables = [
649
            'table' => 'tx_cal_exception_event_group_mm',
650
            'dbQueries' => $dbQueries,
651
        ];
652
653
        $db = HelperUtility::getDatabaseConnection($variables['table']);
654
        $q = $db->createQueryBuilder();
655
656
        $q->select('*')
657
            ->from($variables['table'])
658
            ->where('uid_local', $q->createNamedParameter((int)$groupId, \PDO::PARAM_INT));
659
660
        $dbQueries[] = $q->getSQL();
661
662
        $mmResults = $q->execute()->fetchAll();
663
        foreach ($mmResults as $mmResult) {
664
            $variables = [
665
                'table' => 'tx_cal_exception_event',
666
                'dbQueries' => $dbQueries,
667
            ];
668
669
            $q->resetQueryParts()->resetRestrictions();
670
            $q->select('*')
671
                ->from($variables['table'])
672
                ->where(
673
                    $q->expr()->eq('uid', $q->createNamedParameter((int)$mmResult['uid_foreign'], \PDO::PARAM_INT))
674
                );
675
676
            $dbQueries[] = $q->getSQL();
677
678
            $selectResults = $q->execute()->fetchAll();
679
680
            foreach ($selectResults as $selectResult) {
681
                $configurationRow = [
682
                    'pid' => $selectResult['pid'],
683
                    'tstamp' => $selectResult['tstamp'],
684
                    'crdate' => $selectResult['crdate'],
685
                    'type' => 'time',
686
                    'handling' => 'include',
687
                    'start_date' => (string)$selectResult['start_date'] ?: null,
688
                    'end_date' => (string)$selectResult['end_date'] ?: null,
689
                    'start_time' => (int)$selectResult['start_time'],
690
                    'end_time' => (int)$selectResult['end_time'],
691
                    'all_day' => (null === $selectResult['start_time'] && null === $selectResult['end_time']) ? 1 : 0,
692
                    'frequency' => $this->mapFrequency($selectResult['freq']),
693
                    'till_date' => (string)$selectResult['until'] ?: null,
694
                    'counter_amount' => (int)$selectResult['cnt'],
695
                    'counter_interval' => (int)$selectResult['interval'],
696
                    'import_id' => self::IMPORT_PREFIX . $selectResult['uid'],
697
                ];
698
699
                $variables = [
700
                    'table' => self::CONFIGURATION_TABLE,
701
                    'configurationRow' => $configurationRow,
702
                ];
703
704
                $dispatcher = HelperUtility::getSignalSlotDispatcher();
705
                $variables = $dispatcher->dispatch(__CLASS__, __FUNCTION__ . 'PreInsert', $variables);
706
707
                $q->resetQueryParts()->resetRestrictions();
708
                $q->insert($variables['table'])->values($variables['configurationRow']);
709
710
                $dbQueries[] = $q->getSQL();
711
712
                $q->execute();
713
714
                $recordIds[] = $db->lastInsertId($variables['table']);
715
            }
716
        }
717
718
        return implode(',', $recordIds);
719
    }
720
721
    /**
722
     * Map frequency.
723
     *
724
     * @param string $calFrequency
725
     *
726
     * @return string
727
     */
728
    protected function mapFrequency($calFrequency)
729
    {
730
        $freq = [
731
            'none' => null,
732
            'day' => 'daily',
733
            'week' => 'weekly',
734
            'month' => 'monthly',
735
            'year' => 'yearly',
736
        ];
737
738
        if (!isset($freq[$calFrequency])) {
739
            return '';
740
        }
741
742
        return $freq[$calFrequency];
743
    }
744
745
    /**
746
     * Migrate the 'tx_cal_category' table to the 'sys_category' table.
747
     *
748
     * @param       $calIds
749
     * @param array $dbQueries
750
     * @param       $customMessages
751
     */
752
    protected function performSysCategoryUpdate($calIds, array &$dbQueries, &$customMessages)
753
    {
754
        // first migrate from tx_cal_category to sys_category
755
        $variables = [
756
            'table' => 'tx_cal_category',
757
            'dbQueries' => $dbQueries,
758
            'calIds' => $calIds,
759
        ];
760
761
        $db = HelperUtility::getDatabaseConnection($variables['table']);
762
        $q = $db->createQueryBuilder();
763
        $q->getRestrictions()
764
            ->removeAll()
765
            ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
766
767
        $q->select('*')
768
            ->from($variables['table']);
769
770
        $dbQueries[] = $q->getSQL();
771
772
        $selectResults = $q->execute()->fetchAll();
773
774
        foreach ($selectResults as $category) {
775
            $sysCategoryRecord = [
776
                'pid' => $category['pid'],
777
                'tstamp' => $category['tstamp'],
778
                'crdate' => $category['crdate'],
779
                'cruser_id' => $category['cruser_id'],
780
                'deleted' => $category['deleted'],
781
                'hidden' => $category['hidden'],
782
                'starttime' => $category['starttime'],
783
                'endtime' => $category['endtime'],
784
                'sys_language_uid' => $category['sys_language_uid'],
785
                'l10n_parent' => $category['l18n_parent'],
786
                'l10n_diffsource' => $category['l18n_diffsource'],
787
                'title' => $category['title'],
788
                'parent' => (int)$category['parent_category'],
789
                'import_id' => self::IMPORT_PREFIX . (int)$category['uid'],
790
                'sorting' => $category['sorting'],
791
            ];
792
793
            $q->resetQueryParts()->resetRestrictions();
794
795
            $q->insert('sys_category')->values($sysCategoryRecord);
796
            $dbQueries[] = $q->getSQL();
797
798
            $q->execute();
799
        }
800
801
        // second rewrite the tree
802
        $variables = [
803
            'table' => 'sys_category',
804
            'dbQueries' => $dbQueries,
805
            'calIds' => $calIds,
806
        ];
807
808
        $q->resetQueryParts()->resetRestrictions();
809
810
        $q->select('*')
811
            ->from($variables['table'])
812
            ->where(
813
                $q->expr()->neq('import_id', $q->createNamedParameter(''))
814
            );
815
816
        $dbQueries[] = $q->getSQL();
817
        $selectResults = $q->execute()->fetchAll();
818
819
        foreach ($selectResults as $sysCategory) {
820
            // update parent, because there are just the old uids
821
            $q->resetQueryParts()->resetRestrictions();
822
            $q->update('sys_category')
823
                ->where(
824
                    $q->expr()->eq('uid', $q->createNamedParameter((int)$sysCategory['uid'], \PDO::PARAM_INT))
825
                )->set(
826
                    'parent',
827
                    $this->getSysCategoryParentUid(self::IMPORT_PREFIX . (int)$sysCategory['parent'])
828
                );
829
830
            $dbQueries[] = $q->getSQL();
831
832
            $q->execute();
833
        }
834
    }
835
836
    /**
837
     * Return the parentUid for the 'sys_category' entry on base of the import_id.
838
     *
839
     * @param string $importId
840
     *
841
     * @return int
842
     */
843
    protected function getSysCategoryParentUid($importId)
844
    {
845
        $table = 'sys_category';
846
        $db = HelperUtility::getDatabaseConnection($table);
847
        $q = $db->createQueryBuilder();
848
849
        $q->select('uid')
850
            ->from($table)
851
            ->where(
852
                $q->expr()->eq('import_id', $q->createNamedParameter($importId))
853
            );
854
855
        $dbQueries[] = $q->getSQL();
0 ignored issues
show
Coding Style Comprehensibility introduced by
$dbQueries was never initialized. Although not strictly required by PHP, it is generally a good practice to add $dbQueries = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
856
857
        $result = $q->execute()->fetchAll();
858
859
        return (int)$result[0]['uid'];
860
    }
861
862
    /**
863
     * Get the event uid on base of the given import_id.
864
     * The import_id is the original tx_cal_event id prefixed with the IMPORT_PREFIX.
865
     *
866
     * @param string $importId
867
     * @param array  $dbQueries
868
     * @param array  $customMessages
869
     *
870
     * @return int
871
     */
872
    protected function getCalendarizeEventUid($importId, &$dbQueries, &$customMessages)
873
    {
874
        $variables = [
875
            'table' => self::EVENT_TABLE,
876
            'dbQueries' => $dbQueries,
877
        ];
878
879
        $q = HelperUtility::getDatabaseConnection($variables['table'])->createQueryBuilder();
880
881
        $dispatcher = HelperUtility::getSignalSlotDispatcher();
882
        $variables = $dispatcher->dispatch(__CLASS__, __FUNCTION__, $variables);
883
884
        // also get restricted (e.g. hidden) records, otherwise retrieving event uid for
885
        // restricted records will always return 0
886
        $q->getRestrictions()
887
            ->removeAll()
888
            ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
889
        $q->select('uid')
890
            ->from($variables['table'])
891
            ->where(
892
                $q->expr()->eq('import_id', $q->createNamedParameter($importId))
893
            );
894
895
        $dbQueries[] = $q->getSQL();
896
897
        $result = $q->execute()->fetchAll();
898
899
        return (int)$result[0]['uid'];
900
    }
901
902
    /**
903
     * Get the sys_category uid on base of the given import_id.
904
     * The import_id is the original tx_cal_category id prefixed with the IMPORT_PREFIX.
905
     *
906
     * @see CalMigrationUpdate::IMPORT_PREFIX
907
     *
908
     * @param string $importId
909
     * @param array  $dbQueries
910
     * @param array  $customMessages
911
     *
912
     * @return int
913
     */
914
    protected function getCalendarizeCategoryUid($importId, &$dbQueries, &$customMessages)
915
    {
916
        $variables = [
917
            'table' => 'sys_category',
918
            'dbQueries' => $dbQueries,
919
        ];
920
921
        $q = HelperUtility::getDatabaseConnection($variables['table'])->createQueryBuilder();
922
923
        $dispatcher = HelperUtility::getSignalSlotDispatcher();
924
        $variables = $dispatcher->dispatch(__CLASS__, __FUNCTION__, $variables);
925
926
        $q->select('uid')
927
            ->from($variables['table'])
928
            ->where(
929
                $q->expr()->eq('import_id', $q->createNamedParameter($importId))
930
            );
931
932
        $dbQueries[] = $q->getSQL();
933
934
        $result = $q->execute()->fetchAll();
935
936
        return (int)$result[0]['uid'];
937
    }
938
939
    /**
940
     * Build configurations.
941
     *
942
     * @param $calEventRow
943
     * @param $dbQueries
944
     *
945
     * @return int
946
     */
947
    protected function buildConfigurations($calEventRow, &$dbQueries)
948
    {
949
        $configurationRow = [
950
            'pid' => $calEventRow['pid'],
951
            'tstamp' => $calEventRow['tstamp'],
952
            'crdate' => $calEventRow['crdate'],
953
            'type' => 'time',
954
            'handling' => 'include',
955
            'start_date' => (string)$calEventRow['start_date'] ?: null,
956
            'end_date' => (string)$calEventRow['end_date'] ?: null,
957
            'start_time' => (int)$calEventRow['start_time'],
958
            'end_time' => (int)$calEventRow['end_time'],
959
            'all_day' => $calEventRow['allday'],
960
            'frequency' => $this->mapFrequency($calEventRow['freq']),
961
            'till_date' => (string)$calEventRow['until'] ?: null,
962
            'counter_amount' => (int)$calEventRow['cnt'],
963
            'counter_interval' => (int)$calEventRow['interval'],
964
        ];
965
966
        $variables = [
967
            'table' => self::CONFIGURATION_TABLE,
968
            'configurationRow' => $configurationRow,
969
            'calEventRow' => $calEventRow,
970
            'dbQueries' => $dbQueries,
971
        ];
972
973
        $db = HelperUtility::getDatabaseConnection($variables['table']);
974
        $q = $db->createQueryBuilder();
975
976
        $dispatcher = HelperUtility::getSignalSlotDispatcher();
977
        $variables = $dispatcher->dispatch(__CLASS__, __FUNCTION__ . 'PreInsert', $variables);
978
979
        $q->insert($variables['table'])
980
            ->values($variables['configurationRow']);
981
982
        $dbQueries[] = $q->getSQL();
983
        $q->execute();
984
        $recordId = $db->lastInsertId($variables['table']);
985
986
        $variables = [
987
            'table' => $variables['table'],
988
            'configurationRow' => $configurationRow,
989
            'calEventRow' => $calEventRow,
990
            'recordId' => $recordId,
991
            'dbQueries' => $dbQueries,
992
        ];
993
994
        $dispatcher = HelperUtility::getSignalSlotDispatcher();
995
        $variables = $dispatcher->dispatch(__CLASS__, __FUNCTION__ . 'PostInsert', $variables);
996
997
        return $variables['recordId'];
998
    }
999
1000
    /**
1001
     * Get the non migrated cal IDs.
1002
     *
1003
     * @return array
1004
     */
1005
    protected function getNonMigratedCalIds()
1006
    {
1007
        $checkImportIds = [];
1008
        $nonMigrated = [];
1009
1010
        $table = 'tx_cal_event';
1011
        $q = HelperUtility::getDatabaseConnection($table)->createQueryBuilder();
1012
        $q->getRestrictions()
1013
            ->removeAll()
1014
            ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
1015
1016
        $events = $q->select('uid')
1017
            ->from($table)
1018
            ->execute()
1019
            ->fetchAll();
1020
1021
        foreach ($events as $event) {
1022
            $checkImportIds[] = '"' . self::IMPORT_PREFIX . $event['uid'] . '"';
1023
            $nonMigrated[(int)$event['uid']] = (int)$event['uid'];
1024
        }
1025
1026
        $countOriginal = \count($checkImportIds);
1027
        if (0 === $countOriginal) {
1028
            return [];
1029
        }
1030
1031
        $variables = [
1032
            'table' => self::EVENT_TABLE,
1033
        ];
1034
1035
        $dispatcher = HelperUtility::getSignalSlotDispatcher();
1036
        $variables = $dispatcher->dispatch(__CLASS__, __FUNCTION__ . 'PreSelect', $variables);
1037
1038
        $q->resetQueryParts();
1039
1040
        $migratedRows = $q->select('uid', 'import_id')
1041
            ->from($variables['table'])
1042
            ->where(
1043
                $q->expr()->in('import_id', $checkImportIds)
1044
            )
1045
            ->execute()
1046
            ->fetchAll();
1047
1048
        foreach ($migratedRows as $migratedRow) {
1049
            $importId = (int)str_replace(self::IMPORT_PREFIX, '', $migratedRow['import_id']);
1050
            if (isset($nonMigrated[$importId])) {
1051
                unset($nonMigrated[$importId]);
1052
            }
1053
        }
1054
1055
        $variables = [
1056
            'table' => $variables['table'],
1057
            'migratedRows' => $migratedRows,
1058
            'nonMigrated' => $nonMigrated,
1059
        ];
1060
1061
        $dispatcher = HelperUtility::getSignalSlotDispatcher();
1062
        $variables = $dispatcher->dispatch(__CLASS__, __FUNCTION__ . 'ReadyParsed', $variables);
1063
1064
        return $variables['nonMigrated'];
1065
    }
1066
1067
    public function updateNecessary(): bool
1068
    {
1069
        $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
1070
        $connection = $connectionPool->getConnectionByName(ConnectionPool::DEFAULT_CONNECTION_NAME);
1071
        $dbSchema = $connection->getSchemaManager()->createSchema();
1072
1073
        $tableNames = array_map(function ($table) {
1074
            return $table->getName();
1075
        }, $dbSchema->getTables());
1076
1077
        return \in_array('tx_cal_event', $tableNames);
1078
    }
1079
1080
    public function getPrerequisites(): array
1081
    {
1082
        return [
1083
            DatabaseUpdatedPrerequisite::class,
1084
        ];
1085
    }
1086
}
1087