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