RemoteServer::getRowDetails()   F
last analyzed

Complexity

Conditions 28
Paths 5184

Size

Total Lines 195
Code Lines 135

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 135
c 1
b 0
f 0
dl 0
loc 195
rs 0
cc 28
nc 5184
nop 1

How to fix   Long Method    Complexity   

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
 * This file is part of the TYPO3 CMS project.
5
 *
6
 * It is free software; you can redistribute it and/or modify it under
7
 * the terms of the GNU General Public License, either version 2
8
 * of the License, or any later version.
9
 *
10
 * For the full copyright and license information, please read the
11
 * LICENSE.txt file that was distributed with this source code.
12
 *
13
 * The TYPO3 project - inspiring people to share!
14
 */
15
16
namespace TYPO3\CMS\Workspaces\Controller\Remote;
17
18
use TYPO3\CMS\Backend\Backend\Avatar\Avatar;
19
use TYPO3\CMS\Backend\Form\FormDataCompiler;
20
use TYPO3\CMS\Backend\Form\FormDataGroup\TcaDatabaseRecord;
21
use TYPO3\CMS\Backend\Utility\BackendUtility;
22
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
23
use TYPO3\CMS\Core\Database\ConnectionPool;
24
use TYPO3\CMS\Core\Imaging\Icon;
25
use TYPO3\CMS\Core\Imaging\IconFactory;
26
use TYPO3\CMS\Core\Localization\LanguageService;
27
use TYPO3\CMS\Core\Resource\FileReference;
28
use TYPO3\CMS\Core\Resource\ProcessedFile;
29
use TYPO3\CMS\Core\SysLog\Action\Database as DatabaseAction;
30
use TYPO3\CMS\Core\Utility\DiffUtility;
31
use TYPO3\CMS\Core\Utility\GeneralUtility;
32
use TYPO3\CMS\Core\Utility\MathUtility;
33
use TYPO3\CMS\Core\Utility\PathUtility;
34
use TYPO3\CMS\Core\Utility\StringUtility;
35
use TYPO3\CMS\Core\Versioning\VersionState;
36
use TYPO3\CMS\Workspaces\Domain\Model\CombinedRecord;
37
use TYPO3\CMS\Workspaces\Service\GridDataService;
38
use TYPO3\CMS\Workspaces\Service\HistoryService;
39
use TYPO3\CMS\Workspaces\Service\IntegrityService;
40
use TYPO3\CMS\Workspaces\Service\StagesService;
41
use TYPO3\CMS\Workspaces\Service\WorkspaceService;
42
43
/**
44
 * Class RemoteServer
45
 * @internal This is a specific Backend Controller implementation and is not considered part of the Public TYPO3 API.
46
 */
