[TASK] Improve duplicate exception code check
[Packages/TYPO3.CMS.git] / typo3 / sysext / workspaces / Classes / ExtDirect / ActionHandler.php
1 <?php
2 namespace TYPO3\CMS\Workspaces\ExtDirect;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use TYPO3\CMS\Backend\Utility\BackendUtility;
18 use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
19 use TYPO3\CMS\Core\Utility\GeneralUtility;
20 use TYPO3\CMS\Fluid\View\StandaloneView;
21 use TYPO3\CMS\Workspaces\Domain\Record\StageRecord;
22 use TYPO3\CMS\Workspaces\Domain\Record\WorkspaceRecord;
23 use TYPO3\CMS\Workspaces\Service\StagesService;
24 use TYPO3\CMS\Workspaces\Service\WorkspaceService;
25
26 /**
27 * ExtDirect action handler
28 */
29 class ActionHandler extends AbstractHandler
30 {
31 /**
32 * @var StagesService
33 */
34 protected $stageService;
35
36 /**
37 * Creates this object.
38 */
39 public function __construct()
40 {
41 $this->stageService = GeneralUtility::makeInstance(StagesService::class);
42 }
43
44 /**
45 * Generates a workspace preview link.
46 *
47 * @param int $uid The ID of the record to be linked
48 * @return string the full domain including the protocol http:// or https://, but without the trailing '/'
49 */
50 public function generateWorkspacePreviewLink($uid)
51 {
52 return $this->getWorkspaceService()->generateWorkspacePreviewLink($uid);
53 }
54
55 /**
56 * Generates workspace preview links for all available languages of a page.
57 *
58 * @param int $uid
59 * @return array
60 */
61 public function generateWorkspacePreviewLinksForAllLanguages($uid)
62 {
63 return $this->getWorkspaceService()->generateWorkspacePreviewLinksForAllLanguages($uid);
64 }
65
66 /**
67 * Swaps a single record.
68 *
69 * @param string $table
70 * @param int $t3ver_oid
71 * @param int $orig_uid
72 * @return void
73 * @todo What about reporting errors back to the ExtJS interface? /olly/
74 */
75 public function swapSingleRecord($table, $t3ver_oid, $orig_uid)
76 {
77 $versionRecord = BackendUtility::getRecord($table, $orig_uid);
78 $currentWorkspace = $this->setTemporaryWorkspace($versionRecord['t3ver_wsid']);
79
80 $cmd[$table][$t3ver_oid]['version'] = [
81 'action' => 'swap',
82 'swapWith' => $orig_uid,
83 'swapIntoWS' => 1
84 ];
85 $this->processTcaCmd($cmd);
86
87 $this->setTemporaryWorkspace($currentWorkspace);
88 }
89
90 /**
91 * Deletes a single record.
92 *
93 * @param string $table
94 * @param int $uid
95 * @return void
96 * @todo What about reporting errors back to the ExtJS interface? /olly/
97 */
98 public function deleteSingleRecord($table, $uid)
99 {
100 $versionRecord = BackendUtility::getRecord($table, $uid);
101 $currentWorkspace = $this->setTemporaryWorkspace($versionRecord['t3ver_wsid']);
102
103 $cmd[$table][$uid]['version'] = [
104 'action' => 'clearWSID'
105 ];
106 $this->processTcaCmd($cmd);
107
108 $this->setTemporaryWorkspace($currentWorkspace);
109 }
110
111 /**
112 * Generates a view link for a page.
113 *
114 * @param string $table
115 * @param string $uid
116 * @return string
117 */
118 public function viewSingleRecord($table, $uid)
119 {
120 return WorkspaceService::viewSingleRecord($table, $uid);
121 }
122
123 /**
124 * Executes an action (publish, discard, swap) to a selection set.
125 *
126 * @param \stdClass $parameter
127 * @return array
128 */
129 public function executeSelectionAction($parameter)
130 {
131 $result = [];
132
133 if (empty($parameter->action) || empty($parameter->selection)) {
134 $result['error'] = 'No action or record selection given';
135 return $result;
136 }
137
138 $commands = [];
139 $swapIntoWorkspace = ($parameter->action === 'swap');
140 if ($parameter->action === 'publish' || $swapIntoWorkspace) {
141 $commands = $this->getPublishSwapCommands($parameter->selection, $swapIntoWorkspace);
142 } elseif ($parameter->action === 'discard') {
143 $commands = $this->getFlushCommands($parameter->selection);
144 }
145
146 $result = $this->processTcaCmd($commands);
147 $result['total'] = count($commands);
148 return $result;
149 }
150
151 /**
152 * Get publish swap commands
153 *
154 * @param array|\stdClass[] $selection
155 * @param bool $swapIntoWorkspace
156 * @return array
157 */
158 protected function getPublishSwapCommands(array $selection, $swapIntoWorkspace)
159 {
160 $commands = [];
161 foreach ($selection as $record) {
162 $commands[$record->table][$record->liveId]['version'] = [
163 'action' => 'swap',
164 'swapWith' => $record->versionId,
165 'swapIntoWS' => (bool)$swapIntoWorkspace,
166 ];
167 }
168 return $commands;
169 }
170
171 /**
172 * Get flush commands
173 *
174 * @param array|\stdClass[] $selection
175 * @return array
176 */
177 protected function getFlushCommands(array $selection)
178 {
179 $commands = [];
180 foreach ($selection as $record) {
181 $commands[$record->table][$record->versionId]['version'] = [
182 'action' => 'clearWSID',
183 ];
184 }
185 return $commands;
186 }
187
188 /**
189 * Saves the selected columns to be shown to the preferences of the current backend user.
190 *
191 * @param \stdClass $model
192 * @return void
193 */
194 public function saveColumnModel($model)
195 {
196 $data = [];
197 foreach ($model as $column) {
198 $data[$column->column] = [
199 'position' => $column->position,
200 'hidden' => $column->hidden
201 ];
202 }
203 $GLOBALS['BE_USER']->uc['moduleData']['Workspaces'][$GLOBALS['BE_USER']->workspace]['columns'] = $data;
204 $GLOBALS['BE_USER']->writeUC();
205 }
206
207 public function loadColumnModel()
208 {
209 if (is_array($GLOBALS['BE_USER']->uc['moduleData']['Workspaces'][$GLOBALS['BE_USER']->workspace]['columns'])) {
210 return $GLOBALS['BE_USER']->uc['moduleData']['Workspaces'][$GLOBALS['BE_USER']->workspace]['columns'];
211 } else {
212 return [];
213 }
214 }
215
216 /**
217 * Saves the selected language.
218 *
219 * @param int|string $language
220 * @return void
221 */
222 public function saveLanguageSelection($language)
223 {
224 if (\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($language) === false && $language !== 'all') {
225 $language = 'all';
226 }
227 $GLOBALS['BE_USER']->uc['moduleData']['Workspaces'][$GLOBALS['BE_USER']->workspace]['language'] = $language;
228 $GLOBALS['BE_USER']->writeUC();
229 }
230
231 /**
232 * Gets the dialog window to be displayed before a record can be sent to the next stage.
233 *
234 * @param int $uid
235 * @param string $table
236 * @param int $t3ver_oid
237 * @return array
238 */
239 public function sendToNextStageWindow($uid, $table, $t3ver_oid)
240 {
241 $elementRecord = BackendUtility::getRecord($table, $uid);
242 $currentWorkspace = $this->setTemporaryWorkspace($elementRecord['t3ver_wsid']);
243
244 if (is_array($elementRecord)) {
245 $workspaceRecord = WorkspaceRecord::get($elementRecord['t3ver_wsid']);
246 $nextStageRecord = $workspaceRecord->getNextStage($elementRecord['t3ver_stage']);
247 if ($nextStageRecord !== null) {
248 $this->stageService->getRecordService()->add($table, $uid);
249 $result = $this->getSentToStageWindow($nextStageRecord);
250 $result['affects'] = [
251 'table' => $table,
252 'nextStage' => $nextStageRecord->getUid(),
253 't3ver_oid' => $t3ver_oid,
254 'uid' => $uid
255 ];
256 } else {
257 $result = $this->getErrorResponse('error.stageId.invalid', 1291111644);
258 }
259 } else {
260 $result = $this->getErrorResponse('error.sendToNextStage.noRecordFound', 1287264776);
261 }
262
263 $this->setTemporaryWorkspace($currentWorkspace);
264 return $result;
265 }
266
267 /**
268 * Gets the dialog window to be displayed before a record can be sent to the previous stage.
269 *
270 * @param int $uid
271 * @param string $table
272 * @return array
273 */
274 public function sendToPrevStageWindow($uid, $table)
275 {
276 $elementRecord = BackendUtility::getRecord($table, $uid);
277 $currentWorkspace = $this->setTemporaryWorkspace($elementRecord['t3ver_wsid']);
278
279 if (is_array($elementRecord)) {
280 $workspaceRecord = WorkspaceRecord::get($elementRecord['t3ver_wsid']);
281 $stageRecord = $workspaceRecord->getStage($elementRecord['t3ver_stage']);
282
283 if ($stageRecord !== null) {
284 if (!$stageRecord->isEditStage()) {
285 $this->stageService->getRecordService()->add($table, $uid);
286 $previousStageRecord = $stageRecord->getPrevious();
287 $result = $this->getSentToStageWindow($previousStageRecord);
288 $result['affects'] = [
289 'table' => $table,
290 'uid' => $uid,
291 'nextStage' => $previousStageRecord->getUid()
292 ];
293 } else {
294 // element is already in edit stage, there is no prev stage - return an error message
295 $result = $this->getErrorResponse('error.sendToPrevStage.noPreviousStage', 1287264746);
296 }
297 } else {
298 $result = $this->getErrorResponse('error.stageId.invalid', 1291111644);
299 }
300 } else {
301 $result = $this->getErrorResponse('error.sendToNextStage.noRecordFound', 1287264765);
302 }
303
304 $this->setTemporaryWorkspace($currentWorkspace);
305 return $result;
306 }
307
308 /**
309 * Gets the dialog window to be displayed before a record can be sent to a specific stage.
310 *
311 * @param int $nextStageId
312 * @param array|\stdClass[] $elements
313 * @return array
314 */
315 public function sendToSpecificStageWindow($nextStageId, array $elements)
316 {
317 foreach ($elements as $element) {
318 $this->stageService->getRecordService()->add(
319 $element->table,
320 $element->uid
321 );
322 }
323
324 $result = $this->getSentToStageWindow($nextStageId);
325 $result['affects'] = [
326 'nextStage' => $nextStageId
327 ];
328 return $result;
329 }
330
331 /**
332 * Gets a merged variant of recipient defined by uid and custom ones.
333 *
334 * @param array $uidOfRecipients list of recipients
335 * @param string $additionalRecipients given user string of additional recipients
336 * @param int $stageId stage id
337 * @return array
338 * @throws \InvalidArgumentException
339 */
340 public function getRecipientList(array $uidOfRecipients, $additionalRecipients, $stageId)
341 {
342 $stageRecord = WorkspaceRecord::get($this->getCurrentWorkspace())->getStage($stageId);
343
344 if ($stageRecord === null) {
345 throw new \InvalidArgumentException(
346 $GLOBALS['LANG']->sL('LLL:EXT:workspaces/Resources/Private/Language/locallang.xlf:error.stageId.integer'),
347 1476044776
348 );
349 }
350
351 $recipients = [];
352 $finalRecipients = [];
353 $backendUserIds = $stageRecord->getAllRecipients();
354 foreach ($uidOfRecipients as $userUid) {
355 // Ensure that only configured backend users are considered
356 if (!in_array($userUid, $backendUserIds)) {
357 continue;
358 }
359 $beUserRecord = BackendUtility::getRecord('be_users', (int)$userUid);
360 if (is_array($beUserRecord) && $beUserRecord['email'] !== '') {
361 $uc = $beUserRecord['uc'] ? unserialize($beUserRecord['uc']) : [];
362 $recipients[$beUserRecord['email']] = [
363 'email' => $beUserRecord['email'],
364 'lang' => isset($uc['lang']) ? $uc['lang'] : $beUserRecord['lang']
365 ];
366 }
367 }
368
369 if ($stageRecord->hasPreselection() && !$stageRecord->isPreselectionChangeable()) {
370 $preselectedBackendUsers = $this->getStageService()->getBackendUsers(
371 implode(',', $this->stageService->getPreselectedRecipients($stageRecord))
372 );
373
374 foreach ($preselectedBackendUsers as $preselectedBackendUser) {
375 if (empty($preselectedBackendUser['email']) || !GeneralUtility::validEmail($preselectedBackendUser['email'])) {
376 continue;
377 }
378 if (!isset($recipients[$preselectedBackendUser['email']])) {
379 $uc = (!empty($preselectedBackendUser['uc']) ? unserialize($preselectedBackendUser['uc']) : []);
380 $recipients[$preselectedBackendUser['email']] = [
381 'email' => $preselectedBackendUser['email'],
382 'lang' => (isset($uc['lang']) ? $uc['lang'] : $preselectedBackendUser['lang'])
383 ];
384 }
385 }
386 }
387
388 if ($additionalRecipients !== '') {
389 $emails = GeneralUtility::trimExplode(LF, $additionalRecipients, true);
390 $additionalRecipients = [];
391 foreach ($emails as $email) {
392 $additionalRecipients[$email] = ['email' => $email];
393 }
394 } else {
395 $additionalRecipients = [];
396 }
397 // We merge $recipients on top of $additionalRecipients because $recipients
398 // possibly is more complete with a user language. Furthermore, the list of
399 // recipients is automatically unique since we indexed $additionalRecipients
400 // and $recipients with the email address
401 $allRecipients = array_merge($additionalRecipients, $recipients);
402 foreach ($allRecipients as $email => $recipientInformation) {
403 if (GeneralUtility::validEmail($email)) {
404 $finalRecipients[] = $recipientInformation;
405 }
406 }
407 return $finalRecipients;
408 }
409
410 /**
411 * Discard all items from given page id.
412 *
413 * @param int $pageId
414 * @return array
415 */
416 public function discardStagesFromPage($pageId)
417 {
418 $cmdMapArray = [];
419 /** @var $workspaceService WorkspaceService */
420 $workspaceService = GeneralUtility::makeInstance(WorkspaceService::class);
421 /** @var $stageService StagesService */
422 $stageService = GeneralUtility::makeInstance(StagesService::class);
423 $workspaceItemsArray = $workspaceService->selectVersionsInWorkspace($stageService->getWorkspaceId(), ($filter = 1), ($stage = -99), $pageId, ($recursionLevel = 0), ($selectionType = 'tables_modify'));
424 foreach ($workspaceItemsArray as $tableName => $items) {
425 foreach ($items as $item) {
426 $cmdMapArray[$tableName][$item['uid']]['version']['action'] = 'clearWSID';
427 }
428 }
429 $this->processTcaCmd($cmdMapArray);
430 return [
431 'success' => true
432 ];
433 }
434
435 /**
436 * Push the given element collection to the next workspace stage.
437 *
438 * <code>
439 * $parameters->additional = your@mail.com
440 * $parameters->affects->__TABLENAME__
441 * $parameters->comments
442 * $parameters->receipients
443 * $parameters->stageId
444 * </code>
445 *
446 * @param \stdClass $parameters
447 * @return array
448 */
449 public function sentCollectionToStage(\stdClass $parameters)
450 {
451 $cmdMapArray = [];
452 $comment = $parameters->comments;
453 $stageId = $parameters->stageId;
454 if (\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($stageId) === false) {
455 throw new \InvalidArgumentException('Missing "stageId" in $parameters array.', 1319488194);
456 }
457 if (!is_object($parameters->affects) || empty($parameters->affects)) {
458 throw new \InvalidArgumentException('Missing "affected items" in $parameters array.', 1319488195);
459 }
460 $recipients = $this->getRecipientList((array)$parameters->recipients, $parameters->additional, $stageId);
461 foreach ($parameters->affects as $tableName => $items) {
462 foreach ($items as $item) {
463 // Publishing uses live id in command map
464 if ($stageId == StagesService::STAGE_PUBLISH_EXECUTE_ID) {
465 $cmdMapArray[$tableName][$item->t3ver_oid]['version']['action'] = 'swap';
466 $cmdMapArray[$tableName][$item->t3ver_oid]['version']['swapWith'] = $item->uid;
467 $cmdMapArray[$tableName][$item->t3ver_oid]['version']['comment'] = $comment;
468 $cmdMapArray[$tableName][$item->t3ver_oid]['version']['notificationAlternativeRecipients'] = $recipients;
469 // Setting stage uses version id in command map
470 } else {
471 $cmdMapArray[$tableName][$item->uid]['version']['action'] = 'setStage';
472 $cmdMapArray[$tableName][$item->uid]['version']['stageId'] = $stageId;
473 $cmdMapArray[$tableName][$item->uid]['version']['comment'] = $comment;
474 $cmdMapArray[$tableName][$item->uid]['version']['notificationAlternativeRecipients'] = $recipients;
475 }
476 }
477 }
478 $this->processTcaCmd($cmdMapArray);
479 return [
480 'success' => true,
481 // force refresh after publishing changes
482 'refreshLivePanel' => $parameters->stageId == -20
483 ];
484 }
485
486 /**
487 * Process TCA command map array.
488 *
489 * @param array $cmdMapArray
490 * @return array
491 */
492 protected function processTcaCmd(array $cmdMapArray)
493 {
494 $result = [];
495
496 if (empty($cmdMapArray)) {
497 $result['error'] = 'No commands given to be processed';
498 return $result;
499 }
500
501 /** @var \TYPO3\CMS\Core\DataHandling\DataHandler $dataHandler */
502 $dataHandler = GeneralUtility::makeInstance(\TYPO3\CMS\Core\DataHandling\DataHandler::class);
503 $dataHandler->start([], $cmdMapArray);
504 $dataHandler->process_cmdmap();
505
506 if ($dataHandler->errorLog) {
507 $result['error'] = implode('<br/>', $dataHandler->errorLog);
508 }
509
510 return $result;
511 }
512
513 /**
514 * Gets an object with this structure:
515 *
516 * affects: object
517 * table
518 * t3ver_oid
519 * nextStage
520 * uid
521 * receipients: array with uids
522 * additional: string
523 * comments: string
524 *
525 * @param \stdClass $parameters
526 * @return array
527 */
528 public function sendToNextStageExecute(\stdClass $parameters)
529 {
530 $cmdArray = [];
531 $setStageId = $parameters->affects->nextStage;
532 $comments = $parameters->comments;
533 $table = $parameters->affects->table;
534 $uid = $parameters->affects->uid;
535 $t3ver_oid = $parameters->affects->t3ver_oid;
536
537 $elementRecord = BackendUtility::getRecord($table, $uid);
538 $currentWorkspace = $this->setTemporaryWorkspace($elementRecord['t3ver_wsid']);
539
540 $recipients = $this->getRecipientList((array)$parameters->recipients, $parameters->additional, $setStageId);
541 if ($setStageId == StagesService::STAGE_PUBLISH_EXECUTE_ID) {
542 $cmdArray[$table][$t3ver_oid]['version']['action'] = 'swap';
543 $cmdArray[$table][$t3ver_oid]['version']['swapWith'] = $uid;
544 $cmdArray[$table][$t3ver_oid]['version']['comment'] = $comments;
545 $cmdArray[$table][$t3ver_oid]['version']['notificationAlternativeRecipients'] = $recipients;
546 } else {
547 $cmdArray[$table][$uid]['version']['action'] = 'setStage';
548 $cmdArray[$table][$uid]['version']['stageId'] = $setStageId;
549 $cmdArray[$table][$uid]['version']['comment'] = $comments;
550 $cmdArray[$table][$uid]['version']['notificationAlternativeRecipients'] = $recipients;
551 }
552 $this->processTcaCmd($cmdArray);
553 $result = [
554 'success' => true
555 ];
556
557 $this->setTemporaryWorkspace($currentWorkspace);
558 return $result;
559 }
560
561 /**
562 * Gets an object with this structure:
563 *
564 * affects: object
565 * table
566 * t3ver_oid
567 * nextStage
568 * receipients: array with uids
569 * additional: string
570 * comments: string
571 *
572 * @param \stdClass $parameters
573 * @return array
574 */
575 public function sendToPrevStageExecute(\stdClass $parameters)
576 {
577 $cmdArray = [];
578 $setStageId = $parameters->affects->nextStage;
579 $comments = $parameters->comments;
580 $table = $parameters->affects->table;
581 $uid = $parameters->affects->uid;
582
583 $elementRecord = BackendUtility::getRecord($table, $uid);
584 $currentWorkspace = $this->setTemporaryWorkspace($elementRecord['t3ver_wsid']);
585
586 $recipients = $this->getRecipientList((array)$parameters->recipients, $parameters->additional, $setStageId);
587 $cmdArray[$table][$uid]['version']['action'] = 'setStage';
588 $cmdArray[$table][$uid]['version']['stageId'] = $setStageId;
589 $cmdArray[$table][$uid]['version']['comment'] = $comments;
590 $cmdArray[$table][$uid]['version']['notificationAlternativeRecipients'] = $recipients;
591 $this->processTcaCmd($cmdArray);
592 $result = [
593 'success' => true
594 ];
595
596 $this->setTemporaryWorkspace($currentWorkspace);
597 return $result;
598 }
599
600 /**
601 * Gets an object with this structure:
602 *
603 * affects: object
604 * elements: array
605 * 0: object
606 * table
607 * t3ver_oid
608 * uid
609 * 1: object
610 * table
611 * t3ver_oid
612 * uid
613 * nextStage
614 * recipients: array with uids
615 * additional: string
616 * comments: string
617 *
618 * @param \stdClass $parameters
619 * @return array
620 */
621 public function sendToSpecificStageExecute(\stdClass $parameters)
622 {
623 $cmdArray = [];
624 $setStageId = $parameters->affects->nextStage;
625 $comments = $parameters->comments;
626 $elements = $parameters->affects->elements;
627 $recipients = $this->getRecipientList((array)$parameters->recipients, $parameters->additional, $setStageId);
628 foreach ($elements as $element) {
629 // Avoid any action on records that have already been published to live
630 $elementRecord = BackendUtility::getRecord($element->table, $element->uid);
631 if ((int)$elementRecord['t3ver_wsid'] === 0) {
632 continue;
633 }
634
635 if ($setStageId == StagesService::STAGE_PUBLISH_EXECUTE_ID) {
636 $cmdArray[$element->table][$element->t3ver_oid]['version']['action'] = 'swap';
637 $cmdArray[$element->table][$element->t3ver_oid]['version']['swapWith'] = $element->uid;
638 $cmdArray[$element->table][$element->t3ver_oid]['version']['comment'] = $comments;
639 $cmdArray[$element->table][$element->t3ver_oid]['version']['notificationAlternativeRecipients'] = $recipients;
640 } else {
641 $cmdArray[$element->table][$element->uid]['version']['action'] = 'setStage';
642 $cmdArray[$element->table][$element->uid]['version']['stageId'] = $setStageId;
643 $cmdArray[$element->table][$element->uid]['version']['comment'] = $comments;
644 $cmdArray[$element->table][$element->uid]['version']['notificationAlternativeRecipients'] = $recipients;
645 }
646 }
647 $this->processTcaCmd($cmdArray);
648 $result = [
649 'success' => true
650 ];
651 return $result;
652 }
653
654 /**
655 * Gets the dialog window to be displayed before a record can be sent to a stage.
656 *
657 * @param StageRecord|int $nextStage
658 * @return array
659 */
660 protected function getSentToStageWindow($nextStage)
661 {
662 if (!$nextStage instanceof StageRecord) {
663 $nextStage = WorkspaceRecord::get($this->getCurrentWorkspace())->getStage($nextStage);
664 }
665
666 $result = [];
667 if ($nextStage->isDialogEnabled()) {
668 $result['sendMailTo'] = $this->getRecipientsOfStage($nextStage->getUid());
669 $result['additional'] = [
670 'type' => 'textarea',
671 'value' => ''
672 ];
673 }
674 $result['comments'] = [
675 'type' => 'textarea',
676 'value' => ($nextStage->isInternal() ? '' : $nextStage->getDefaultComment())
677 ];
678
679 return $result;
680 }
681
682 /**
683 * Gets all assigned recipients of a particular stage.
684 *
685 * @param StageRecord|int $stageRecord
686 * @return array
687 */
688 protected function getRecipientsOfStage($stageRecord)
689 {
690 if (!$stageRecord instanceof StageRecord) {
691 $stageRecord = WorkspaceRecord::get($this->getCurrentWorkspace())->getStage($stageRecord);
692 }
693
694 $result = [];
695 $allRecipients = $this->getStageService()->getResponsibleBeUser($stageRecord);
696 $preselectedRecipients = $this->stageService->getPreselectedRecipients($stageRecord);
697 $isPreselectionChangeable = $stageRecord->isPreselectionChangeable();
698
699 foreach ($allRecipients as $backendUserId => $backendUser) {
700 if (empty($backendUser['email']) || !GeneralUtility::validEmail($backendUser['email'])) {
701 continue;
702 }
703
704 $name = (!empty($backendUser['realName']) ? $backendUser['realName'] : $backendUser['username']);
705 $checked = in_array($backendUserId, $preselectedRecipients);
706 $disabled = ($checked && !$isPreselectionChangeable);
707
708 $result[] = [
709 'label' => sprintf('%s (%s)', $name, $backendUser['email']),
710 'value' => $backendUserId,
711 'name' => 'recipients-' . $backendUserId,
712 'checked' => $checked,
713 'disabled' => $disabled
714 ];
715 }
716
717 return $result;
718 }
719
720 /**
721 * Gets the default comment of a particular stage.
722 *
723 * @param int $stage
724 * @return string
725 */
726 protected function getDefaultCommentOfStage($stage)
727 {
728 $result = $this->getStageService()->getPropertyOfCurrentWorkspaceStage($stage, 'default_mailcomment');
729 return $result;
730 }
731
732 /**
733 * Gets an instance of the Stage service.
734 *
735 * @return StagesService
736 */
737 protected function getStageService()
738 {
739 if (!isset($this->stageService)) {
740 $this->stageService = GeneralUtility::makeInstance(StagesService::class);
741 }
742 return $this->stageService;
743 }
744
745 /**
746 * Send all available workspace records to the previous stage.
747 *
748 * @param int $id Current page id to process items to previous stage.
749 * @return array
750 */
751 public function sendPageToPreviousStage($id)
752 {
753 $workspaceService = GeneralUtility::makeInstance(WorkspaceService::class);
754 $workspaceItemsArray = $workspaceService->selectVersionsInWorkspace($this->stageService->getWorkspaceId(), ($filter = 1), ($stage = -99), $id, ($recursionLevel = 0), ($selectionType = 'tables_modify'));
755 list($currentStage, $previousStage) = $this->getStageService()->getPreviousStageForElementCollection($workspaceItemsArray);
756 // get only the relevant items for processing
757 $workspaceItemsArray = $workspaceService->selectVersionsInWorkspace($this->stageService->getWorkspaceId(), ($filter = 1), $currentStage['uid'], $id, ($recursionLevel = 0), ($selectionType = 'tables_modify'));
758 $stageFormFields = $this->getSentToStageWindow($previousStage['uid']);
759 $result = array_merge($stageFormFields, [
760 'title' => 'Status message: Page send to next stage - ID: ' . $id . ' - Next stage title: ' . $previousStage['title'],
761 'items' => $this->getSentToStageWindow($previousStage['uid']),
762 'affects' => $workspaceItemsArray,
763 'stageId' => $previousStage['uid']
764 ]);
765 return $result;
766 }
767
768 /**
769 * @param int $id Current Page id to select Workspace items from.
770 * @return array
771 */
772 public function sendPageToNextStage($id)
773 {
774 $workspaceService = GeneralUtility::makeInstance(WorkspaceService::class);
775 $workspaceItemsArray = $workspaceService->selectVersionsInWorkspace($this->stageService->getWorkspaceId(), ($filter = 1), ($stage = -99), $id, ($recursionLevel = 0), ($selectionType = 'tables_modify'));
776 list($currentStage, $nextStage) = $this->getStageService()->getNextStageForElementCollection($workspaceItemsArray);
777 // get only the relevant items for processing
778 $workspaceItemsArray = $workspaceService->selectVersionsInWorkspace($this->stageService->getWorkspaceId(), ($filter = 1), $currentStage['uid'], $id, ($recursionLevel = 0), ($selectionType = 'tables_modify'));
779 $stageFormFields = $this->getSentToStageWindow($nextStage['uid']);
780 $result = array_merge($stageFormFields, [
781 'title' => 'Status message: Page send to next stage - ID: ' . $id . ' - Next stage title: ' . $nextStage['title'],
782 'affects' => $workspaceItemsArray,
783 'stageId' => $nextStage['uid']
784 ]);
785 return $result;
786 }
787
788 /**
789 * Fetch the current label and visible state of the buttons.
790 *
791 * @param int $id
792 * @return string The pre-rendered HTML for the stage buttons
793 */
794 public function updateStageChangeButtons($id)
795 {
796 /** @var StagesService $stageService */
797 $stageService = GeneralUtility::makeInstance(StagesService::class);
798 /** @var WorkspaceService $workspaceService */
799 $workspaceService = GeneralUtility::makeInstance(WorkspaceService::class);
800 // fetch the next and previous stage
801 $workspaceItemsArray = $workspaceService->selectVersionsInWorkspace($stageService->getWorkspaceId(), ($filter = 1), ($stage = -99), $id, ($recursionLevel = 0), ($selectionType = 'tables_modify'));
802 list(, $nextStage) = $stageService->getNextStageForElementCollection($workspaceItemsArray);
803 list(, $previousStage) = $stageService->getPreviousStageForElementCollection($workspaceItemsArray);
804
805 /** @var StandaloneView $view */
806 $view = GeneralUtility::makeInstance(StandaloneView::class);
807 $extensionPath = ExtensionManagementUtility::extPath('workspaces');
808 $view->setPartialRootPaths(['default' => $extensionPath . 'Resources/Private/Partials']);
809 $view->setTemplatePathAndFilename($extensionPath . 'Resources/Private/Templates/Preview/Ajax/StageButtons.html');
810 $request = $view->getRequest();
811 $request->setControllerExtensionName('workspaces');
812 $view->assignMultiple([
813 'enablePreviousStageButton' => is_array($previousStage) && !empty($previousStage),
814 'enableNextStageButton' => is_array($nextStage) && !empty($nextStage),
815 'enableDiscardStageButton' => is_array($nextStage) && !empty($nextStage) || is_array($previousStage) && !empty($previousStage),
816 'nextStage' => $nextStage['title'],
817 'nextStageId' => $nextStage['uid'],
818 'prevStage' => $previousStage['title'],
819 'prevStageId' => $previousStage['uid'],
820 ]);
821 $renderedView = $view->render();
822 return $renderedView;
823 }
824
825 /**
826 * @param int $workspaceId
827 * @return int Id of the original workspace
828 * @throws \TYPO3\CMS\Core\Exception
829 */
830 protected function setTemporaryWorkspace($workspaceId)
831 {
832 $workspaceId = (int)$workspaceId;
833 $currentWorkspace = (int)$this->getBackendUser()->workspace;
834
835 if ($currentWorkspace !== $workspaceId) {
836 if (!$this->getBackendUser()->setTemporaryWorkspace($workspaceId)) {
837 throw new \TYPO3\CMS\Core\Exception(
838 'Cannot set temporary workspace to "' . $workspaceId . '"',
839 1371484524
840 );
841 }
842 }
843
844 return $currentWorkspace;
845 }
846
847 /**
848 * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
849 */
850 protected function getBackendUser()
851 {
852 return $GLOBALS['BE_USER'];
853 }
854 }