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
16namespace TYPO3\CMS\Workspaces\Domain\Record;
17
18use TYPO3\CMS\Workspaces\Service\StagesService;
19
20/**
21 * Combined record class
22 */
23class StageRecord extends AbstractRecord
24{
25    /**
26     * @var WorkspaceRecord
27     */
28    protected $workspace;
29
30    /**
31     * @var bool
32     */
33    protected $internal = false;
34
35    /**
36     * @var array
37     */
38    protected $responsiblePersons;
39
40    /**
41     * @var array
42     */
43    protected $defaultRecipients;
44
45    /**
46     * @var array
47     */
48    protected $preselectedRecipients;
49
50    /**
51     * @var array
52     */
53    protected $allRecipients;
54
55    /**
56     * @param int $uid
57     * @param array $record
58     * @return StageRecord
59     */
60    public static function get($uid, array $record = null)
61    {
62        if (empty($record)) {
63            $record = static::fetch('sys_workspace_stage', $uid);
64        }
65        return WorkspaceRecord::get($record['parentid'])->getStage($uid);
66    }
67
68    /**
69     * @param WorkspaceRecord $workspace
70     * @param int $uid
71     * @param array $record
72     * @return StageRecord
73     */
74    public static function build(WorkspaceRecord $workspace, $uid, array $record = null)
75    {
76        if (empty($record)) {
77            $record = static::fetch('sys_workspace_stage', $uid);
78        }
79        return new self($workspace, $record);
80    }
81
82    /**
83     * @param WorkspaceRecord $workspace
84     * @param array $record
85     */
86    public function __construct(WorkspaceRecord $workspace, array $record)
87    {
88        parent::__construct($record);
89        $this->workspace = $workspace;
90    }
91
92    /**
93     * @return WorkspaceRecord
94     */
95    public function getWorkspace()
96    {
97        return $this->workspace;
98    }
99
100    /**
101     * @return StageRecord|null
102     */
103    public function getPrevious()
104    {
105        return $this->getWorkspace()->getPreviousStage($this->getUid());
106    }
107
108    /**
109     * @return StageRecord|null
110     */
111    public function getNext()
112    {
113        return $this->getWorkspace()->getNextStage($this->getUid());
114    }
115
116    /**
117     * @param StageRecord $stageRecord
118     * @return int
119     */
120    public function determineOrder(StageRecord $stageRecord)
121    {
122        if ($this->getUid() === $stageRecord->getUid()) {
123            return 0;
124        }
125        if ($this->isEditStage() || $stageRecord->isExecuteStage() || $this->isPreviousTo($stageRecord)) {
126            return -1;
127        }
128        if ($this->isExecuteStage() || $stageRecord->isEditStage() || $this->isNextTo($stageRecord)) {
129            return 1;
130        }
131        return 0;
132    }
133
134    /**
135     * Determines whether $this is in a previous stage compared to $stageRecord.
136     *
137     * @param StageRecord $stageRecord
138     * @return bool
139     */
140    public function isPreviousTo(StageRecord $stageRecord)
141    {
142        $current = $stageRecord;
143        while ($previous = $current->getPrevious()) {
144            if ($this->getUid() === $previous->getUid()) {
145                return true;
146            }
147            $current = $previous;
148        }
149        return false;
150    }
151
152    /**
153     * Determines whether $this is in a later stage compared to $stageRecord.
154     *
155     * @param StageRecord $stageRecord
156     * @return bool
157     */
158    public function isNextTo(StageRecord $stageRecord)
159    {
160        $current = $stageRecord;
161        while ($next = $current->getNext()) {
162            if ($this->getUid() === $next->getUid()) {
163                return true;
164            }
165            $current = $next;
166        }
167        return false;
168    }
169
170    /**
171     * @return string
172     */
173    public function getDefaultComment()
174    {
175        $defaultComment = '';
176        if (isset($this->record['default_mailcomment'])) {
177            $defaultComment = $this->record['default_mailcomment'];
178        }
179        return $defaultComment;
180    }
181
182    /**
183     * @param bool $internal
184     */
185    public function setInternal($internal = true)
186    {
187        $this->internal = (bool)$internal;
188    }
189
190    /**
191     * @return bool
192     */
193    public function isInternal()
194    {
195        return $this->internal;
196    }
197
198    /**
199     * @return bool
200     */
201    public function isEditStage()
202    {
203        return $this->getUid() === StagesService::STAGE_EDIT_ID;
204    }
205
206    /**
207     * @return bool
208     */
209    public function isPublishStage()
210    {
211        return $this->getUid() === StagesService::STAGE_PUBLISH_ID;
212    }
213
214    /**
215     * @return bool
216     */
217    public function isExecuteStage()
218    {
219        return $this->getUid() === StagesService::STAGE_PUBLISH_EXECUTE_ID;
220    }
221
222    /**
223     * @return bool
224     */
225    public function isDialogEnabled()
226    {
227        return ((int)$this->record['allow_notificaton_settings'] & 1) > 0;
228    }
229
230    /**
231     * @return bool
232     */
233    public function isPreselectionChangeable()
234    {
235        return ((int)$this->record['allow_notificaton_settings'] & 2) > 0;
236    }
237
238    /**
239     * @return bool
240     */
241    public function areOwnersPreselected()
242    {
243        return ((int)$this->record['notification_preselection'] & 1) > 0;
244    }
245
246    /**
247     * @return bool
248     */
249    public function areMembersPreselected()
250    {
251        return ((int)$this->record['notification_preselection'] & 2) > 0;
252    }
253
254    /**
255     * @return bool
256     */
257    public function areEditorsPreselected()
258    {
259        return ((int)$this->record['notification_preselection'] & 4) > 0;
260    }
261
262    /**
263     * @return bool
264     */
265    public function areResponsiblePersonsPreselected()
266    {
267        return ((int)$this->record['notification_preselection'] & 8) > 0;
268    }
269
270    /**
271     * @return bool
272     */
273    public function hasDefaultRecipients(): bool
274    {
275        return $this->record['notification_defaults'] !== '';
276    }
277
278    /**
279     * @return bool
280     */
281    public function hasPreselection()
282    {
283        return
284            $this->areOwnersPreselected()
285            || $this->areMembersPreselected()
286            || $this->areEditorsPreselected()
287            || $this->areResponsiblePersonsPreselected()
288            || $this->hasDefaultRecipients()
289        ;
290    }
291
292    /**
293     * @return array
294     */
295    public function getResponsiblePersons()
296    {
297        if (!isset($this->responsiblePersons)) {
298            $this->responsiblePersons = [];
299            if (!empty($this->record['responsible_persons'])) {
300                $this->responsiblePersons = $this->getStagesService()->resolveBackendUserIds($this->record['responsible_persons']);
301            }
302        }
303        return $this->responsiblePersons;
304    }
305
306    /**
307     * @return array
308     */
309    public function getDefaultRecipients()
310    {
311        if (!isset($this->defaultRecipients)) {
312            $this->defaultRecipients = $this->getStagesService()->resolveBackendUserIds($this->record['notification_defaults']);
313        }
314        return $this->defaultRecipients;
315    }
316
317    /**
318     * Gets all recipients (backend user ids).
319     *
320     * @return array
321     */
322    public function getAllRecipients()
323    {
324        if (!isset($this->allRecipients)) {
325            $allRecipients = $this->getDefaultRecipients();
326
327            if ($this->isInternal() || $this->areOwnersPreselected()) {
328                $allRecipients = array_merge($allRecipients, $this->getWorkspace()->getOwners());
329            }
330            if ($this->isInternal() || $this->areMembersPreselected()) {
331                $allRecipients = array_merge($allRecipients, $this->getWorkspace()->getMembers());
332            }
333            if (!$this->isInternal()) {
334                $allRecipients = array_merge($allRecipients, $this->getResponsiblePersons());
335            }
336
337            $this->allRecipients = array_unique($allRecipients);
338        }
339
340        return $this->allRecipients;
341    }
342
343    /**
344     * @return int[]
345     */
346    public function getPreselectedRecipients()
347    {
348        if (!isset($this->preselectedRecipients)) {
349            $preselectedRecipients = $this->getDefaultRecipients();
350
351            if ($this->areOwnersPreselected()) {
352                $preselectedRecipients = array_merge($preselectedRecipients, $this->getWorkspace()->getOwners());
353            }
354            if ($this->areMembersPreselected()) {
355                $preselectedRecipients = array_merge($preselectedRecipients, $this->getWorkspace()->getMembers());
356            }
357            if ($this->areResponsiblePersonsPreselected()) {
358                $preselectedRecipients = array_merge($preselectedRecipients, $this->getResponsiblePersons());
359            }
360
361            $this->preselectedRecipients = array_unique($preselectedRecipients);
362        }
363
364        return $this->preselectedRecipients;
365    }
366
367    /**
368     * @return bool
369     */
370    public function isAllowed()
371    {
372        return
373            $this->isEditStage()
374            || static::getBackendUser()->workspaceCheckStageForCurrent($this->getUid())
375            || $this->isExecuteStage() && static::getBackendUser()->workspacePublishAccess($this->workspace->getUid())
376        ;
377    }
378}
379