47
class RemoteServer
48
{
49
    /**
50
     * @var GridDataService
51
     */
52
    protected $gridDataService;
53
54
    /**
55
     * @var StagesService
56
     */
57
    protected $stagesService;
58
59
    /**
60
     * @var WorkspaceService
61
     */
62
    protected $workspaceService;
63
64
    /**
65
     * @var DiffUtility
66
     */
67
    protected $differenceHandler;
68
69
    public function __construct()
70
    {
71
        $this->workspaceService = GeneralUtility::makeInstance(WorkspaceService::class);
72
        $this->gridDataService = GeneralUtility::makeInstance(GridDataService::class);
73
        $this->stagesService = GeneralUtility::makeInstance(StagesService::class);
74
    }
75
76
    /**
77
     * Checks integrity of elements before performing actions on them.
78
     *
79
     * @param \stdClass $parameters
80
     * @return array
81
     */
82
    public function checkIntegrity(\stdClass $parameters)
83
    {
84
        $integrity = $this->createIntegrityService($this->getAffectedElements($parameters));
85
        $integrity->check();
86
        $response = [
87
            'result' => $integrity->getStatusRepresentation()
88
        ];
89
        return $response;
90
    }
91
92
    /**
93
     * Get List of workspace changes
94
     *
95
     * @param \stdClass $parameter
96
     * @return array $data
97
     */
98
    public function getWorkspaceInfos($parameter)
99
    {
100
        // To avoid too much work we use -1 to indicate that every page is relevant
101
        $pageId = $parameter->id > 0 ? $parameter->id : -1;
102
        if (!isset($parameter->language) || !MathUtility::canBeInterpretedAsInteger($parameter->language)) {
103
            $parameter->language = null;
104
        }
105
        $versions = $this->workspaceService->selectVersionsInWorkspace(
106
            $this->getCurrentWorkspace(),
107
            -99,
108
            $pageId,
109
            $parameter->depth,
110
            'tables_select',
111
            $parameter->language
112
        );
113
        $data = $this->gridDataService->generateGridListFromVersions($versions, $parameter, $this->getCurrentWorkspace());
114
        return $data;
115
    }
116
117
    /**
118
     * Get List of available workspace actions
119
     *
120
     * @return array $data
121
     */
122
    public function getStageActions()
123
    {
124
        $stages = $this->stagesService->getStagesForWSUser();
125
        $data = [
126
            'total' => count($stages),
127
            'data' => $stages
128
        ];
129
        return $data;
130
    }
131
132
    /**
133
     * Fetch further information to current selected workspace record.
134
     *
135
     * @param \stdClass $parameter
136
     * @return array $data
137
     */
138
    public function getRowDetails($parameter)
139
    {
140
        $diffReturnArray = [];
141
        $liveReturnArray = [];
142
        $diffUtility = $this->getDifferenceHandler();
143
        $liveRecord = (array)BackendUtility::getRecord($parameter->table, $parameter->t3ver_oid);
144
        $versionRecord = (array)BackendUtility::getRecord($parameter->table, $parameter->uid);
145
        $versionState = VersionState::cast((int)($versionRecord['t3ver_state'] ?? 0));
146
        $iconFactory = GeneralUtility::makeInstance(IconFactory::class);
147
        $icon_Live = $iconFactory->getIconForRecord($parameter->table, $liveRecord, Icon::SIZE_SMALL)->render();
148
        $icon_Workspace = $iconFactory->getIconForRecord($parameter->table, $versionRecord, Icon::SIZE_SMALL)->render();
149
        $stagePosition = $this->stagesService->getPositionOfCurrentStage($parameter->stage);
150
        $fieldsOfRecords = array_keys($liveRecord);
151
        $isNewOrDeletePlaceholder = $versionState->equals(VersionState::NEW_PLACEHOLDER) || $versionState->equals(VersionState::DELETE_PLACEHOLDER);
152
        $suitableFields = ($isNewOrDeletePlaceholder && ($parameter->filterFields ?? false)) ? array_flip($this->getSuitableFields($parameter->table, $parameter->t3ver_oid)) : [];
153
        foreach ($fieldsOfRecords as $fieldName) {
154
            if (
155
                empty($GLOBALS['TCA'][$parameter->table]['columns'][$fieldName]['config'])
156
            ) {
157
                continue;
158
            }
159
            // Disable internal fields
160
            if (($GLOBALS['TCA'][$parameter->table]['ctrl']['transOrigDiffSourceField'] ?? '') === $fieldName) {
161
                continue;
162
            }
163
            if (($GLOBALS['TCA'][$parameter->table]['ctrl']['origUid'] ?? '') === $fieldName) {
164
                continue;
165
            }
166
            // Get the field's label. If not available, use the field name
167
            $fieldTitle = $this->getLanguageService()->sL(BackendUtility::getItemLabel($parameter->table, $fieldName));
168
            if (empty($fieldTitle)) {
169
                $fieldTitle = $fieldName;
170
            }
171
            // Gets the TCA configuration for the current field
172
            $configuration = $GLOBALS['TCA'][$parameter->table]['columns'][$fieldName]['config'];
173
            // check for exclude fields
174
            if ($this->getBackendUser()->isAdmin() || $GLOBALS['TCA'][$parameter->table]['columns'][$fieldName]['exclude'] == 0 || GeneralUtility::inList($this->getBackendUser()->groupData['non_exclude_fields'], $parameter->table . ':' . $fieldName)) {
175
                // call diff class only if there is a difference
176
                if ($configuration['type'] === 'inline' && $configuration['foreign_table'] === 'sys_file_reference') {
177
                    $useThumbnails = false;
178
                    if (!empty($configuration['overrideChildTca']['columns']['uid_local']['config']['appearance']['elementBrowserAllowed']) && !empty($GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'])) {
179
                        $fileExtensions = GeneralUtility::trimExplode(',', $GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'], true);
180
                        $allowedExtensions = GeneralUtility::trimExplode(',', $configuration['overrideChildTca']['columns']['uid_local']['config']['appearance']['elementBrowserAllowed'], true);
181
                        $differentExtensions = array_diff($allowedExtensions, $fileExtensions);
182
                        $useThumbnails = empty($differentExtensions);
183
                    }
184
185
                    $liveFileReferences = (array)BackendUtility::resolveFileReferences(
186
                        $parameter->table,
187
                        $fieldName,
188
                        $liveRecord,
189
                        0
190
                    );
191
                    $versionFileReferences = (array)BackendUtility::resolveFileReferences(
192
                        $parameter->table,
193
                        $fieldName,
194
                        $versionRecord,
195
                        $this->getCurrentWorkspace()
196
                    );
197
                    $fileReferenceDifferences = $this->prepareFileReferenceDifferences(
198
                        $liveFileReferences,
199
                        $versionFileReferences,
200
                        $useThumbnails
201
                    );
202
203
                    if ($fileReferenceDifferences === null) {
204
                        continue;
205
                    }
206
207
                    $diffReturnArray[] = [
208
                        'field' => $fieldName,
209
                        'label' => $fieldTitle,
210
                        'content' => $fileReferenceDifferences['differences']
211
                    ];
212
                    $liveReturnArray[] = [
213
                        'field' => $fieldName,
214
                        'label' => $fieldTitle,
215
                        'content' => $fileReferenceDifferences['live']
216
                    ];
217
                } elseif ($isNewOrDeletePlaceholder && isset($suitableFields[$fieldName])) {
218
                    // If this is a new or delete placeholder, add diff view for all appropriate fields
219
                    $newOrDeleteRecord[$fieldName] = BackendUtility::getProcessedValue(
220
                        $parameter->table,
221
                        $fieldName,
222
                        $liveRecord[$fieldName], // Both (live and version) values are the same
223
                        0,
224
                        true,
225
                        false,
226
                        $liveRecord['uid'] // Relations of new/delete placeholder do always contain the live uid
227
                    ) ?? '';
228
229
                    // Don't add empty fields
230
                    if ($newOrDeleteRecord[$fieldName] === '') {
231
                        continue;
232
                    }
233
234
                    $diffReturnArray[] = [
235
                        'field' => $fieldName,
236
                        'label' => $fieldTitle,
237
                        'content' => $versionState->equals(VersionState::NEW_PLACEHOLDER)
238
                            ? $diffUtility->makeDiffDisplay('', $newOrDeleteRecord[$fieldName])
239
                            : $diffUtility->makeDiffDisplay($newOrDeleteRecord[$fieldName], '')
240
                    ];
241
242
                    // Generally not needed by Core, but let's make it available for further processing in hooks
243
                    $liveReturnArray[] = [
244
                        'field' => $fieldName,
245
                        'label' => $fieldTitle,
246
                        'content' => $newOrDeleteRecord[$fieldName]
247
                    ];
248
                } elseif ((string)$liveRecord[$fieldName] !== (string)$versionRecord[$fieldName]) {
249
                    // Select the human readable values before diff
250
                    $liveRecord[$fieldName] = BackendUtility::getProcessedValue(
251
                        $parameter->table,
252
                        $fieldName,
253
                        $liveRecord[$fieldName],
254
                        0,
255
                        true,
256
                        false,
257
                        $liveRecord['uid']
258
                    );
259
                    $versionRecord[$fieldName] = BackendUtility::getProcessedValue(
260
                        $parameter->table,
261
                        $fieldName,
262
                        $versionRecord[$fieldName],
263
                        0,
264
                        true,
265
                        false,
266
                        $versionRecord['uid']
267
                    );
268
269
                    $diffReturnArray[] = [
270
                        'field' => $fieldName,
271
                        'label' => $fieldTitle,
272
                        'content' => $diffUtility->makeDiffDisplay($liveRecord[$fieldName], $versionRecord[$fieldName])
273
                    ];
274
                    $liveReturnArray[] = [
275
                        'field' => $fieldName,
276
                        'label' => $fieldTitle,
277
                        'content' => $liveRecord[$fieldName]
278
                    ];
279
                }
280
            }
281
        }
282
        // Hook for modifying the difference and live arrays
283
        // (this may be used by custom or dynamically-defined fields)
284
        foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['workspaces']['modifyDifferenceArray'] ?? [] as $className) {
285
            $hookObject = GeneralUtility::makeInstance($className);
286
            if (method_exists($hookObject, 'modifyDifferenceArray')) {
287
                $hookObject->modifyDifferenceArray($parameter, $diffReturnArray, $liveReturnArray, $diffUtility);
288
            }
289
        }
290
        $commentsForRecord = $this->getCommentsForRecord($parameter->uid, $parameter->table);
291
292
        $historyService = GeneralUtility::makeInstance(HistoryService::class);
293
        $history = $historyService->getHistory($parameter->table, $parameter->t3ver_oid);
294
295
        if ($this->stagesService->isPrevStageAllowedForUser($parameter->stage)) {
296
            $prevStage = $this->stagesService->getPrevStage($parameter->stage);
297
            if (isset($prevStage[0])) {
298
                $prevStage = current($prevStage);
0 ignored issues
show
Bug introduced by
It seems like $prevStage can also be of type boolean; however, parameter $array of current() does only seem to accept array|object, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

298
                $prevStage = current(/** @scrutinizer ignore-type */ $prevStage);
Loading history...
299
            }
300
        }
301
        if ($this->stagesService->isNextStageAllowedForUser($parameter->stage)) {
302
            $nextStage = $this->stagesService->getNextStage($parameter->stage);
303
            if (isset($nextStage[0])) {
304
                $nextStage = current($nextStage);
305
            }
306
        }
307
308
        return [
309
            'total' => 1,
310
            'data' => [
311
                [
312
                    // these parts contain HTML (don't escape)
313
                    'diff' => $diffReturnArray,
314
                    'live_record' => $liveReturnArray,
315
                    'icon_Live' => $icon_Live,
316
                    'icon_Workspace' => $icon_Workspace,
317
                    // this part is already escaped in getCommentsForRecord()
318
                    'comments' => $commentsForRecord,
319
                    // escape/sanitize the others
320
                    'path_Live' => htmlspecialchars(BackendUtility::getRecordPath($liveRecord['pid'], '', 999)),
0 ignored issues
show
Bug introduced by
It seems like TYPO3\CMS\Backend\Utilit...Record['pid'], '', 999) can also be of type array<integer,string>; however, parameter $string of htmlspecialchars() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

320
                    'path_Live' => htmlspecialchars(/** @scrutinizer ignore-type */ BackendUtility::getRecordPath($liveRecord['pid'], '', 999)),
Loading history...
321
                    'label_Stage' => htmlspecialchars($this->stagesService->getStageTitle($parameter->stage)),
322
                    'label_PrevStage' => $prevStage ?? false,
323
                    'label_NextStage' => $nextStage ?? false,
324
                    'stage_position' => (int)$stagePosition['position'],
325
                    'stage_count' => (int)$stagePosition['count'],
326
                    'parent' => [
327
                        'table' => htmlspecialchars($parameter->table),
328
                        'uid' => (int)$parameter->uid
329
                    ],
330
                    'history' => [
331
                        'data' => $history,
332
                        'total' => count($history)
333
                    ]
334
                ]
335
            ]
336
        ];
337
    }
338
339
    /**
340
     * Prepares difference view for file references.
341
     *
342
     * @param FileReference[] $liveFileReferences
343
     * @param FileReference[] $versionFileReferences
344
     * @param bool|false $useThumbnails
345
     * @return array|null
346
     */
347
    protected function prepareFileReferenceDifferences(array $liveFileReferences, array $versionFileReferences, $useThumbnails = false)
348
    {
349
        $randomValue = StringUtility::getUniqueId('file');
350
351
        $liveValues = [];
352
        $versionValues = [];
353
        $candidates = [];
354
        $substitutes = [];
355
356
        // Process live references
357
        foreach ($liveFileReferences as $identifier => $liveFileReference) {
358
            $identifierWithRandomValue = $randomValue . '__' . $liveFileReference->getUid() . '__' . $randomValue;
359
            $candidates[$identifierWithRandomValue] = $liveFileReference;
360
            $liveValues[] = $identifierWithRandomValue;
361
        }
362
363
        // Process version references
364
        foreach ($versionFileReferences as $identifier => $versionFileReference) {
365
            $identifierWithRandomValue = $randomValue . '__' . $versionFileReference->getUid() . '__' . $randomValue;
366
            $candidates[$identifierWithRandomValue] = $versionFileReference;
367
            $versionValues[] = $identifierWithRandomValue;
368
        }
369
370
        // Combine values and surround by spaces
371
        // (to reduce the chunks Diff will find)
372
        $liveInformation = ' ' . implode(' ', $liveValues) . ' ';
373
        $versionInformation = ' ' . implode(' ', $versionValues) . ' ';
374
375
        // Return if information has not changed
376
        if ($liveInformation === $versionInformation) {
377
            return null;
378
        }
379
380
        /**
381
         * @var string $identifierWithRandomValue
382
         * @var FileReference $fileReference
383
         */
384
        foreach ($candidates as $identifierWithRandomValue => $fileReference) {
385
            if ($useThumbnails) {
386
                $thumbnailFile = $fileReference->getOriginalFile()->process(
387
                    ProcessedFile::CONTEXT_IMAGEPREVIEW,
388
                    ['width' => 40, 'height' => 40]
389
                );
390
                $thumbnailMarkup = '<img src="' . PathUtility::getAbsoluteWebPath($thumbnailFile->getPublicUrl() ?? '') . '" />';
391
                $substitutes[$identifierWithRandomValue] = $thumbnailMarkup;
392
            } else {
393
                $substitutes[$identifierWithRandomValue] = $fileReference->getPublicUrl();
394
            }
395
        }
396
397
        $differences = $this->getDifferenceHandler()->makeDiffDisplay($liveInformation, $versionInformation);
398
        $liveInformation = str_replace(array_keys($substitutes), array_values($substitutes), trim($liveInformation));
399
        $differences = str_replace(array_keys($substitutes), array_values($substitutes), trim($differences));
400
401
        return [
402
            'live' => $liveInformation,
403
            'differences' => $differences
404
        ];
405
    }
406
407
    /**
408
     * Gets an array with all sys_log entries and their comments for the given record uid and table
409
     *
410
     * @param int $uid uid of changed element to search for in log
411
     * @param string $table Name of the record's table
412
     * @return array
413
     */
414
    public function getCommentsForRecord($uid, $table)
415
    {
416
        $sysLogReturnArray = [];
417
        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_log');
418
419
        $result = $queryBuilder
420
            ->select('log_data', 'tstamp', 'userid')
421
            ->from('sys_log')
422
            ->where(
423
                $queryBuilder->expr()->eq(
424
                    'action',
425
                    $queryBuilder->createNamedParameter(DatabaseAction::UPDATE, \PDO::PARAM_INT)
426
                ),
427
                $queryBuilder->expr()->eq(
428
                    'details_nr',
429
                    $queryBuilder->createNamedParameter(30, \PDO::PARAM_INT)
430
                ),
431
                $queryBuilder->expr()->eq(
432
                    'tablename',
433
                    $queryBuilder->createNamedParameter($table, \PDO::PARAM_STR)
434
                ),
435
                $queryBuilder->expr()->eq(
436
                    'recuid',
437
                    $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT)
438
                )
439
            )
440
            ->orderBy('tstamp', 'DESC')
441
            ->execute();
442
443
        /** @var Avatar $avatar */
444
        $avatar = GeneralUtility::makeInstance(Avatar::class);
445
446
        while ($sysLogRow = $result->fetch()) {
447
            $sysLogEntry = [];
448
            $data = unserialize($sysLogRow['log_data']);
449
            $beUserRecord = BackendUtility::getRecord('be_users', $sysLogRow['userid']);
450
            $sysLogEntry['stage_title'] = htmlspecialchars($this->stagesService->getStageTitle($data['stage']));
451
            $sysLogEntry['user_uid'] = (int)$sysLogRow['userid'];
452
            $sysLogEntry['user_username'] = is_array($beUserRecord) ? htmlspecialchars($beUserRecord['username']) : '';
453
            $sysLogEntry['tstamp'] = htmlspecialchars(BackendUtility::datetime($sysLogRow['tstamp']));
454
            $sysLogEntry['user_comment'] = nl2br(htmlspecialchars($data['comment']));
455
            $sysLogEntry['user_avatar'] = $avatar->render($beUserRecord);
456
            $sysLogReturnArray[] = $sysLogEntry;
457
        }
458
        return $sysLogReturnArray;
459
    }
