[TASK] Add verbose output to report mail for failed tests
[Packages/TYPO3.CMS.git] / typo3 / sysext / reports / Classes / Report / Status / Status.php
1 <?php
2 namespace TYPO3\CMS\Reports\Report\Status;
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\Reports\ExtendedStatusProviderInterface;
18 use TYPO3\CMS\Reports\ReportInterface;
19 use TYPO3\CMS\Reports\StatusProviderInterface;
20
21 /**
22 * The status report
23 *
24 * @author Ingo Renner <ingo@typo3.org>
25 */
26 class Status implements ReportInterface {
27
28 /**
29 * @var StatusProviderInterface[][]
30 */
31 protected $statusProviders = array();
32
33 /**
34 * Constructor for class tx_reports_report_Status
35 */
36 public function __construct() {
37 $this->getStatusProviders();
38 $GLOBALS['LANG']->includeLLFile('EXT:reports/reports/locallang.xlf');
39 }
40
41 /**
42 * Takes care of creating / rendering the status report
43 *
44 * @return string The status report as HTML
45 */
46 public function getReport() {
47 $content = '';
48 $status = $this->getSystemStatus();
49 $highestSeverity = $this->getHighestSeverity($status);
50 // Updating the registry
51 $registry = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Registry');
52 $registry->set('tx_reports', 'status.highestSeverity', $highestSeverity);
53 $content .= '<p class="lead">' . $GLOBALS['LANG']->getLL('status_report_explanation') . '</p>';
54 return $content . $this->renderStatus($status);
55 }
56
57 /**
58 * Gets all registered status providers and creates instances of them.
59 *
60 * @return void
61 */
62 protected function getStatusProviders() {
63 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['reports']['tx_reports']['status']['providers'] as $key => $statusProvidersList) {
64 $this->statusProviders[$key] = array();
65 foreach ($statusProvidersList as $statusProvider) {
66 $statusProviderInstance = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance($statusProvider);
67 if ($statusProviderInstance instanceof StatusProviderInterface) {
68 $this->statusProviders[$key][] = $statusProviderInstance;
69 }
70 }
71 }
72 }
73
74 /**
75 * Runs through all status providers and returns all statuses collected.
76 *
77 * @return \TYPO3\CMS\Reports\Status[]
78 */
79 public function getSystemStatus() {
80 $status = array();
81 foreach ($this->statusProviders as $statusProviderId => $statusProviderList) {
82 $status[$statusProviderId] = array();
83 foreach ($statusProviderList as $statusProvider) {
84 $statuses = $statusProvider->getStatus();
85 $status[$statusProviderId] = array_merge($status[$statusProviderId], $statuses);
86 }
87 }
88 return $status;
89 }
90
91 /**
92 * Runs through all status providers and returns all statuses collected, which are detailed.
93 *
94 * @return \TYPO3\CMS\Reports\Status[]
95 */
96 public function getDetailedSystemStatus() {
97 $status = array();
98 foreach ($this->statusProviders as $statusProviderId => $statusProviderList) {
99 $status[$statusProviderId] = array();
100 foreach ($statusProviderList as $statusProvider) {
101 if ($statusProvider instanceof ExtendedStatusProviderInterface) {
102 $statuses = $statusProvider->getDetailedStatus();
103 $status[$statusProviderId] = array_merge($status[$statusProviderId], $statuses);
104 }
105 }
106 }
107 return $status;
108 }
109
110 /**
111 * Determines the highest severity from the given statuses.
112 *
113 * @param array $statusCollection An array of \TYPO3\CMS\Reports\Status objects.
114 * @return int The highest severity found from the statuses.
115 */
116 public function getHighestSeverity(array $statusCollection) {
117 $highestSeverity = \TYPO3\CMS\Reports\Status::NOTICE;
118 foreach ($statusCollection as $statusProvider => $providerStatuses) {
119 /** @var $status \TYPO3\CMS\Reports\Status */
120 foreach ($providerStatuses as $status) {
121 if ($status->getSeverity() > $highestSeverity) {
122 $highestSeverity = $status->getSeverity();
123 }
124 // Reached the highest severity level, no need to go on
125 if ($highestSeverity == \TYPO3\CMS\Reports\Status::ERROR) {
126 break;
127 }
128 }
129 }
130 return $highestSeverity;
131 }
132
133 /**
134 * Renders the system's status
135 *
136 * @param array $statusCollection An array of statuses as returned by the available status providers
137 * @return string The system status as an HTML table
138 */
139 protected function renderStatus(array $statusCollection) {
140 // TODO refactor into separate methods, status list and single status
141 $content = '';
142 $template = '
143 <div class="alert alert-###CLASS###">
144 <div class="header-container">
145 <div class="message-header message-left">###HEADER###</div>
146 <div class="message-header message-right">###STATUS###</div>
147 </div>
148 <div class="message-body">###CONTENT###</div>
149 </div>';
150 $statuses = $this->sortStatusProviders($statusCollection);
151 foreach ($statuses as $provider => $providerStatus) {
152 $providerState = $this->sortStatuses($providerStatus);
153 $id = str_replace(' ', '-', $provider);
154 $classes = array(
155 \TYPO3\CMS\Reports\Status::NOTICE => 'notice',
156 \TYPO3\CMS\Reports\Status::INFO => 'info',
157 \TYPO3\CMS\Reports\Status::OK => 'success',
158 \TYPO3\CMS\Reports\Status::WARNING => 'warning',
159 \TYPO3\CMS\Reports\Status::ERROR => 'danger'
160 );
161 $icon[\TYPO3\CMS\Reports\Status::WARNING] = \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('status-dialog-warning');
162 $icon[\TYPO3\CMS\Reports\Status::ERROR] = \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('status-dialog-error');
163 $messages = '';
164 $headerIcon = '';
165 $sectionSeverity = 0;
166 /** @var $status \TYPO3\CMS\Reports\Status */
167 foreach ($providerState as $status) {
168 $severity = $status->getSeverity();
169 $sectionSeverity = $severity > $sectionSeverity ? $severity : $sectionSeverity;
170 $messages .= strtr($template, array(
171 '###CLASS###' => $classes[$severity],
172 '###HEADER###' => $status->getTitle(),
173 '###STATUS###' => $status->getValue(),
174 '###CONTENT###' => $status->getMessage()
175 ));
176 }
177 if ($sectionSeverity > 0) {
178 $headerIcon = $icon[$sectionSeverity];
179 }
180 $content .= $GLOBALS['TBE_TEMPLATE']->collapseableSection($headerIcon . $provider, $messages, $id, 'reports.states');
181 }
182 return $content;
183 }
184
185 /**
186 * Sorts the status providers (alphabetically and puts primary status providers at the beginning)
187 *
188 * @param array $statusCollection A collection of statuses (with providers)
189 * @return array The collection of statuses sorted by provider (beginning with provider "_install")
190 */
191 protected function sortStatusProviders(array $statusCollection) {
192 // Extract the primary status collections, i.e. the status groups
193 // that must appear on top of the status report
194 // Change their keys to localized collection titles
195 $primaryStatuses = array(
196 $GLOBALS['LANG']->getLL('status_typo3') => $statusCollection['typo3'],
197 $GLOBALS['LANG']->getLL('status_system') => $statusCollection['system'],
198 $GLOBALS['LANG']->getLL('status_security') => $statusCollection['security'],
199 $GLOBALS['LANG']->getLL('status_configuration') => $statusCollection['configuration']
200 );
201 unset($statusCollection['typo3'], $statusCollection['system'], $statusCollection['security'], $statusCollection['configuration']);
202 // Assemble list of secondary status collections with left-over collections
203 // Change their keys using localized labels if available
204 // TODO extract into getLabel() method
205 $secondaryStatuses = array();
206 foreach ($statusCollection as $statusProviderId => $collection) {
207 $label = '';
208 if (strpos($statusProviderId, 'LLL:') === 0) {
209 // Label provided by extension
210 $label = $GLOBALS['LANG']->sL($statusProviderId);
211 } else {
212 // Generic label
213 $label = $GLOBALS['LANG']->getLL('status_' . $statusProviderId);
214 }
215 $providerLabel = empty($label) ? $statusProviderId : $label;
216 $secondaryStatuses[$providerLabel] = $collection;
217 }
218 // Sort the secondary status collections alphabetically
219 ksort($secondaryStatuses);
220 $orderedStatusCollection = array_merge($primaryStatuses, $secondaryStatuses);
221 return $orderedStatusCollection;
222 }
223
224 /**
225 * Sorts the statuses by severity
226 *
227 * @param array $statusCollection A collection of statuses per provider
228 * @return array The collection of statuses sorted by severity
229 */
230 protected function sortStatuses(array $statusCollection) {
231 $statuses = array();
232 $sortTitle = array();
233 $header = NULL;
234 /** @var $status \TYPO3\CMS\Reports\Status */
235 foreach ($statusCollection as $status) {
236 if ($status->getTitle() === 'TYPO3') {
237 $header = $status;
238 continue;
239 }
240 $statuses[] = $status;
241 $sortTitle[] = $status->getSeverity();
242 }
243 array_multisort($sortTitle, SORT_DESC, $statuses);
244 // Making sure that the core version information is always on the top
245 if (is_object($header)) {
246 array_unshift($statuses, $header);
247 }
248 return $statuses;
249 }
250
251 }