Total Complexity | 109 |
Total Lines | 717 |
Duplicated Lines | 0 % |
Changes | 1 | ||
Bugs | 0 | Features | 0 |
Complex classes like RecordProvider often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use RecordProvider, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
32 | class RecordProvider extends AbstractProvider |
||
33 | { |
||
34 | /** |
||
35 | * Database record |
||
36 | * |
||
37 | * @var array |
||
38 | */ |
||
39 | protected $record = []; |
||
40 | |||
41 | /** |
||
42 | * Database record of the page $this->record is placed on |
||
43 | * |
||
44 | * @var array |
||
45 | */ |
||
46 | protected $pageRecord = []; |
||
47 | |||
48 | /** |
||
49 | * Local cache for the result of BackendUserAuthentication::calcPerms() |
||
50 | * |
||
51 | * @var Permission |
||
52 | */ |
||
53 | protected $pagePermissions; |
||
54 | |||
55 | /** |
||
56 | * @var array |
||
57 | */ |
||
58 | protected $itemsConfiguration = [ |
||
59 | 'view' => [ |
||
60 | 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.view', |
||
61 | 'iconIdentifier' => 'actions-view', |
||
62 | 'callbackAction' => 'viewRecord' |
||
63 | ], |
||
64 | 'edit' => [ |
||
65 | 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.edit', |
||
66 | 'iconIdentifier' => 'actions-open', |
||
67 | 'callbackAction' => 'editRecord' |
||
68 | ], |
||
69 | 'new' => [ |
||
70 | 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.new', |
||
71 | 'iconIdentifier' => 'actions-add', |
||
72 | 'callbackAction' => 'newRecord' |
||
73 | ], |
||
74 | 'info' => [ |
||
75 | 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.info', |
||
76 | 'iconIdentifier' => 'actions-document-info', |
||
77 | 'callbackAction' => 'openInfoPopUp' |
||
78 | ], |
||
79 | 'divider1' => [ |
||
80 | 'type' => 'divider' |
||
81 | ], |
||
82 | 'copy' => [ |
||
83 | 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.copy', |
||
84 | 'iconIdentifier' => 'actions-edit-copy', |
||
85 | 'callbackAction' => 'copy' |
||
86 | ], |
||
87 | 'copyRelease' => [ |
||
88 | 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.copy', |
||
89 | 'iconIdentifier' => 'actions-edit-copy-release', |
||
90 | 'callbackAction' => 'clipboardRelease' |
||
91 | ], |
||
92 | 'cut' => [ |
||
93 | 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.cut', |
||
94 | 'iconIdentifier' => 'actions-edit-cut', |
||
95 | 'callbackAction' => 'cut' |
||
96 | ], |
||
97 | 'cutRelease' => [ |
||
98 | 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.cutrelease', |
||
99 | 'iconIdentifier' => 'actions-edit-cut-release', |
||
100 | 'callbackAction' => 'clipboardRelease' |
||
101 | ], |
||
102 | 'pasteAfter' => [ |
||
103 | 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.pasteafter', |
||
104 | 'iconIdentifier' => 'actions-document-paste-after', |
||
105 | 'callbackAction' => 'pasteAfter' |
||
106 | ], |
||
107 | 'divider2' => [ |
||
108 | 'type' => 'divider' |
||
109 | ], |
||
110 | 'more' => [ |
||
111 | 'type' => 'submenu', |
||
112 | 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.more', |
||
113 | 'iconIdentifier' => '', |
||
114 | 'callbackAction' => 'openSubmenu', |
||
115 | 'childItems' => [ |
||
116 | 'newWizard' => [ |
||
117 | 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_misc.xlf:CM_newWizard', |
||
118 | 'iconIdentifier' => 'actions-add', |
||
119 | 'callbackAction' => 'newContentWizard', |
||
120 | ], |
||
121 | 'openListModule' => [ |
||
122 | 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_misc.xlf:CM_db_list', |
||
123 | 'iconIdentifier' => 'actions-system-list-open', |
||
124 | 'callbackAction' => 'openListModule', |
||
125 | ], |
||
126 | ], |
||
127 | ], |
||
128 | 'divider3' => [ |
||
129 | 'type' => 'divider' |
||
130 | ], |
||
131 | 'enable' => [ |
||
132 | 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:enable', |
||
133 | 'iconIdentifier' => 'actions-edit-unhide', |
||
134 | 'callbackAction' => 'enableRecord', |
||
135 | ], |
||
136 | 'disable' => [ |
||
137 | 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:disable', |
||
138 | 'iconIdentifier' => 'actions-edit-hide', |
||
139 | 'callbackAction' => 'disableRecord', |
||
140 | ], |
||
141 | 'delete' => [ |
||
142 | 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.delete', |
||
143 | 'iconIdentifier' => 'actions-edit-delete', |
||
144 | 'callbackAction' => 'deleteRecord', |
||
145 | ], |
||
146 | 'history' => [ |
||
147 | 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_misc.xlf:CM_history', |
||
148 | 'iconIdentifier' => 'actions-document-history-open', |
||
149 | 'callbackAction' => 'openHistoryPopUp', |
||
150 | ], |
||
151 | ]; |
||
152 | |||
153 | /** |
||
154 | * Whether this provider should kick in |
||
155 | * |
||
156 | * @return bool |
||
157 | */ |
||
158 | public function canHandle(): bool |
||
159 | { |
||
160 | if (in_array($this->table, ['sys_file', 'pages'], true)) { |
||
161 | return false; |
||
162 | } |
||
163 | return isset($GLOBALS['TCA'][$this->table]); |
||
164 | } |
||
165 | |||
166 | /** |
||
167 | * Initialize db record |
||
168 | */ |
||
169 | protected function initialize() |
||
174 | } |
||
175 | |||
176 | /** |
||
177 | * Priority is set to lower then default value, in order to skip this provider if there is less generic provider available. |
||
178 | * |
||
179 | * @return int |
||
180 | */ |
||
181 | public function getPriority(): int |
||
184 | } |
||
185 | |||
186 | /** |
||
187 | * This provider works as a fallback if there is no provider dedicated for certain table, thus it's only kicking in when $items are empty. |
||
188 | * |
||
189 | * @param array $items |
||
190 | * @return array |
||
191 | */ |
||
192 | public function addItems(array $items): array |
||
199 | } |
||
200 | |||
201 | /** |
||
202 | * Whether a given item can be rendered (e.g. user has enough permissions) |
||
203 | * |
||
204 | * @param string $itemName |
||
205 | * @param string $type |
||
206 | * @return bool |
||
207 | */ |
||
208 | protected function canRender(string $itemName, string $type): bool |
||
209 | { |
||
210 | if (in_array($type, ['divider', 'submenu'], true)) { |
||
211 | return true; |
||
212 | } |
||
213 | if (in_array($itemName, $this->disabledItems, true)) { |
||
214 | return false; |
||
215 | } |
||
216 | $canRender = false; |
||
217 | switch ($itemName) { |
||
218 | case 'view': |
||
219 | $canRender = $this->canBeViewed(); |
||
220 | break; |
||
221 | case 'edit': |
||
222 | $canRender = $this->canBeEdited(); |
||
223 | break; |
||
224 | case 'new': |
||
225 | $canRender = $this->canBeNew(); |
||
226 | break; |
||
227 | case 'newWizard': |
||
228 | $canRender = $this->canOpenNewCEWizard(); |
||
229 | break; |
||
230 | case 'info': |
||
231 | $canRender = $this->canShowInfo(); |
||
232 | break; |
||
233 | case 'enable': |
||
234 | $canRender = $this->canBeEnabled(); |
||
235 | break; |
||
236 | case 'disable': |
||
237 | $canRender = $this->canBeDisabled(); |
||
238 | break; |
||
239 | case 'delete': |
||
240 | $canRender = $this->canBeDeleted(); |
||
241 | break; |
||
242 | case 'history': |
||
243 | $canRender = $this->canShowHistory(); |
||
244 | break; |
||
245 | case 'openListModule': |
||
246 | $canRender = $this->canOpenListModule(); |
||
247 | break; |
||
248 | case 'copy': |
||
249 | $canRender = $this->canBeCopied(); |
||
250 | break; |
||
251 | case 'copyRelease': |
||
252 | $canRender = $this->isRecordInClipboard('copy'); |
||
253 | break; |
||
254 | case 'cut': |
||
255 | $canRender = $this->canBeCut(); |
||
256 | break; |
||
257 | case 'cutRelease': |
||
258 | $canRender = $this->isRecordInClipboard('cut'); |
||
259 | break; |
||
260 | case 'pasteAfter': |
||
261 | $canRender = $this->canBePastedAfter(); |
||
262 | break; |
||
263 | } |
||
264 | return $canRender; |
||
265 | } |
||
266 | |||
267 | /** |
||
268 | * Saves calculated permissions for a page containing given record, to speed things up |
||
269 | */ |
||
270 | protected function initPermissions() |
||
271 | { |
||
272 | $this->pageRecord = BackendUtility::getRecord('pages', $this->record['pid']) ?? []; |
||
273 | $this->pagePermissions = new Permission($this->backendUser->calcPerms($this->pageRecord)); |
||
274 | } |
||
275 | |||
276 | /** |
||
277 | * Returns true if a current user have access to given permission |
||
278 | * |
||
279 | * @see BackendUserAuthentication::doesUserHaveAccess() |
||
280 | * @param int $permission |
||
281 | * @return bool |
||
282 | */ |
||
283 | protected function hasPagePermission(int $permission): bool |
||
284 | { |
||
285 | return $this->backendUser->isAdmin() || $this->pagePermissions->isGranted($permission); |
||
286 | } |
||
287 | |||
288 | /** |
||
289 | * Additional attributes for JS |
||
290 | * |
||
291 | * @param string $itemName |
||
292 | * @return array |
||
293 | */ |
||
294 | protected function getAdditionalAttributes(string $itemName): array |
||
295 | { |
||
296 | $attributes = []; |
||
297 | if ($itemName === 'view') { |
||
298 | $attributes += $this->getViewAdditionalAttributes(); |
||
299 | } |
||
300 | if ($itemName === 'enable' || $itemName === 'disable') { |
||
301 | $attributes += $this->getEnableDisableAdditionalAttributes(); |
||
302 | } |
||
303 | if ($itemName === 'newWizard' && $this->table === 'tt_content') { |
||
304 | $moduleName = BackendUtility::getPagesTSconfig($this->record['pid'])['mod.']['newContentElementWizard.']['override'] |
||
305 | ?? 'new_content_element_wizard'; |
||
306 | $urlParameters = [ |
||
307 | 'id' => $this->record['pid'], |
||
308 | 'sys_language_uid' => $this->record['sys_language_uid'], |
||
309 | 'colPos' => $this->record['colPos'], |
||
310 | 'uid_pid' => -$this->record['uid'] |
||
311 | ]; |
||
312 | $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class); |
||
313 | $url = (string)$uriBuilder->buildUriFromRoute($moduleName, $urlParameters); |
||
314 | $attributes += [ |
||
315 | 'data-new-wizard-url' => htmlspecialchars($url), |
||
316 | 'data-title' => $this->languageService->getLL('newContentElement'), |
||
317 | ]; |
||
318 | } |
||
319 | if ($itemName === 'delete') { |
||
320 | $attributes += $this->getDeleteAdditionalAttributes(); |
||
321 | } |
||
322 | if ($itemName === 'openListModule') { |
||
323 | $attributes += [ |
||
324 | 'data-page-uid' => $this->record['pid'] |
||
325 | ]; |
||
326 | } |
||
327 | if ($itemName === 'pasteAfter') { |
||
328 | $attributes += $this->getPasteAdditionalAttributes('after'); |
||
329 | } |
||
330 | return $attributes; |
||
331 | } |
||
332 | |||
333 | /** |
||
334 | * Additional attributes for the 'view' item |
||
335 | * |
||
336 | * @return array |
||
337 | */ |
||
338 | protected function getViewAdditionalAttributes(): array |
||
339 | { |
||
340 | $attributes = []; |
||
341 | $viewLink = $this->getViewLink(); |
||
342 | if ($viewLink) { |
||
343 | $attributes += [ |
||
344 | 'data-preview-url' => htmlspecialchars($viewLink), |
||
345 | ]; |
||
346 | } |
||
347 | return $attributes; |
||
348 | } |
||
349 | |||
350 | /** |
||
351 | * Additional attributes for the hide & unhide items |
||
352 | * |
||
353 | * @return array |
||
354 | */ |
||
355 | protected function getEnableDisableAdditionalAttributes(): array |
||
359 | ]; |
||
360 | } |
||
361 | |||
362 | /** |
||
363 | * Additional attributes for the pasteInto and pasteAfter items |
||
364 | * |
||
365 | * @param string $type "after" or "into" |
||
366 | * @return array |
||
367 | */ |
||
368 | protected function getPasteAdditionalAttributes(string $type): array |
||
369 | { |
||
370 | $closeText = $this->languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:cancel'); |
||
371 | $okText = $this->languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:ok'); |
||
372 | $attributes = []; |
||
373 | if ($this->backendUser->jsConfirmation(JsConfirmation::COPY_MOVE_PASTE)) { |
||
374 | $selItem = $this->clipboard->getSelectedRecord(); |
||
375 | $title = $this->languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_mod_web_list.xlf:clip_paste'); |
||
376 | |||
377 | $confirmMessage = sprintf( |
||
378 | $this->languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:mess.' |
||
379 | . ($this->clipboard->currentMode() === 'copy' ? 'copy' : 'move') . '_' . $type), |
||
380 | GeneralUtility::fixed_lgd_cs($selItem['_RECORD_TITLE'], $this->backendUser->uc['titleLen']), |
||
381 | GeneralUtility::fixed_lgd_cs(BackendUtility::getRecordTitle($this->table, $this->record), $this->backendUser->uc['titleLen']) |
||
382 | ); |
||
383 | $attributes += [ |
||
384 | 'data-title' => htmlspecialchars($title), |
||
385 | 'data-message' => htmlspecialchars($confirmMessage), |
||
386 | 'data-button-close-text' => htmlspecialchars($closeText), |
||
387 | 'data-button-ok-text' => htmlspecialchars($okText), |
||
388 | ]; |
||
389 | } |
||
390 | return $attributes; |
||
391 | } |
||
392 | |||
393 | /** |
||
394 | * Additional data for a "delete" action (confirmation modal title and message) |
||
395 | * |
||
396 | * @return array |
||
397 | */ |
||
398 | protected function getDeleteAdditionalAttributes(): array |
||
399 | { |
||
400 | $closeText = $this->languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:cancel'); |
||
401 | $okText = $this->languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:delete'); |
||
402 | $attributes = []; |
||
403 | if ($this->backendUser->jsConfirmation(JsConfirmation::DELETE)) { |
||
404 | $recordTitle = GeneralUtility::fixed_lgd_cs(BackendUtility::getRecordTitle($this->table, $this->record), $this->backendUser->uc['titleLen']); |
||
405 | |||
406 | $title = $this->languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_mod_web_list.xlf:delete'); |
||
407 | $confirmMessage = sprintf( |
||
408 | $this->languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:mess.delete'), |
||
409 | $recordTitle |
||
410 | ); |
||
411 | $confirmMessage .= BackendUtility::referenceCount( |
||
412 | $this->table, |
||
413 | $this->record['uid'], |
||
414 | ' ' . $this->languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.referencesToRecord') |
||
415 | ); |
||
416 | $confirmMessage .= BackendUtility::translationCount( |
||
417 | $this->table, |
||
418 | $this->record['uid'], |
||
419 | ' ' . $this->languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.translationsOfRecord') |
||
420 | ); |
||
421 | $attributes += [ |
||
422 | 'data-title' => htmlspecialchars($title), |
||
423 | 'data-message' => htmlspecialchars($confirmMessage), |
||
424 | 'data-button-close-text' => htmlspecialchars($closeText), |
||
425 | 'data-button-ok-text' => htmlspecialchars($okText), |
||
426 | ]; |
||
427 | } |
||
428 | return $attributes; |
||
429 | } |
||
430 | |||
431 | /** |
||
432 | * Returns id of the Page used for preview |
||
433 | * |
||
434 | * @return int |
||
435 | */ |
||
436 | protected function getPreviewPid(): int |
||
439 | } |
||
440 | |||
441 | /** |
||
442 | * Returns the view link |
||
443 | * |
||
444 | * @return string |
||
445 | */ |
||
446 | protected function getViewLink(): string |
||
447 | { |
||
448 | $anchorSection = ''; |
||
449 | $additionalParams = ''; |
||
450 | if ($this->table === 'tt_content') { |
||
451 | $anchorSection = '#c' . $this->record['uid']; |
||
452 | $language = (int)$this->record[$GLOBALS['TCA']['tt_content']['ctrl']['languageField']]; |
||
453 | if ($language > 0) { |
||
454 | $additionalParams = '&L=' . $language; |
||
455 | } |
||
456 | } |
||
457 | |||
458 | try { |
||
459 | return BackendUtility::getPreviewUrl( |
||
460 | $this->getPreviewPid(), |
||
461 | '', |
||
462 | null, |
||
463 | $anchorSection, |
||
464 | '', |
||
465 | $additionalParams |
||
466 | ); |
||
467 | } catch (UnableToLinkToPageException $e) { |
||
468 | return ''; |
||
469 | } |
||
470 | } |
||
471 | |||
472 | /** |
||
473 | * Checks if the page is allowed to show info |
||
474 | * |
||
475 | * @return bool |
||
476 | */ |
||
477 | protected function canShowInfo(): bool |
||
478 | { |
||
479 | return true; |
||
480 | } |
||
481 | |||
482 | /** |
||
483 | * Checks if the page is allowed to show info |
||
484 | * |
||
485 | * @return bool |
||
486 | */ |
||
487 | protected function canShowHistory(): bool |
||
491 | } |
||
492 | |||
493 | /** |
||
494 | * Checks if the record can be previewed in frontend |
||
495 | * |
||
496 | * @return bool |
||
497 | */ |
||
498 | protected function canBeViewed(): bool |
||
499 | { |
||
500 | return $this->table === 'tt_content' && $this->parentPageCanBeViewed(); |
||
501 | } |
||
502 | |||
503 | /** |
||
504 | * Whether a record can be edited |
||
505 | * |
||
506 | * @return bool |
||
507 | */ |
||
508 | protected function canBeEdited(): bool |
||
509 | { |
||
510 | if (isset($GLOBALS['TCA'][$this->table]['ctrl']['readOnly']) && $GLOBALS['TCA'][$this->table]['ctrl']['readOnly']) { |
||
511 | return false; |
||
512 | } |
||
513 | if ($this->backendUser->isAdmin()) { |
||
514 | return true; |
||
515 | } |
||
516 | if (isset($GLOBALS['TCA'][$this->table]['ctrl']['adminOnly']) && $GLOBALS['TCA'][$this->table]['ctrl']['adminOnly']) { |
||
517 | return false; |
||
518 | } |
||
519 | |||
520 | $access = !$this->isRecordLocked() |
||
521 | && $this->backendUser->check('tables_modify', $this->table) |
||
522 | && $this->hasPagePermission(Permission::CONTENT_EDIT) |
||
523 | && $this->backendUser->recordEditAccessInternals($this->table, $this->record); |
||
524 | return $access; |
||
525 | } |
||
526 | |||
527 | /** |
||
528 | * Whether a record can be created |
||
529 | * |
||
530 | * @return bool |
||
531 | */ |
||
532 | protected function canBeNew(): bool |
||
533 | { |
||
534 | return $this->canBeEdited() && !$this->isRecordATranslation(); |
||
535 | } |
||
536 | |||
537 | /** |
||
538 | * Checks if disableDelete flag is set in TSConfig for the current table |
||
539 | * |
||
540 | * @return bool |
||
541 | */ |
||
542 | protected function isDeletionDisabledInTS(): bool |
||
548 | ); |
||
549 | } |
||
550 | |||
551 | /** |
||
552 | * Checks if the user has the right to delete the record |
||
553 | * |
||
554 | * @return bool |
||
555 | */ |
||
556 | protected function canBeDeleted(): bool |
||
557 | { |
||
561 | } |
||
562 | |||
563 | /** |
||
564 | * Returns true if current record can be unhidden/enabled |
||
565 | * |
||
566 | * @return bool |
||
567 | */ |
||
568 | protected function canBeEnabled(): bool |
||
569 | { |
||
570 | return $this->hasDisableColumnWithValue(1) && $this->canBeEdited(); |
||
571 | } |
||
572 | |||
573 | /** |
||
574 | * Returns true if current record can be hidden |
||
575 | * |
||
576 | * @return bool |
||
577 | */ |
||
578 | protected function canBeDisabled(): bool |
||
579 | { |
||
580 | return $this->hasDisableColumnWithValue(0) |
||
581 | && !$this->isRecordCurrentBackendUser() |
||
582 | && $this->canBeEdited(); |
||
583 | } |
||
584 | |||
585 | /** |
||
586 | * Returns true new content element wizard can be shown |
||
587 | * |
||
588 | * @return bool |
||
589 | */ |
||
590 | protected function canOpenNewCEWizard(): bool |
||
591 | { |
||
592 | return $this->table === 'tt_content' |
||
593 | && (bool)(BackendUtility::getPagesTSconfig($this->record['pid'])['mod.']['web_layout.']['disableNewContentElementWizard'] ?? true) |
||
594 | && $this->canBeEdited() && !$this->isRecordATranslation(); |
||
595 | } |
||
596 | |||
597 | /** |
||
598 | * @return bool |
||
599 | */ |
||
600 | protected function canOpenListModule(): bool |
||
601 | { |
||
602 | return $this->backendUser->check('modules', 'web_list'); |
||
603 | } |
||
604 | |||
605 | /** |
||
606 | * @return bool |
||
607 | */ |
||
608 | protected function canBeCopied(): bool |
||
609 | { |
||
610 | return !$this->isRecordInClipboard('copy') |
||
611 | && !$this->isRecordATranslation(); |
||
612 | } |
||
613 | |||
614 | /** |
||
615 | * @return bool |
||
616 | */ |
||
617 | protected function canBeCut(): bool |
||
618 | { |
||
619 | return !$this->isRecordInClipboard('cut') |
||
620 | && $this->canBeEdited() |
||
621 | && !$this->isRecordATranslation(); |
||
622 | } |
||
623 | |||
624 | /** |
||
625 | * Paste after is only shown for records from the same table (comparing record in clipboard and record clicked) |
||
626 | * |
||
627 | * @return bool |
||
628 | */ |
||
629 | protected function canBePastedAfter(): bool |
||
630 | { |
||
631 | $clipboardElementCount = count($this->clipboard->elFromTable($this->table)); |
||
632 | |||
633 | return $clipboardElementCount |
||
634 | && $this->backendUser->check('tables_modify', $this->table) |
||
635 | && $this->hasPagePermission(Permission::CONTENT_EDIT); |
||
636 | } |
||
637 | |||
638 | /** |
||
639 | * Checks if table have "disable" column (e.g. "hidden"), if user has access to this column |
||
640 | * and if it contains given value |
||
641 | * |
||
642 | * @param int $value |
||
643 | * @return bool |
||
644 | */ |
||
645 | protected function hasDisableColumnWithValue(int $value): bool |
||
646 | { |
||
647 | if (isset($GLOBALS['TCA'][$this->table]['ctrl']['enablecolumns']['disabled'])) { |
||
648 | $hiddenFieldName = $GLOBALS['TCA'][$this->table]['ctrl']['enablecolumns']['disabled']; |
||
649 | if ( |
||
650 | $hiddenFieldName !== '' && !empty($GLOBALS['TCA'][$this->table]['columns'][$hiddenFieldName]) |
||
651 | && ( |
||
652 | empty($GLOBALS['TCA'][$this->table]['columns'][$hiddenFieldName]['exclude']) |
||
653 | || $this->backendUser->check('non_exclude_fields', $this->table . ':' . $hiddenFieldName) |
||
654 | ) |
||
655 | ) { |
||
656 | return (int)($this->record[$hiddenFieldName] ?? 0) === (int)$value; |
||
657 | } |
||
658 | } |
||
659 | return false; |
||
660 | } |
||
661 | |||
662 | /** |
||
663 | * Record is locked if page is locked or page is not locked but record is |
||
664 | * |
||
665 | * @return bool |
||
666 | */ |
||
667 | protected function isRecordLocked(): bool |
||
668 | { |
||
669 | return (int)$this->pageRecord['editlock'] === 1 |
||
670 | || isset($GLOBALS['TCA'][$this->table]['ctrl']['editlock']) |
||
671 | && (int)$this->record[$GLOBALS['TCA'][$this->table]['ctrl']['editlock']] === 1; |
||
672 | } |
||
673 | |||
674 | /** |
||
675 | * Returns true is a current record is a delete placeholder |
||
676 | * |
||
677 | * @return bool |
||
678 | */ |
||
679 | protected function isDeletePlaceholder(): bool |
||
685 | } |
||
686 | |||
687 | /** |
||
688 | * Checks if current record is in the "normal" pad of the clipboard |
||
689 | * |
||
690 | * @param string $mode "copy", "cut" or '' for any mode |
||
691 | * @return bool |
||
692 | */ |
||
693 | protected function isRecordInClipboard(string $mode = ''): bool |
||
694 | { |
||
695 | $isSelected = ''; |
||
696 | if ($this->clipboard->current === 'normal' && isset($this->record['uid'])) { |
||
697 | $isSelected = $this->clipboard->isSelected($this->table, $this->record['uid']); |
||
698 | } |
||
699 | return $mode === '' ? !empty($isSelected) : $isSelected === $mode; |
||
700 | } |
||
701 | |||
702 | /** |
||
703 | * Returns true is a record ia a translation |
||
704 | * |
||
705 | * @return bool |
||
706 | */ |
||
707 | protected function isRecordATranslation(): bool |
||
710 | } |
||
711 | |||
712 | /** |
||
713 | * Return true in case the current record is the current backend user |
||
714 | * |
||
715 | * @return bool |
||
716 | */ |
||
717 | protected function isRecordCurrentBackendUser(): bool |
||
721 | } |
||
722 | |||
723 | /** |
||
724 | * Check whether the elements' parent page can be viewed |
||
725 | * |
||
726 | * @return bool |
||
727 | */ |
||
728 | protected function parentPageCanBeViewed(): bool |
||
729 | { |
||
730 | if (!isset($this->pageRecord['uid']) || !($this->pageRecord['doktype'] ?? false)) { |
||
731 | // In case parent page record is invalid, the element can not be viewed |
||
732 | return false; |
||
733 | } |
||
734 | |||
735 | // Finally, we check whether the parent page has a "no view doktype" assigned |
||
736 | return !in_array((int)$this->pageRecord['doktype'], [ |
||
737 | PageRepository::DOKTYPE_SPACER, |
||
738 | PageRepository::DOKTYPE_SYSFOLDER, |
||
739 | PageRepository::DOKTYPE_RECYCLER |
||
740 | ], true); |
||
741 | } |
||
742 | |||
743 | /** |
||
744 | * @return string |
||
745 | */ |
||
746 | protected function getIdentifier(): string |
||
749 | } |
||
750 | } |
||
751 |