460
461
    /**
462
     * Gets all available system languages.
463
     *
464
     * @param \stdClass $parameters
465
     * @return array
466
     */
467
    public function getSystemLanguages(\stdClass $parameters)
468
    {
469
        $iconFactory = GeneralUtility::makeInstance(IconFactory::class);
470
        $systemLanguages = [
471
            [
472
                'uid' => 'all',
473
                'title' => $this->getLanguageService()->sL('LLL:EXT:workspaces/Resources/Private/Language/locallang.xlf:language.allLanguages'),
474
                'icon' => $iconFactory->getIcon('empty-empty', Icon::SIZE_SMALL)->render()
475
            ]
476
        ];
477
        foreach ($this->gridDataService->getSystemLanguages($parameters->pageUid ?? 0) as $id => $systemLanguage) {
478
            if ($id < 0) {
479
                continue;
480
            }
481
            $systemLanguages[] = [
482
                'uid' => $id,
483
                'title' => htmlspecialchars($systemLanguage['title']),
484
                'icon' => $iconFactory->getIcon($systemLanguage['flagIcon'], Icon::SIZE_SMALL)->render()
485
            ];
486
        }
487
        $result = [
488
            'total' => count($systemLanguages),
489
            'data' => $systemLanguages
490
        ];
491
        return $result;
492
    }
