Completed
Pull Request — master (#525)
by
unknown
02:34
created

performLinkEventToSysCategory()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 64

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 64
rs 8.7853
c 0
b 0
f 0
cc 3
nc 3
nop 3

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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\Connection;
15
use TYPO3\CMS\Core\Database\ConnectionPool;
16
use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
17
use TYPO3\CMS\Core\Utility\GeneralUtility;
18
use TYPO3\CMS\Install\Updates\DatabaseUpdatedPrerequisite;
19
20
/**
21
 * CalMigrationUpdate.
22
 *
23
 * If using the slots please use the m with func_get_args!
24
 * Example:
25
 * /**
26
 *  * @SignalClass("HDNET\Calendarize\Updates\CalMigrationUpdate")
27
 *  * @SignalName("getCalendarizeEventUid")
28
 *
29
 *  *@return array
30
 *  *
31
 * public function getCalendarizeEventUid()
32
 * {
33
 *    $args = func_get_args();
34
 *    list($table, $dbQueries, $call) = $args;
35
 *
36
 *    $variables = [
37
 *        'table'     => self::EVENT_TABLE,
38
 *        'dbQueries' => $dbQueries
39
 *    ];
40
 *
41
 *    return $variables;
42
 * }
43
 */
44
class CalMigrationUpdate extends AbstractUpdate
45
{
46
    /**
47
     * Import prefix.
48
     */
49
    const IMPORT_PREFIX = 'calMigration:';
50
51
    /**
52
     * Event table.
53
     */
54
    const EVENT_TABLE = 'tx_calendarize_domain_model_event';
55
56
    /**
57
     * Configuration table.
58
     */
59
    const CONFIGURATION_TABLE = 'tx_calendarize_domain_model_configuration';
60
61
    /**
62
     * ConfigurationGroup table.
63
     */
64
    const CONFIGURATION_GROUP_TABLE = 'tx_calendarize_domain_model_configurationgroup';
65
66
    /**
67
     * The human-readable title of the upgrade wizard.
68
     *
69
     * @var string
70
     */
71
    protected $title = 'Migrate cal event structures to the new calendarize event structures.
72
    Try to migrate all cal information and place the new calendarize event models in the same folder
73
    as the cal-records. Please note: the migration will be create calendarize default models.';
74
75
    public function getIdentifier(): string
76
    {
77
        return 'calendarize_calMigration';
78
    }
79
80
    /**
81
     * Checks whether updates are required.
82
     *
83
     * @param string &$description The description for the update
84
     *
85
     * @return bool Whether an update is required (TRUE) or not (FALSE)
86
     */
87
    public function checkForUpdate(&$description)
88
    {
89
        $nonMigratedCalIds = $this->getNonMigratedCalIds();
90
        $count = \count($nonMigratedCalIds);
91
        if (0 === $count) {
92
            return false;
93
        }
94
        $description = 'There ' . ($count > 1 ? 'are ' . $count : 'is ' . $count) . ' non migrated EXT:cal event
95
        ' . ($count > 1 ? 's' : '') . '. Run the update process to migrate the events to EXT:calendarize events.';
96
97
        return true;
98
    }
99
100
    /**
101
     * Performs the accordant updates.
102
     *
103
     * @param array &$dbQueries      Queries done in this update
104
     * @param mixed &$customMessages Custom messages
105
     *
106
     * @return bool Whether everything went smoothly or not
107
     */
108
    public function executeUpdate(): bool
109
    {
110
        $calIds = $this->getNonMigratedCalIds();
111
        if (empty($calIds)) {
112
            return true;
113
        }
114
        $dbQueries = [];
115
116
        /**
117
         * @var bool
118
         */
119
        $calUsesSysCategories = $this->isCalWithSysCategories();
120
121
        if (!$calUsesSysCategories) {
122
            $this->performSysCategoryUpdate($calIds, $dbQueries, $customMessages);
123
        }
124
        $this->performSysFileReferenceUpdate($calIds, $dbQueries, $customMessages);
125
        $this->performExceptionEventUpdate($calIds, $dbQueries, $customMessages);
126
        $this->performCalEventUpdate($calIds, $dbQueries, $customMessages);
127
        if ($calUsesSysCategories) {
128
            $this->performLinkEventToSysCategory($calIds, $dbQueries, $customMessages);
129
        } else {
130
            $this->performLinkEventToCategory($calIds, $dbQueries, $customMessages);
131
        }
132
        $this->performLinkEventToConfigurationGroup($calIds, $dbQueries, $customMessages);
133
134
        return true;
135
    }
136
137
    /**
138
     * Check if cal is already using sys_category instead
139
     * of tx_cal_category. This affects the conversion of
140
     * categories and category / event relations.
141
     *
142
     * @return bool
143
     */
144
    protected function isCalWithSysCategories(): bool
145
    {
146
        $table = 'sys_category_record_mm';
147
148
        $db = HelperUtility::getDatabaseConnection($table);
149
        $q = $db->createQueryBuilder();
150
        $count = (int)$q->count('*')
151
            ->from($table)
152
            ->where(
153
                $q->expr()->eq('tablenames', $q->createNamedParameter('tx_cal_event')),
154
                $q->expr()->eq('fieldname', $q->createNamedParameter('category_id'))
155
            )
156
            ->execute();
157
        return $count > 0;
158
    }
159
160
    /**
161
     * Perform CAL event update.
162
     *
163
     * @param       $calIds
164
     * @param array $dbQueries
165
     * @param       $customMessages
166
     *
167
     * @return bool
168
     */
169
    public function performCalEventUpdate($calIds, array &$dbQueries, &$customMessages)
170
    {
171
        $table = 'tx_cal_event';
172
        $db = HelperUtility::getDatabaseConnection($table);
173
        $q = $db->createQueryBuilder();
174
        $q->getRestrictions()
175
            ->removeAll()
176
            ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
177
178
        $locationTable = 'tx_cal_location';
179
        $locations = HelperUtility::getDatabaseConnection($locationTable)
180
            ->createQueryBuilder()
181
            ->select('*')
182
            ->from($locationTable)
183
            ->execute()
184
            ->fetchAll();
185
        $locationByUid = [];
186
        foreach ($locations as $location) {
187
            $locationByUid[$location['uid']] = $location['name'];
188
        }
189
190
        $events = $q->select('*')
191
            ->from($table)
192
            ->where(
193
                $q->expr()->in('uid', $q->createNamedParameter($calIds, Connection::PARAM_INT_ARRAY))
194
            )
195
            ->orderBy('l18n_parent')
196
            ->execute()->fetchAll();
197
198
        foreach ($events as $event) {
199
            // Get the parent id of the event record
200
            // Note: The parent record should exist at this time, since we orderBy('l18n_parent')
201
            $parentEventUid = 0;
202
            if ($event['l18n_parent']) {
203
                $parentEventUid = (int)$this->getCalendarizeEventUid(
204
                    self::IMPORT_PREFIX . $event['l18n_parent'],
205
                    $dbQueries,
206
                    $customMessages
207
                );
208
            }
209
210
            $calendarizeEventRecord = [
211
                'pid' => $event['pid'],
212
                'import_id' => self::IMPORT_PREFIX . (int)$event['uid'],
213
                'sys_language_uid' => $event['sys_language_uid'] ?? 0,
214
                'l10n_parent' => $parentEventUid,
215
                'tstamp' => $event['tstamp'],
216
                'crdate' => $event['crdate'],
217
                'hidden' => $event['hidden'],
218
                'starttime' => $event['starttime'],
219
                'endtime' => $event['endtime'],
220
                'title' => $event['title'],
221
                'organizer' => $event['organizer'],
222
                'location' => $event['location_id'] > 0 ? $locationByUid[$event['location_id']] : $event['location'],
223
                'abstract' => $event['teaser'],
224
                'description' => $event['description'],
225
                'images' => (int)$event['image'],
226
                'downloads' => (int)$event['attachment'],
227
                'calendarize' => $this->buildConfigurations($event, $dbQueries),
228
            ];
229
230
            $variables = [
231
                'calendarizeEventRecord' => $calendarizeEventRecord,
232
                'event' => $event,
233
                'table' => self::EVENT_TABLE,
234
                'dbQueries' => $dbQueries,
235
            ];
236
237
            $dispatcher = HelperUtility::getSignalSlotDispatcher();
238
            $variables = $dispatcher->dispatch(__CLASS__, __FUNCTION__ . 'PreInsert', $variables);
239
240
            $db = HelperUtility::getDatabaseConnection($variables['table']);
241
            $q = $db->createQueryBuilder();
242
            $q->insert($variables['table'])->values($variables['calendarizeEventRecord']);
243
            $dbQueries[] = $q->getSQL();
244
245
            $q->execute();
246
247
            $variablesPostInsert = [
248
                'calendarizeEventRecord' => $calendarizeEventRecord,
249
                'event' => $event,
250
                'table' => $variables['table'],
251
                'recordId' => $db->lastInsertId($variables['table']),
252
                'dbQueries' => $dbQueries,
253
            ];
254
255
            $dispatcher = HelperUtility::getSignalSlotDispatcher();
256
            $dispatcher->dispatch(__CLASS__, __FUNCTION__ . 'PostInsert', $variablesPostInsert);
257
        }
258
259
        $indexer = GeneralUtility::makeInstance(IndexerService::class);
260
        $indexer->reindexAll();
261
262
        return true;
263
    }
264
265
    /**
266
     * Perform exception event update.
267
     *
268
     * @param       $calIds
269
     * @param array $dbQueries
270
     * @param array $customMessages
271
     *
272
     * @return bool
273
     */
274
    public function performExceptionEventUpdate($calIds, &$dbQueries, &$customMessages)
275
    {
276
        $table = 'tx_cal_exception_event_group';
277
        // ConfigurationGroup für jede ExceptionGroup
278
        $db = HelperUtility::getDatabaseConnection($table);
279
        $q = $db->createQueryBuilder();
280
281
        $variables = [
282
            'table' => $table,
283
            'dbQueries' => $dbQueries,
284
            'calIds' => $calIds,
285
        ];
286
287
        $q->getRestrictions()
288
            ->removeAll()
289
            ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
290
291
        $q->select('*')->from($variables['table']);
292
293
        $selectResults = $q->execute()->fetchAll();
294
        $dbQueries[] = $q->getSQL();
295
296
        foreach ($selectResults as $selectResult) {
297
            $group = [
298
                'pid' => $selectResult['pid'],
299
                'tstamp' => $selectResult['tstamp'],
300
                'crdate' => $selectResult['crdate'],
301
                'cruser_id' => $selectResult['cruser_id'],
302
                'title' => $selectResult['title'],
303
                'configurations' => $this->getExceptionConfigurationForExceptionGroup($selectResult['uid'], $dbQueries),
304
                'hidden' => $selectResult['hidden'],
305
                'import_id' => self::IMPORT_PREFIX . $selectResult['uid'],
306
            ];
307
308
            $q = $db->createQueryBuilder();
309
            $q->insert(self::CONFIGURATION_GROUP_TABLE)->values($group);
310
            $dbQueries[] = $q->getSQL();
311
312
            $q->execute();
313
        }
314
315
        return true;
316
    }
317
318
    /**
319
     * Perform link event to configuration group.
320
     *
321
     * @param $calIds
322
     * @param $dbQueries
323
     * @param $customMessages
324
     *
325
     * @return bool
326
     */
327
    public function performLinkEventToConfigurationGroup($calIds, &$dbQueries, &$customMessages)
328
    {
329
        $db = HelperUtility::getDatabaseConnection(self::CONFIGURATION_GROUP_TABLE);
330
        $q = $db->createQueryBuilder();
331
        $now = new \DateTime();
332
333
        $variables = [
334
            'table' => self::CONFIGURATION_GROUP_TABLE,
335
            'dbQueries' => $dbQueries,
336
            'calIds' => $calIds,
337
        ];
338
339
        $selectResults = $q->select('*')->from($variables['table'])->execute()->fetchAll();
340
        $dbQueries[] = $q->getSQL();
341
342
        foreach ($selectResults as $group) {
343
            $importId = explode(':', $group['import_id']);
344
            $groupId = (int)$importId[1];
345
346
            $variables = [
347
                'table' => 'tx_cal_exception_event_mm',
348
                'dbQueries' => $dbQueries,
349
                'calIds' => $calIds,
350
            ];
351
352
            $q = HelperUtility::getDatabaseConnection('uid_local')->createQueryBuilder();
353
354
            $q->select('uid_local')
355
                ->from($variables['table'])
356
                ->where(
357
                    $q->expr()->andX(
358
                        $q->expr()->eq('tablenames', $q->createNamedParameter('tx_cal_exception_event_group')),
359
                        $q->expr()->eq('uid_foreign', $q->createNamedParameter((int)$groupId, \PDO::PARAM_INT))
360
                    )
361
                );
362
363
            $dbQueries[] = $q->getSQL();
364
            $selectResults = $q->execute()->fetchAll();
365
366
            foreach ($selectResults as $eventUid) {
367
                $eventImportId = self::IMPORT_PREFIX . (int)$eventUid['uid_local'];
368
                $configurationRow = [
369
                    'pid' => (int)$group['pid'],
370
                    'tstamp' => $now->getTimestamp(),
371
                    'crdate' => $now->getTimestamp(),
372
                    'type' => 'group',
373
                    'handling' => 'exclude',
374
                    'groups' => $group['uid'],
375
                ];
376
377
                $this->updateEventWithConfiguration($eventImportId, $configurationRow, $dbQueries, $customMessages);
378
            }
379
        }
380
381
        return true;
382
    }
383
384
    /**
385
     * Migrate the 'sys_file_reference' entries from 'tx_cal_event' to 'tx_calendarize_domain_model_event'.
386
     * Mark the imported entries with the import-id.
387
     *
388
     * @param       $calIds
389
     * @param array $dbQueries
390
     * @param       $customMessages
391
     */
392
    public function performSysFileReferenceUpdate($calIds, array &$dbQueries, &$customMessages)
393
    {
394
        $db = HelperUtility::getDatabaseConnection('tx_cal_event');
395
        $q = $db->createQueryBuilder();
396
397
        $variables = [
398
            'table' => 'tx_cal_event',
399
            'fieldnames' => ['image', 'attachment'],
400
            'dbQueries' => $dbQueries,
401
            'calIds' => $calIds,
402
        ];
403
404
        // select all not migrated entries
405
        $fieldnames = 'fieldname = \'' . implode('\' OR fieldname = \'', $variables['fieldnames']) . '\'';
406
        $selectWhere = 'tablenames = \'' . $variables['table'] . '\' AND (' . $fieldnames . ')';
407
        $selectWhere .= ' AND NOT EXISTS (SELECT NULL FROM sys_file_reference sfr2 WHERE sfr2.import_id = CONCAT(\'' . self::IMPORT_PREFIX . '\', sfr1.uid))';
408
409
        $q->select('*')
410
            ->from('sys_file_reference', 'sfr1')
411
            ->where($selectWhere);
412
413
        $dbQueries[] = $q->getSQL();
414
        $selectResults = $q->execute()->fetchAll();
415
416
        $variables = [
417
            'table' => self::EVENT_TABLE,
418
            'fieldnames' => $variables['fieldnames'],
419
            'dbQueries' => $dbQueries,
420
            'calIds' => $calIds,
421
            'selectResults' => $selectResults,
422
        ];
423
424
        // create new entry with import_id
425
        $db = HelperUtility::getDatabaseConnection('sys_file_reference');
426
        foreach ($variables['selectResults'] as $selectResult) {
427
            $selectResult['tablenames'] = $variables['table'];
428
            $selectResult['import_id'] = self::IMPORT_PREFIX . $selectResult['uid'];
429
            $selectResult['fieldname'] = ('image' === $selectResult['fieldname']) ? 'images' : 'downloads';
430
            unset($selectResult['uid_foreign'], $selectResult['uid']);
431
432
            $q = $db->createQueryBuilder();
433
            $q->insert('sys_file_reference')->values($selectResult);
434
435
            $dbQueries[] = $q->getSQL();
436
437
            $q->execute();
438
        }
439
    }
440
441
    /**
442
     * Link the Events to the migrated Categories.
443
     * This build up the 'sys_category_record_mm' table on base of the 'tx_cal_event_category_mm' table.
444
     *
445
     * @param       $calIds
446
     * @param array $dbQueries
447
     * @param array $customMessages
448
     */
449
    public function performLinkEventToCategory($calIds, &$dbQueries, &$customMessages)
450
    {
451
        $table = 'tx_cal_event_category_mm';
452
453
        $db = HelperUtility::getDatabaseConnection($table);
454
        $q = $db->createQueryBuilder();
455
456
        $q->select('*')->from($table);
457
        $dbQueries[] = $q->getSQL();
458
459
        $selectResults = $q->execute()->fetchAll();
460
461
        $variables = [
462
            'tablenames' => self::EVENT_TABLE,
463
            'fieldname' => 'categories',
464
            'dbQueries' => $dbQueries,
465
        ];
466
467
        $dispatcher = HelperUtility::getSignalSlotDispatcher();
468
        $variables = $dispatcher->dispatch(__CLASS__, __FUNCTION__, $variables);
469
470
        foreach ($selectResults as $mm) {
471
            $eventUid = (int)$this->getCalendarizeEventUid(self::IMPORT_PREFIX . $mm['uid_local'], $dbQueries, $customMessages);
472
            $categoryUid = (int)$this->getCalendarizeCategoryUid(
473
                self::IMPORT_PREFIX . $mm['uid_foreign'],
474
                $dbQueries,
475
                $customMessages
476
            );
477
478
            if (0 !== $eventUid && 0 !== $categoryUid) {
479
                $insertValues = [
480
                    'uid_local' => $categoryUid,
481
                    'uid_foreign' => $eventUid,
482
                    'tablenames' => $variables['tablenames'],
483
                    'fieldname' => $variables['fieldname'],
484
                ];
485
486
                $q = $db->createQueryBuilder();
487
                $q->insert($table)->values($insertValues);
488
                $dbQueries[] = $q->getSQL();
489
490
                $q->execute();
491
            }
492
        }
493
    }
494
495
    /**
496
     * Link the Events to the migrated categories.
497
     *
498
     * This uses the existing 'sys_category_record_mm' table which links tx_cal_event to sys_category.
499
     * The fields must be updated to use tx_calendarize_domain_model_event instead.
500
     * Additionally, the uid_foreign must be updated to point to the new event uid.
501
     *
502
     * Before: tablenames='tx_cal_event', fieldname='category_id'
503
     * After: tablenames='tx_calendarize_domain_model_event', fieldname='categories'
504
     *
505
     * @param       $calIds
506
     * @param array $dbQueries
507
     * @param array $customMessages
508
     */
509
    public function performLinkEventToSysCategory($calIds, &$dbQueries, &$customMessages)
510
    {
511
        $table = 'sys_category_record_mm';
512
513
        $db = HelperUtility::getDatabaseConnection($table);
514
        $q = $db->createQueryBuilder();
515
516
        $q->select('uid_foreign')->from($table)
517
            ->where(
518
                $q->expr()->eq('tablenames', $q->createNamedParameter('tx_cal_event')),
519
                $q->expr()->eq('fieldname', $q->createNamedParameter('category_id')),
520
                $q->expr()->neq('uid_local', $q->createNamedParameter(0, \PDO::PARAM_INT)),
521
                $q->expr()->neq('uid_foreign', $q->createNamedParameter(0, \PDO::PARAM_INT))
522
            )->groupBy('uid_foreign');
523
524
        $selectResults = $q->execute()->fetchAll();
525
526
        $variables = [
527
            'tablenames' => self::EVENT_TABLE,
528
            'fieldname' => 'categories'
529
        ];
530
531
        $dispatcher = HelperUtility::getSignalSlotDispatcher();
532
        $variables = $dispatcher->dispatch(__CLASS__, __FUNCTION__, $variables);
533
534
        foreach ($selectResults as $mm) {
535
            $eventUidOld = (int) $mm['uid_foreign'];
536
            // event id is in uid_foreign
537
            $eventUid = (int)$this->getCalendarizeEventUid(self::IMPORT_PREFIX . $eventUidOld, $dbQueries, $customMessages);
538
539
            $q = $db->createQueryBuilder();
540
            if ($eventUid !== 0) {
541
                $q->update($table)
542
                    ->set('tablenames', $variables['tablenames'])
543
                    ->set('fieldname', $variables['fieldname'])
544
                    ->set('uid_foreign', $eventUid)
545
                    ->where(
546
                        $q->expr()->eq('uid_foreign', $q->createNamedParameter($eventUidOld, \PDO::PARAM_INT)),
547
                        $q->expr()->eq('tablenames', $q->createNamedParameter('tx_cal_event')),
548
                        $q->expr()->eq('fieldname', $q->createNamedParameter('category_id'))
549
                    )->execute();
550
            } else {
551
                $q->delete($table)
552
                    ->where(
553
                        $q->expr()->eq('uid_foreign', $q->createNamedParameter($eventUid, \PDO::PARAM_INT)),
554
                        $q->expr()->eq('tablenames', $q->createNamedParameter('tx_cal_event')),
555
                        $q->expr()->eq('fieldname', $q->createNamedParameter('category_id'))
556
                    )
557
                    ->execute();
558
            }
559
        }
560
561
        // delete remaining entries with insufficient values (e.g. uid_foreign=0)
562
        $q = $db->createQueryBuilder();
563
        $q->delete($table)
564
            ->where(
565
                $q->expr()->eq('tablenames', $q->createNamedParameter('tx_cal_event')),
566
                $q->expr()->orX(
567
                    $q->expr()->eq('fieldname', $q->createNamedParameter('')),
568
                    $q->expr()->eq('uid_local', $q->createNamedParameter(0, \PDO::PARAM_INT)),
569
                    $q->expr()->eq('uid_foreign', $q->createNamedParameter(0, \PDO::PARAM_INT))
570
                )
571
            )->execute();
572
    }
573
574
    /**
575
     * Update event with configuration.
576
     *
577
     * @param $eventImportId
578
     * @param $configuration
579
     * @param $dbQueries
580
     * @param $customMessages
581
     *
582
     * @return array
583
     */
584
    protected function updateEventWithConfiguration($eventImportId, $configuration, &$dbQueries, &$customMessages)
585
    {
586
        $db = HelperUtility::getDatabaseConnection(self::CONFIGURATION_TABLE);
587
588
        $configurationRow = $this->findEventExcludeConfiguration($eventImportId, $dbQueries, $customMessages);
589
        if ($configurationRow) {
590
            $configurationRow['groups'] = $this->addValueToCsv($configurationRow['groups'], $configuration['groups']);
591
592
            unset($configurationRow['uid']);
593
594
            $q = HelperUtility::getDatabaseConnection(self::CONFIGURATION_GROUP_TABLE)->createQueryBuilder();
595
            $q->update(self::CONFIGURATION_GROUP_TABLE)
596
                ->where('uid', $q->createNamedParameter((int)$configuration['uid'], \PDO::PARAM_INT));
597
            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...
598
                $q->set($key, $value);
599
            }
600
601
            $dbQueries[] = $q->getSQL();
602
            $results = $q->execute();
603
        } else {
604
            $q = $db->createQueryBuilder();
605
            $q->insert(self::CONFIGURATION_TABLE)->values($configuration);
606
            $dbQueries[] = $q->getSQL();
607
608
            $configurationId = $db->lastInsertId(self::CONFIGURATION_TABLE);
609
610
            $results = $this->addConfigurationIdToEvent($eventImportId, $configurationId, $dbQueries, $customMessages);
611
        }
612
613
        return $results;
614
    }
615
616
    /**
617
     * Add Value to CSV.
618
     *
619
     * @param string $csv
620
     * @param string $value
621
     *
622
     * @return string
623
     */
624
    protected function addValueToCsv($csv, $value)
625
    {
626
        $csvArray = GeneralUtility::trimExplode(',', $csv);
627
628
        // check for doubles
629
        $values = array_flip($csvArray);
630
        if (isset($values[$value])) {
631
            return $csv;
632
        }
633
        $csvArray[] = $value;
634
        $csv = implode(',', $csvArray);
635
636
        return $csv;
637
    }
638
639
    /**
640
     * Add configuration ID to event.
641
     *
642
     * @param string $eventImportId
643
     * @param int    $configurationId
644
     * @param array  $dbQueries
645
     * @param array  $customMessages
646
     *
647
     * @return array|bool
648
     */
649
    protected function addConfigurationIdToEvent($eventImportId, $configurationId, &$dbQueries, &$customMessages)
650
    {
651
        $event = $this->findEventByImportId($eventImportId, $dbQueries, $customMessages);
652
        if (!$event) {
653
            return false;
654
        }
655
656
        $event['calendarize'] = $this->addValueToCsv($event['calendarize'], $configurationId);
657
658
        return $this->updateEvent($event['uid'], $event, $dbQueries, $customMessages);
659
    }
660
661
    /**
662
     * Update event.
663
     *
664
     * @param int   $eventId
665
     * @param array $values
666
     * @param array $dbQueries
667
     * @param array $customMessages
668
     *
669
     * @return array
670
     */
671
    protected function updateEvent($eventId, $values, &$dbQueries, &$customMessages)
672
    {
673
        $db = HelperUtility::getDatabaseConnection(self::EVENT_TABLE);
674
        $q = $db->createQueryBuilder();
675
676
        $variables = [
677
            'table' => self::EVENT_TABLE,
678
            'eventId' => (int)$eventId,
679
            'values' => $values,
680
            'dbQueries' => $dbQueries,
681
        ];
682
683
        $dispatcher = HelperUtility::getSignalSlotDispatcher();
684
        $variables = $dispatcher->dispatch(__CLASS__, __FUNCTION__, $variables);
685
686
        $q->update($variables['table'])
687
            ->where(
688
                $q->expr()->eq('uid', $q->createNamedParameter((int)$eventId, \PDO::PARAM_INT))
689
            );
690
        foreach ($variables['values'] as $key => $value) {
691
            $q->set($key, $value);
692
        }
693
694
        unset($values['uid']);
695
696
        $dbQueries[] = $q->getSQL();
697
698
        return $q->execute()->fetchAll();
699
    }
700
701
    /**
702
     * Find event by import ID.
703
     *
704
     * @param $eventImportId
705
     * @param $dbQueries
706
     * @param $customMessages
707
     *
708
     * @return array|bool
709
     */
710
    protected function findEventByImportId($eventImportId, &$dbQueries, &$customMessages)
711
    {
712
        $db = HelperUtility::getDatabaseConnection(self::EVENT_TABLE);
713
        $q = $db->createQueryBuilder();
714
715
        $variables = [
716
            'table' => self::EVENT_TABLE,
717
            'dbQueries' => $dbQueries,
718
            'eventImportId' => $eventImportId,
719
        ];
720
721
        $dispatcher = HelperUtility::getSignalSlotDispatcher();
722
        $variables = $dispatcher->dispatch(__CLASS__, __FUNCTION__, $variables);
723
724
        $q->select('*')->from($variables['table'])
725
            ->where(
726
                $q->expr()->eq('import_id', $q->createNamedParameter($eventImportId))
727
            );
728
729
        $dbQueries[] = $q->getSQL();
730
731
        return $q->execute()->fetchAll();
732
    }
733
734
    /**
735
     * Find event exclude configuration.
736
     *
737
     * @param string $eventImportId
738
     * @param array  $dbQueries
739
     * @param array  $customMessages
740
     *
741
     * @return array|bool
742
     */
743
    protected function findEventExcludeConfiguration($eventImportId, &$dbQueries, &$customMessages)
744
    {
745
        $event = $this->findEventByImportId($eventImportId, $dbQueries, $customMessages);
746
747
        if (!$event) {
748
            return false;
749
        }
750
751
        $variables = [
752
            'table' => self::CONFIGURATION_TABLE,
753
            'dbQueries' => $dbQueries,
754
            'event' => $event,
755
        ];
756
757
        $db = HelperUtility::getDatabaseConnection($variables['table']);
758
        $q = $db->createQueryBuilder();
759
760
        $q->select('*')
761
            ->from($variables['table'])
762
            ->where(
763
                $q->expr()->andX(
764
                    $q->expr()->eq('type', 'group'),
765
                    $q->expr()->eq('handling', 'exclude'),
766
                    $q->expr()->in('uid', $variables['event']['calendarize'])
767
                )
768
            );
769
770
        $dbQueries[] = $q->getSQL();
771
772
        return $q->execute()->fetchAll();
773
    }
774
775
    /**
776
     * Get exception configuration for exception group.
777
     *
778
     * @param       $groupId
779
     * @param array $dbQueries
780
     *
781
     * @return string
782
     */
783
    protected function getExceptionConfigurationForExceptionGroup($groupId, &$dbQueries)
784
    {
785
        $recordIds = [];
786
        $variables = [
787
            'table' => 'tx_cal_exception_event_group_mm',
788
            'dbQueries' => $dbQueries,
789
        ];
790
791
        $db = HelperUtility::getDatabaseConnection($variables['table']);
792
        $q = $db->createQueryBuilder();
793
794
        $q->select('*')
795
            ->from($variables['table'])
796
            ->where('uid_local', $q->createNamedParameter((int)$groupId, \PDO::PARAM_INT));
797
798
        $dbQueries[] = $q->getSQL();
799
800
        $mmResults = $q->execute()->fetchAll();
801
        foreach ($mmResults as $mmResult) {
802
            $variables = [
803
                'table' => 'tx_cal_exception_event',
804
                'dbQueries' => $dbQueries,
805
            ];
806
807
            $q = $db->createQueryBuilder();
808
            $q->select('*')
809
                ->from($variables['table'])
810
                ->where(
811
                    $q->expr()->eq('uid', $q->createNamedParameter((int)$mmResult['uid_foreign'], \PDO::PARAM_INT))
812
                );
813
814
            $dbQueries[] = $q->getSQL();
815
816
            $selectResults = $q->execute()->fetchAll();
817
818
            foreach ($selectResults as $selectResult) {
819
                $configurationRow = [
820
                    'pid' => $selectResult['pid'],
821
                    'tstamp' => $selectResult['tstamp'],
822
                    'crdate' => $selectResult['crdate'],
823
                    'type' => 'time',
824
                    'handling' => 'include',
825
                    'start_date' => (string)$selectResult['start_date'] ?: null,
826
                    'end_date' => (string)$selectResult['end_date'] ?: null,
827
                    'start_time' => (int)$selectResult['start_time'],
828
                    'end_time' => (int)$selectResult['end_time'],
829
                    'all_day' => (null === $selectResult['start_time'] && null === $selectResult['end_time']) ? 1 : 0,
830
                    'frequency' => $this->mapFrequency($selectResult['freq']),
831
                    'till_date' => (string)$selectResult['until'] ?: null,
832
                    'counter_amount' => (int)$selectResult['cnt'],
833
                    'counter_interval' => (int)$selectResult['interval'],
834
                    'import_id' => self::IMPORT_PREFIX . $selectResult['uid'],
835
                ];
836
837
                $variables = [
838
                    'table' => self::CONFIGURATION_TABLE,
839
                    'configurationRow' => $configurationRow,
840
                ];
841
842
                $dispatcher = HelperUtility::getSignalSlotDispatcher();
843
                $variables = $dispatcher->dispatch(__CLASS__, __FUNCTION__ . 'PreInsert', $variables);
844
845
                $q = $db->createQueryBuilder();
846
                $q->insert($variables['table'])->values($variables['configurationRow']);
847
848
                $dbQueries[] = $q->getSQL();
849
850
                $q->execute();
851
852
                $recordIds[] = $db->lastInsertId($variables['table']);
853
            }
854
        }
855
856
        return implode(',', $recordIds);
857
    }
858
859
    /**
860
     * Map frequency.
861
     *
862
     * @param string $calFrequency
863
     *
864
     * @return string
865
     */
866
    protected function mapFrequency($calFrequency)
867
    {
868
        $freq = [
869
            'none' => null,
870
            'day' => 'daily',
871
            'week' => 'weekly',
872
            'month' => 'monthly',
873
            'year' => 'yearly',
874
        ];
875
876
        if (!isset($freq[$calFrequency])) {
877
            return '';
878
        }
879
880
        return $freq[$calFrequency];
881
    }
882
883
    /**
884
     * Migrate the 'tx_cal_category' table to the 'sys_category' table.
885
     *
886
     * @param       $calIds
887
     * @param array $dbQueries
888
     * @param       $customMessages
889
     */
890
    protected function performSysCategoryUpdate($calIds, array &$dbQueries, &$customMessages)
891
    {
892
        // first migrate from tx_cal_category to sys_category
893
        $variables = [
894
            'table' => 'tx_cal_category',
895
            'dbQueries' => $dbQueries,
896
            'calIds' => $calIds,
897
        ];
898
899
        $db = HelperUtility::getDatabaseConnection($variables['table']);
900
        $q = $db->createQueryBuilder();
901
        $q->getRestrictions()
902
            ->removeAll()
903
            ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
904
905
        $q->select('*')
906
            ->from($variables['table']);
907
908
        $dbQueries[] = $q->getSQL();
909
910
        $selectResults = $q->execute()->fetchAll();
911
912
        foreach ($selectResults as $category) {
913
            $sysCategoryRecord = [
914
                'pid' => $category['pid'],
915
                'tstamp' => $category['tstamp'],
916
                'crdate' => $category['crdate'],
917
                'cruser_id' => $category['cruser_id'],
918
                'deleted' => $category['deleted'],
919
                'hidden' => $category['hidden'],
920
                'starttime' => $category['starttime'],
921
                'endtime' => $category['endtime'],
922
                'sys_language_uid' => $category['sys_language_uid'],
923
                'l10n_parent' => $category['l18n_parent'],
924
                'title' => $category['title'],
925
                'parent' => (int)$category['parent_category'],
926
                'import_id' => self::IMPORT_PREFIX . (int)$category['uid'],
927
                'sorting' => $category['sorting'],
928
            ];
929
930
            $q = $db->createQueryBuilder();
931
            $q->insert('sys_category')->values($sysCategoryRecord);
932
            $dbQueries[] = $q->getSQL();
933
934
            $q->execute();
935
        }
936
937
        // second rewrite the tree
938
        $variables = [
939
            'table' => 'sys_category',
940
            'dbQueries' => $dbQueries,
941
            'calIds' => $calIds,
942
        ];
943
944
        $q = $db->createQueryBuilder();
945
946
        $q->select('*')
947
            ->from($variables['table'])
948
            ->where(
949
                $q->expr()->neq('import_id', $q->createNamedParameter(''))
950
            );
951
952
        $dbQueries[] = $q->getSQL();
953
        $selectResults = $q->execute()->fetchAll();
954
955
        foreach ($selectResults as $sysCategory) {
956
            // update parent, because there are just the old uids
957
            $q = $db->createQueryBuilder();
958
            $q->update('sys_category')
959
                ->where(
960
                    $q->expr()->eq('uid', $q->createNamedParameter((int)$sysCategory['uid'], \PDO::PARAM_INT))
961
                )->set(
962
                    'parent',
963
                    $this->getSysCategoryParentUid(self::IMPORT_PREFIX . (int)$sysCategory['parent'])
964
                );
965
966
            $dbQueries[] = $q->getSQL();
967
968
            $q->execute();
969
        }
970
    }
971
972
    /**
973
     * Return the parentUid for the 'sys_category' entry on base of the import_id.
974
     *
975
     * @param string $importId
976
     *
977
     * @return int
978
     */
979
    protected function getSysCategoryParentUid($importId)
980
    {
981
        $table = 'sys_category';
982
        $db = HelperUtility::getDatabaseConnection($table);
983
        $q = $db->createQueryBuilder();
984
985
        $q->select('uid')
986
            ->from($table)
987
            ->where(
988
                $q->expr()->eq('import_id', $q->createNamedParameter($importId))
989
            );
990
991
        $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...
992
993
        $result = $q->execute()->fetchAll();
994
995
        return (int)$result[0]['uid'];
996
    }
997
998
    /**
999
     * Get the event uid on base of the given import_id.
1000
     * The import_id is the original tx_cal_event id prefixed with the IMPORT_PREFIX.
1001
     *
1002
     * @param string $importId
1003
     * @param array  $dbQueries
1004
     * @param array  $customMessages
1005
     *
1006
     * @return int
1007
     */
1008
    protected function getCalendarizeEventUid($importId, &$dbQueries, &$customMessages)
1009
    {
1010
        $variables = [
1011
            'table' => self::EVENT_TABLE,
1012
            'dbQueries' => $dbQueries,
1013
        ];
1014
1015
        $q = HelperUtility::getDatabaseConnection($variables['table'])->createQueryBuilder();
1016
1017
        $dispatcher = HelperUtility::getSignalSlotDispatcher();
1018
        $variables = $dispatcher->dispatch(__CLASS__, __FUNCTION__, $variables);
1019
1020
        // also get restricted (e.g. hidden) records, otherwise retrieving event uid for
1021
        // restricted records will always return 0
1022
        $q->getRestrictions()
1023
            ->removeAll()
1024
            ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
1025
        $q->select('uid')
1026
            ->from($variables['table'])
1027
            ->where(
1028
                $q->expr()->eq('import_id', $q->createNamedParameter($importId))
1029
            );
1030
1031
        $dbQueries[] = $q->getSQL();
1032
1033
        $result = $q->execute()->fetchAll();
1034
1035
        return (int)$result[0]['uid'];
1036
    }
1037
1038
    /**
1039
     * Get the sys_category uid on base of the given import_id.
1040
     * The import_id is the original tx_cal_category id prefixed with the IMPORT_PREFIX.
1041
     *
1042
     * @see CalMigrationUpdate::IMPORT_PREFIX
1043
     *
1044
     * @param string $importId
1045
     * @param array  $dbQueries
1046
     * @param array  $customMessages
1047
     *
1048
     * @return int
1049
     */
1050
    protected function getCalendarizeCategoryUid($importId, &$dbQueries, &$customMessages)
1051
    {
1052
        $variables = [
1053
            'table' => 'sys_category',
1054
            'dbQueries' => $dbQueries,
1055
        ];
1056
1057
        $q = HelperUtility::getDatabaseConnection($variables['table'])->createQueryBuilder();
1058
1059
        $dispatcher = HelperUtility::getSignalSlotDispatcher();
1060
        $variables = $dispatcher->dispatch(__CLASS__, __FUNCTION__, $variables);
1061
1062
        $q->select('uid')
1063
            ->from($variables['table'])
1064
            ->where(
1065
                $q->expr()->eq('import_id', $q->createNamedParameter($importId))
1066
            );
1067
1068
        $dbQueries[] = $q->getSQL();
1069
1070
        $result = $q->execute()->fetchAll();
1071
1072
        return (int)$result[0]['uid'];
1073
    }
1074
1075
    /**
1076
     * Build configurations.
1077
     *
1078
     * @param $calEventRow
1079
     * @param $dbQueries
1080
     *
1081
     * @return int
1082
     */
1083
    protected function buildConfigurations($calEventRow, &$dbQueries)
1084
    {
1085
        $configurationRow = [
1086
            'pid' => $calEventRow['pid'],
1087
            'tstamp' => $calEventRow['tstamp'],
1088
            'crdate' => $calEventRow['crdate'],
1089
            'type' => 'time',
1090
            'handling' => 'include',
1091
            'start_date' => (string)$calEventRow['start_date'] ?: null,
1092
            'end_date' => (string)$calEventRow['end_date'] ?: null,
1093
            'start_time' => (int)$calEventRow['start_time'],
1094
            'end_time' => (int)$calEventRow['end_time'],
1095
            'all_day' => $calEventRow['allday'],
1096
            'frequency' => $this->mapFrequency($calEventRow['freq']),
1097
            'till_date' => (string)$calEventRow['until'] ?: null,
1098
            'counter_amount' => (int)$calEventRow['cnt'],
1099
            'counter_interval' => (int)$calEventRow['interval'],
1100
        ];
1101
1102
        $variables = [
1103
            'table' => self::CONFIGURATION_TABLE,
1104
            'configurationRow' => $configurationRow,
1105
            'calEventRow' => $calEventRow,
1106
            'dbQueries' => $dbQueries,
1107
        ];
1108
1109
        $db = HelperUtility::getDatabaseConnection($variables['table']);
1110
        $q = $db->createQueryBuilder();
1111
1112
        $dispatcher = HelperUtility::getSignalSlotDispatcher();
1113
        $variables = $dispatcher->dispatch(__CLASS__, __FUNCTION__ . 'PreInsert', $variables);
1114
1115
        $q->insert($variables['table'])
1116
            ->values($variables['configurationRow']);
1117
1118
        $dbQueries[] = $q->getSQL();
1119
        $q->execute();
1120
        $recordId = $db->lastInsertId($variables['table']);
1121
1122
        $variables = [
1123
            'table' => $variables['table'],
1124
            'configurationRow' => $configurationRow,
1125
            'calEventRow' => $calEventRow,
1126
            'recordId' => $recordId,
1127
            'dbQueries' => $dbQueries,
1128
        ];
1129
1130
        $dispatcher = HelperUtility::getSignalSlotDispatcher();
1131
        $variables = $dispatcher->dispatch(__CLASS__, __FUNCTION__ . 'PostInsert', $variables);
1132
1133
        return $variables['recordId'];
1134
    }
1135
1136
    /**
1137
     * Get the non migrated cal IDs.
1138
     *
1139
     * @return array
1140
     */
1141
    protected function getNonMigratedCalIds()
1142
    {
1143
        $checkImportIds = [];
1144
        $nonMigrated = [];
1145
1146
        $table = 'tx_cal_event';
1147
        $q = HelperUtility::getDatabaseConnection($table)->createQueryBuilder();
1148
        $q->getRestrictions()
1149
            ->removeAll()
1150
            ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
1151
1152
        $events = $q->select('uid')
1153
            ->from($table)
1154
            ->execute()
1155
            ->fetchAll();
1156
1157
        foreach ($events as $event) {
1158
            $checkImportIds[] = '"' . self::IMPORT_PREFIX . $event['uid'] . '"';
1159
            $nonMigrated[(int)$event['uid']] = (int)$event['uid'];
1160
        }
1161
1162
        $countOriginal = \count($checkImportIds);
1163
        if (0 === $countOriginal) {
1164
            return [];
1165
        }
1166
1167
        $variables = [
1168
            'table' => self::EVENT_TABLE,
1169
        ];
1170
1171
        $dispatcher = HelperUtility::getSignalSlotDispatcher();
1172
        $variables = $dispatcher->dispatch(__CLASS__, __FUNCTION__ . 'PreSelect', $variables);
1173
1174
        $q = HelperUtility::getDatabaseConnection($variables['table'])->createQueryBuilder();
1175
1176
        $migratedRows = $q->select('uid', 'import_id')
1177
            ->from($variables['table'])
1178
            ->where(
1179
                $q->expr()->in('import_id', $checkImportIds)
1180
            )
1181
            ->execute()
1182
            ->fetchAll();
1183
1184
        foreach ($migratedRows as $migratedRow) {
1185
            $importId = (int)str_replace(self::IMPORT_PREFIX, '', $migratedRow['import_id']);
1186
            if (isset($nonMigrated[$importId])) {
1187
                unset($nonMigrated[$importId]);
1188
            }
1189
        }
1190
1191
        $variables = [
1192
            'table' => $variables['table'],
1193
            'migratedRows' => $migratedRows,
1194
            'nonMigrated' => $nonMigrated,
1195
        ];
1196
1197
        $dispatcher = HelperUtility::getSignalSlotDispatcher();
1198
        $variables = $dispatcher->dispatch(__CLASS__, __FUNCTION__ . 'ReadyParsed', $variables);
1199
1200
        return $variables['nonMigrated'];
1201
    }
1202
1203
    public function updateNecessary(): bool
1204
    {
1205
        $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
1206
        $connection = $connectionPool->getConnectionByName(ConnectionPool::DEFAULT_CONNECTION_NAME);
1207
        $dbSchema = $connection->getSchemaManager()->createSchema();
1208
1209
        $tableNames = array_map(function ($table) {
1210
            return $table->getName();
1211
        }, $dbSchema->getTables());
1212
1213
        return \in_array('tx_cal_event', $tableNames);
1214
    }
1215
1216
    public function getPrerequisites(): array
1217
    {
1218
        return [
1219
            DatabaseUpdatedPrerequisite::class,
1220
        ];
1221
    }
1222
}
1223