[TASK] Allow multiple extractor services with the same priority
[Packages/TYPO3.CMS.git] / typo3 / sysext / workspaces / Classes / Service / IntegrityService.php
1 <?php
2 namespace TYPO3\CMS\Workspaces\Service;
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\Versioning\VersionState;
19 use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
20 use TYPO3\CMS\Workspaces\Domain\Model\CombinedRecord;
21
22 /**
23 * Service for integrity
24 */
25 class IntegrityService
26 {
27 /**
28 * Succes status - everything is fine
29 *
30 * @var int
31 */
32 const STATUS_Succes = 100;
33 /**
34 * Info status - nothing is wrong, but a notice is shown
35 *
36 * @var int
37 */
38 const STATUS_Info = 101;
39 /**
40 * Warning status - user interaction might be required
41 *
42 * @var int
43 */
44 const STATUS_Warning = 102;
45 /**
46 * Error status - user interaction is required
47 *
48 * @var int
49 */
50 const STATUS_Error = 103;
51 /**
52 * @var array
53 */
54 protected $statusRepresentation = [
55 self::STATUS_Succes => 'success',
56 self::STATUS_Info => 'info',
57 self::STATUS_Warning => 'warning',
58 self::STATUS_Error => 'error'
59 ];
60
61 /**
62 * @var CombinedRecord[]
63 */
64 protected $affectedElements;
65
66 /**
67 * Array storing all issues that have been checked and
68 * found during runtime in this object. The array keys
69 * are identifiers of table and the version-id.
70 *
71 * 'tx_table:123' => array(
72 * array(
73 * 'status' => 'warning',
74 * 'message' => 'Element cannot be...',
75 * )
76 * )
77 *
78 * @var array
79 */
80 protected $issues = [];
81
82 /**
83 * Sets the affected elements.
84 *
85 * @param CombinedRecord[] $affectedElements
86 */
87 public function setAffectedElements(array $affectedElements)
88 {
89 $this->affectedElements = $affectedElements;
90 }
91
92 /**
93 * Checks integrity of affected records.
94 */
95 public function check()
96 {
97 foreach ($this->affectedElements as $affectedElement) {
98 $this->checkElement($affectedElement);
99 }
100 }
101
102 /**
103 * Checks a single element.
104 *
105 * @param CombinedRecord $element
106 */
107 public function checkElement(CombinedRecord $element)
108 {
109 $this->checkLocalization($element);
110 }
111
112 /**
113 * Checks workspace localization integrity of a single elements.
114 * If current record is a localization and its localization parent
115 * is new in this workspace (has only a placeholder record in live),
116 * then boths (localization and localization parent) should be published.
117 *
118 * @param CombinedRecord $element
119 */
120 protected function checkLocalization(CombinedRecord $element)
121 {
122 $table = $element->getTable();
123 if (BackendUtility::isTableLocalizable($table)) {
124 $languageField = $GLOBALS['TCA'][$table]['ctrl']['languageField'];
125 $languageParentField = $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'];
126 $versionRow = $element->getVersionRecord()->getRow();
127 // If element is a localization:
128 if ($versionRow[$languageField] > 0) {
129 // Get localization parent from live workspace:
130 $languageParentRecord = BackendUtility::getRecord($table, $versionRow[$languageParentField], 'uid,t3ver_state');
131 // If localization parent is a "new placeholder" record:
132 if (VersionState::cast($languageParentRecord['t3ver_state'])->equals(VersionState::NEW_PLACEHOLDER)) {
133 $title = BackendUtility::getRecordTitle($table, $versionRow);
134 // Add warning for current versionized record:
135 $this->addIssue($element->getLiveRecord()->getIdentifier(), self::STATUS_Warning, sprintf(LocalizationUtility::translate('integrity.dependsOnDefaultLanguageRecord', 'workspaces'), $title));
136 // Add info for related localization parent record:
137 $this->addIssue($table . ':' . $languageParentRecord['uid'], self::STATUS_Info, sprintf(LocalizationUtility::translate('integrity.isDefaultLanguageRecord', 'workspaces'), $title));
138 }
139 }
140 }
141 }
142
143 /**
144 * Gets the status of the most important severity.
145 * (low << success, info, warning, error >> high)
146 *
147 * @param string $identifier Record identifier (table:id) for look-ups
148 * @return string
149 */
150 public function getStatus($identifier = null)
151 {
152 $status = self::STATUS_Succes;
153 if ($identifier === null) {
154 foreach ($this->issues as $idenfieriferIssues) {
155 foreach ($idenfieriferIssues as $issue) {
156 if ($status < $issue['status']) {
157 $status = $issue['status'];
158 }
159 }
160 }
161 } else {
162 foreach ($this->getIssues($identifier) as $issue) {
163 if ($status < $issue['status']) {
164 $status = $issue['status'];
165 }
166 }
167 }
168 return $status;
169 }
170
171 /**
172 * Gets the (human readable) represetation of the status with the most
173 * important severity (wraps $this->getStatus() and translates the result).
174 *
175 * @param string $identifier Record identifier (table:id) for look-ups
176 * @return string One out of success, info, warning, error
177 */
178 public function getStatusRepresentation($identifier = null)
179 {
180 return $this->statusRepresentation[$this->getStatus($identifier)];
181 }
182
183 /**
184 * Gets issues, all or specific for one identifier.
185 *
186 * @param string $identifier Record identifier (table:id) for look-ups
187 * @return array
188 */
189 public function getIssues($identifier = null)
190 {
191 if ($identifier === null) {
192 return $this->issues;
193 }
194 if (isset($this->issues[$identifier])) {
195 return $this->issues[$identifier];
196 }
197 return [];
198 }
199
200 /**
201 * Gets the message of all issues.
202 *
203 * @param string $identifier Record identifier (table:id) for look-ups
204 * @param bool $asString Return results as string instead of array
205 * @return array|string
206 */
207 public function getIssueMessages($identifier = null, $asString = false)
208 {
209 $messages = [];
210 if ($identifier === null) {
211 foreach ($this->issues as $idenfieriferIssues) {
212 foreach ($idenfieriferIssues as $issue) {
213 $messages[] = $issue['message'];
214 }
215 }
216 } else {
217 foreach ($this->getIssues($identifier) as $issue) {
218 $messages[] = $issue['message'];
219 }
220 }
221 if ($asString) {
222 $messages = implode('<br/>', $messages);
223 }
224 return $messages;
225 }
226
227 /**
228 * Adds an issue.
229 *
230 * @param string $identifier Record identifier (table:id)
231 * @param int $status Status code (see constants)
232 * @param string $message Message/description of the issue
233 */
234 protected function addIssue($identifier, $status, $message)
235 {
236 if (!isset($this->issues[$identifier])) {
237 $this->issues[$identifier] = [];
238 }
239 $this->issues[$identifier][] = [
240 'status' => $status,
241 'message' => $message
242 ];
243 }
244 }