493
494
    protected function getBackendUser(): BackendUserAuthentication
495
    {
496
        return $GLOBALS['BE_USER'];
497
    }
498
499
    protected function getLanguageService(): LanguageService
500
    {
501
        return $GLOBALS['LANG'];
502
    }
503
504
    /**
505
     * Gets the difference handler, parsing differences based on sentences.
506
     *
507
     * @return DiffUtility
508
     */
509
    protected function getDifferenceHandler()
510
    {
511
        if (!isset($this->differenceHandler)) {
512
            $this->differenceHandler = GeneralUtility::makeInstance(DiffUtility::class);
513
            $this->differenceHandler->stripTags = false;
514
        }
515
        return $this->differenceHandler;
516
    }
517
518
    /**
519
     * Creates a new instance of the integrity service for the
520
     * given set of affected elements.
521
     *
522
     * @param CombinedRecord[] $affectedElements
523
     * @return IntegrityService
524
     * @see getAffectedElements
525
     */
526
    protected function createIntegrityService(array $affectedElements)
527
    {
528
        $integrityService = GeneralUtility::makeInstance(IntegrityService::class);
529
        $integrityService->setAffectedElements($affectedElements);
530
        return $integrityService;
531
    }
532
533
    /**
534
     * Gets affected elements on publishing/swapping actions.
535
     * Affected elements have a dependency, e.g. translation overlay
536
     * and the default origin record - thus, the default record would be
537
     * affected if the translation overlay shall be published.
538
     *
539
     * @param \stdClass $parameters
540
     * @return array
541
     */
