[CLEANUP] The correct case must be used for standard PHP types in phpdoc
[Packages/TYPO3.CMS.git] / typo3 / sysext / belog / Classes / Controller / AbstractController.php
1 <?php
2 namespace TYPO3\CMS\Belog\Controller;
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\View\BackendTemplateView;
18 use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
19 use TYPO3\CMS\Extbase\Mvc\View\ViewInterface;
20
21 /**
22 * Abstract class to show log entries from sys_log
23 */
24 abstract class AbstractController extends ActionController
25 {
26 /**
27 * @var int
28 */
29 const TIMEFRAME_THISWEEK = 0;
30
31 /**
32 * @var int
33 */
34 const TIMEFRAME_LASTWEEK = 1;
35
36 /**
37 * @var int
38 */
39 const TIMEFRAME_LASTSEVENDAYS = 2;
40
41 /**
42 * @var int
43 */
44 const TIMEFRAME_THISMONTH = 10;
45
46 /**
47 * @var int
48 */
49 const TIMEFRAME_LASTMONTH = 11;
50
51 /**
52 * @var int
53 */
54 const TIMEFRAME_LAST31DAYS = 12;
55
56 /**
57 * @var int
58 */
59 const TIMEFRAME_CUSTOM = 30;
60
61 /**
62 * Whether plugin is running in page context (sub module of Web > Info)
63 *
64 * @var bool
65 */
66 protected $isInPageContext = false;
67
68 /**
69 * Page ID in page context
70 *
71 * @var int
72 */
73 protected $pageId = 0;
74
75 /**
76 * @var \TYPO3\CMS\Belog\Domain\Repository\LogEntryRepository
77 */
78 protected $logEntryRepository = null;
79
80 /**
81 * @var BackendTemplateView
82 */
83 protected $view;
84
85 /**
86 * @param \TYPO3\CMS\Belog\Domain\Repository\LogEntryRepository $logEntryRepository
87 */
88 public function injectLogEntryRepository(\TYPO3\CMS\Belog\Domain\Repository\LogEntryRepository $logEntryRepository)
89 {
90 $this->logEntryRepository = $logEntryRepository;
91 }
92
93 /**
94 * Initialize the view
95 *
96 * @param ViewInterface $view The view
97 */
98 protected function initializeView(ViewInterface $view)
99 {
100 if ($view instanceof BackendTemplateView) {
101 parent::initializeView($view);
102 $view->getModuleTemplate()->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/DateTimePicker');
103 }
104 }
105
106 /**
107 * init all actions
108 */
109 public function initializeAction()
110 {
111 if ($this->isInPageContext === false) {
112 $this->defaultViewObjectName = BackendTemplateView::class;
113 }
114 }
115
116 /**
117 * Initialize index action
118 *
119 * @throws \RuntimeException
120 */
121 public function initializeIndexAction()
122 {
123 // @TODO: Extbase backend modules rely on frontend TypoScript for view, persistence
124 // and settings. Thus, we need a TypoScript root template, that then loads the
125 // ext_typoscript_setup.txt file of this module. This is nasty, but can not be
126 // circumvented until there is a better solution in extbase.
127 // For now we throw an exception if no settings are detected.
128 if (empty($this->settings)) {
129 throw new \RuntimeException(
130 'No settings detected. This usually happens if there is no frontend TypoScript template with root flag set. Please create one.',
131 1333650506
132 );
133 }
134 if (!isset($this->settings['dateFormat'])) {
135 $this->settings['dateFormat'] = $GLOBALS['TYPO3_CONF_VARS']['SYS']['USdateFormat'] ? 'm-d-Y' : 'd-m-Y';
136 }
137 if (!isset($this->settings['timeFormat'])) {
138 $this->settings['timeFormat'] = $GLOBALS['TYPO3_CONF_VARS']['SYS']['hhmm'];
139 }
140 }
141
142 /**
143 * Show general information and the installed modules
144 *
145 * @param \TYPO3\CMS\Belog\Domain\Model\Constraint $constraint
146 */
147 public function indexAction(\TYPO3\CMS\Belog\Domain\Model\Constraint $constraint = null)
148 {
149 // Constraint object handling:
150 // If there is none from GET, try to get it from BE user data, else create new
151 if ($constraint === null) {
152 $constraint = $this->getConstraintFromBeUserData();
153 if ($constraint === null) {
154 $constraint = $this->objectManager->get(\TYPO3\CMS\Belog\Domain\Model\Constraint::class);
155 }
156 } else {
157 $this->persistConstraintInBeUserData($constraint);
158 }
159 $constraint->setIsInPageContext($this->isInPageContext);
160 $constraint->setPageId($this->pageId);
161 $this->setStartAndEndTimeFromTimeSelector($constraint);
162 $this->forceWorkspaceSelectionIfInWorkspace($constraint);
163 $logEntries = $this->logEntryRepository->findByConstraint($constraint);
164 $groupedLogEntries = $this->groupLogEntriesByPageAndDay($logEntries, $constraint->getGroupByPage());
165 $this->view->assign('groupedLogEntries', $groupedLogEntries)->assign('constraint', $constraint)->assign('userGroups', $this->createUserAndGroupListForSelectOptions())->assign('workspaces', $this->createWorkspaceListForSelectOptions())->assign('pageDepths', $this->createPageDepthOptions());
166 }
167
168 /**
169 * Get module states (the constraint object) from user data
170 *
171 * @return \TYPO3\CMS\Belog\Domain\Model\Constraint|null
172 */
173 protected function getConstraintFromBeUserData()
174 {
175 $serializedConstraint = $GLOBALS['BE_USER']->getModuleData(static::class);
176 if (!is_string($serializedConstraint) || empty($serializedConstraint)) {
177 return null;
178 }
179 return @unserialize($serializedConstraint);
180 }
181
182 /**
183 * Save current constraint object in be user settings (uC)
184 *
185 * @param \TYPO3\CMS\Belog\Domain\Model\Constraint $constraint
186 */
187 protected function persistConstraintInBeUserData(\TYPO3\CMS\Belog\Domain\Model\Constraint $constraint)
188 {
189 $GLOBALS['BE_USER']->pushModuleData(static::class, serialize($constraint));
190 }
191
192 /**
193 * Create a sorted array for day and page view from
194 * the query result of the sys log repository.
195 *
196 * If group by page is FALSE, pid is always -1 (will render a flat list),
197 * otherwise the output is splitted by pages.
198 * '12345' is a sub array to split entries by day, number is first second of day
199 *
200 * [pid][dayTimestamp][items]
201 *
202 * @param \TYPO3\CMS\Extbase\Persistence\QueryResultInterface<\TYPO3\CMS\Belog\Domain\Model\LogEntry> $logEntries
203 * @param bool $groupByPage Whether or not log entries should be grouped by page
204 * @return array
205 */
206 protected function groupLogEntriesByPageAndDay(\TYPO3\CMS\Extbase\Persistence\QueryResultInterface $logEntries, $groupByPage = false)
207 {
208 $targetStructure = [];
209 /** @var $entry \TYPO3\CMS\Belog\Domain\Model\LogEntry */
210 foreach ($logEntries as $entry) {
211 // Create page split list or flat list
212 if ($groupByPage) {
213 $pid = $entry->getEventPid();
214 } else {
215 $pid = -1;
216 }
217 // Create array if it is not defined yet
218 if (!is_array($targetStructure[$pid])) {
219 $targetStructure[$pid] = [];
220 }
221 // Get day timestamp of log entry and create sub array if needed
222 $timestampDay = strtotime(strftime('%d.%m.%Y', $entry->getTstamp()));
223 if (!is_array($targetStructure[$pid][$timestampDay])) {
224 $targetStructure[$pid][$timestampDay] = [];
225 }
226 // Add row
227 $targetStructure[$pid][$timestampDay][] = $entry;
228 }
229 ksort($targetStructure);
230 return $targetStructure;
231 }
232
233 /**
234 * Create options for the user / group drop down.
235 * This is not moved to a repository by intention to not mix up this 'meta' data
236 * with real repository work
237 *
238 * @return array Key is the option name, value its label
239 */
240 protected function createUserAndGroupListForSelectOptions()
241 {
242 $userGroupArray = [];
243 // Two meta entries: 'all' and 'self'
244 $userGroupArray[0] = \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate('allUsers', 'Belog');
245 $userGroupArray[-1] = \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate('self', 'Belog');
246 // List of groups, key is gr-'uid'
247 $groups = \TYPO3\CMS\Backend\Utility\BackendUtility::getGroupNames();
248 foreach ($groups as $group) {
249 $userGroupArray['gr-' . $group['uid']] = \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate('group', 'Belog') . ' ' . $group['title'];
250 }
251 // List of users, key is us-'uid'
252 $users = \TYPO3\CMS\Backend\Utility\BackendUtility::getUserNames();
253 foreach ($users as $user) {
254 $userGroupArray['us-' . $user['uid']] = \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate('user', 'Belog') . ' ' . $user['username'];
255 }
256 return $userGroupArray;
257 }
258
259 /**
260 * Create options for the workspace selector
261 *
262 * @return array Key is uid of workspace, value its label
263 */
264 protected function createWorkspaceListForSelectOptions()
265 {
266 if (!\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('workspaces')) {
267 return [];
268 }
269 $workspaceArray = [];
270 // Two meta entries: 'all' and 'live'
271 $workspaceArray[-99] = \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate('any', 'Belog');
272 $workspaceArray[0] = \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate('live', 'Belog');
273 $workspaces = $this->objectManager->get(\TYPO3\CMS\Belog\Domain\Repository\WorkspaceRepository::class)->findAll();
274 /** @var $workspace \TYPO3\CMS\Belog\Domain\Model\Workspace */
275 foreach ($workspaces as $workspace) {
276 $workspaceArray[$workspace->getUid()] = $workspace->getUid() . ': ' . $workspace->getTitle();
277 }
278 return $workspaceArray;
279 }
280
281 /**
282 * If the user is in a workspace different than LIVE,
283 * we force to show only log entries from the selected workspace,
284 * and the workspace selector is not shown.
285 *
286 * @param \TYPO3\CMS\Belog\Domain\Model\Constraint $constraint
287 */
288 protected function forceWorkspaceSelectionIfInWorkspace(\TYPO3\CMS\Belog\Domain\Model\Constraint $constraint)
289 {
290 if ($GLOBALS['BE_USER']->workspace !== 0) {
291 $constraint->setWorkspaceUid($GLOBALS['BE_USER']->workspace);
292 $this->view->assign('showWorkspaceSelector', false);
293 } else {
294 $this->view->assign('showWorkspaceSelector', true);
295 }
296 }
297
298 /**
299 * Create options for the 'depth of page levels' selector.
300 * This is shown if the module is displayed in page -> info
301 *
302 * @return array Key is depth identifier (1 = One level), value the localized select option label
303 */
304 protected function createPageDepthOptions()
305 {
306 $options = [
307 0 => \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.depth_0', 'lang'),
308 1 => \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.depth_1', 'lang'),
309 2 => \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.depth_2', 'lang'),
310 3 => \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.depth_3', 'lang'),
311 4 => \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.depth_4', 'lang'),
312 999 => \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.depth_infi', 'lang')
313 ];
314 return $options;
315 }
316
317 /**
318 * Calculate the start- and end timestamp from the different time selector options
319 *
320 * @param \TYPO3\CMS\Belog\Domain\Model\Constraint $constraint
321 */
322 protected function setStartAndEndTimeFromTimeSelector(\TYPO3\CMS\Belog\Domain\Model\Constraint $constraint)
323 {
324 $startTime = 0;
325 $endTime = $GLOBALS['EXEC_TIME'];
326 // @TODO: Refactor this construct
327 switch ($constraint->getTimeFrame()) {
328 case self::TIMEFRAME_THISWEEK:
329 // This week
330 $week = (date('w') ?: 7) - 1;
331 $startTime = mktime(0, 0, 0) - $week * 3600 * 24;
332 break;
333 case self::TIMEFRAME_LASTWEEK:
334 // Last week
335 $week = (date('w') ?: 7) - 1;
336 $startTime = mktime(0, 0, 0) - ($week + 7) * 3600 * 24;
337 $endTime = mktime(0, 0, 0) - $week * 3600 * 24;
338 break;
339 case self::TIMEFRAME_LASTSEVENDAYS:
340 // Last 7 days
341 $startTime = mktime(0, 0, 0) - 7 * 3600 * 24;
342 break;
343 case self::TIMEFRAME_THISMONTH:
344 // This month
345 $startTime = mktime(0, 0, 0, date('m'), 1);
346 break;
347 case self::TIMEFRAME_LASTMONTH:
348 // Last month
349 $startTime = mktime(0, 0, 0, date('m') - 1, 1);
350 $endTime = mktime(0, 0, 0, date('m'), 1);
351 break;
352 case self::TIMEFRAME_LAST31DAYS:
353 // Last 31 days
354 $startTime = mktime(0, 0, 0) - 31 * 3600 * 24;
355 break;
356 case self::TIMEFRAME_CUSTOM:
357 $startTime = $constraint->getStartTimestamp();
358 if ($constraint->getEndTimestamp() > $constraint->getStartTimestamp()) {
359 $endTime = $constraint->getEndTimestamp();
360 } else {
361 $endTime = $GLOBALS['EXEC_TIME'];
362 }
363 break;
364 default:
365 }
366 $constraint->setStartTimestamp($startTime);
367 $constraint->setEndTimestamp($endTime);
368 }
369 }