542
    protected function getAffectedElements(\stdClass $parameters)
543
    {
544
        $affectedElements = [];
545
        if ($parameters->type === 'selection') {
546
            foreach ((array)$parameters->selection as $element) {
547
                $affectedElements[] = CombinedRecord::create($element->table, $element->liveId, $element->versionId);
548
            }
549
        } elseif ($parameters->type === 'all') {
550
            $versions = $this->workspaceService->selectVersionsInWorkspace(
551
                $this->getCurrentWorkspace(),
552
                -99,
553
                -1,
554
                0,
555
                'tables_select',
556
                $this->validateLanguageParameter($parameters)
557
            );
558
            foreach ($versions as $table => $tableElements) {
559
                foreach ($tableElements as $element) {
560
                    $affectedElement = CombinedRecord::create($table, $element['t3ver_oid'], $element['uid']);
561
                    $affectedElement->getVersionRecord()->setRow($element);
562
                    $affectedElements[] = $affectedElement;
563
                }
564
            }
565
        }
566
        return $affectedElements;
567
    }
568
569
    /**
570
     * Validates whether the submitted language parameter can be
571
     * interpreted as integer value.
572
     *
573
     * @param \stdClass $parameters
574
     * @return int|null
575
     */
576
    protected function validateLanguageParameter(\stdClass $parameters)
577
    {
578
        $language = null;
579
        if (isset($parameters->language) && MathUtility::canBeInterpretedAsInteger($parameters->language)) {
580
            $language = $parameters->language;
581
        }
582
        return $language;
583
    }
584
585
    /**
586
     * Gets the current workspace ID.
587
     *
588
     * @return int The current workspace ID
589
     */
590
    protected function getCurrentWorkspace()
591
    {
592
        return $this->workspaceService->getCurrentWorkspace();
593
    }
594
595
    /**
596
     * Gets the fields suitable for being displayed in new and delete diff views
597
     *
598
     * @param string $table
599
     * @param int $uid
600
     * @return array
601
     */
602
    protected function getSuitableFields(string $table, int $uid): array
603
    {
604
        $formDataCompiler = GeneralUtility::makeInstance(
605
            FormDataCompiler::class,
606
            GeneralUtility::makeInstance(TcaDatabaseRecord::class)
607
        );
608
609
        try {
610
            $result = $formDataCompiler->compile(['command' => 'edit', 'tableName' => $table, 'vanillaUid' => $uid]);
611
            $fieldList = array_unique(array_values($result['columnsToProcess']));
612
        } catch (\Exception $exception) {
613
            $fieldList = [];
614
        }
615
616
        return array_unique(array_merge(
617
            $fieldList,
618
            GeneralUtility::trimExplode(',', (string)($GLOBALS['TCA'][$table]['ctrl']['searchFields'] ?? ''))
619
        ));
620
    }
621
}
622