[BUGFIX] Fix wrong image reference in ext:taskcenter
[Packages/TYPO3.CMS.git] / typo3 / sysext / taskcenter / Classes / Controller / TaskModuleController.php
1 <?php
2 namespace TYPO3\CMS\Taskcenter\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\Utility\BackendUtility;
18 use TYPO3\CMS\Backend\Utility\IconUtility;
19 use TYPO3\CMS\Core\Messaging\FlashMessage;
20 use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
21 use TYPO3\CMS\Core\Utility\GeneralUtility;
22
23 /**
24 * This class provides a taskcenter for BE users
25 *
26 * @author Georg Ringer <typo3@ringerge.org>
27 */
28 class TaskModuleController extends \TYPO3\CMS\Backend\Module\BaseScriptClass {
29
30 /**
31 * @var array
32 */
33 protected $pageinfo;
34
35 /**
36 * The name of the module
37 *
38 * @var string
39 */
40 protected $moduleName = 'user_task';
41
42 /**
43 * Initializes the Module
44 *
45 * @return void
46 */
47 public function __construct() {
48 $this->getLanguageService()->includeLLFile('EXT:taskcenter/task/locallang.xlf');
49 $this->MCONF = array(
50 'name' => $this->moduleName
51 );
52 parent::init();
53 // Initialize document
54 $this->doc = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Template\DocumentTemplate::class);
55 $this->doc->setModuleTemplate(ExtensionManagementUtility::extPath('taskcenter') . 'Resources/Private/Templates/mod_template.html');
56 $this->doc->backPath = $GLOBALS['BACK_PATH'];
57 $this->doc->getPageRenderer()->loadJquery();
58 $this->doc->addStyleSheet('tx_taskcenter', '../' . ExtensionManagementUtility::siteRelPath('taskcenter') . 'Resources/Public/Styles/styles.css');
59 }
60
61 /**
62 * Adds items to the ->MOD_MENU array. Used for the function menu selector.
63 *
64 * @return void
65 */
66 public function menuConfig() {
67 $this->MOD_MENU = array('mode' => array());
68 $this->MOD_MENU['mode']['information'] = $this->getLanguageService()->sL('LLL:EXT:taskcenter/locallang.xlf:task_overview');
69 $this->MOD_MENU['mode']['tasks'] = 'Tasks';
70 parent::menuConfig();
71 }
72
73 /**
74 * Creates the module's content. In this case it rather acts as a kind of #
75 * dispatcher redirecting requests to specific tasks.
76 *
77 * @return void
78 */
79 public function main() {
80 $docHeaderButtons = $this->getButtons();
81 $markers = array();
82 $this->doc->postCode = $this->doc->wrapScriptTags('if (top.fsMod) { top.fsMod.recentIds["web"] = 0; }');
83
84 // Render content depending on the mode
85 $mode = (string)$this->MOD_SETTINGS['mode'];
86 if ($mode === 'information') {
87 $this->renderInformationContent();
88 } else {
89 $this->renderModuleContent();
90 }
91 // Compile document
92 $markers['FUNC_MENU'] = \TYPO3\CMS\Backend\Utility\BackendUtility::getFuncMenu(0, 'SET[mode]', $this->MOD_SETTINGS['mode'], $this->MOD_MENU['mode']);
93 $markers['CONTENT'] = $this->content;
94 // Build the <body> for the module
95 $this->content = $this->doc->moduleBody($this->pageinfo, $docHeaderButtons, $markers);
96 // Renders the module page
97 $this->content = $this->doc->render($this->getLanguageService()->getLL('title'), $this->content);
98 }
99
100 /**
101 * Prints out the module's HTML
102 *
103 * @return void
104 */
105 public function printContent() {
106 echo $this->content;
107 }
108
109 /**
110 * Generates the module content by calling the selected task
111 *
112 * @return void
113 */
114 protected function renderModuleContent() {
115 $title = ($content = ($actionContent = ''));
116 $chosenTask = (string)$this->MOD_SETTINGS['function'];
117 // Render the taskcenter task as default
118 if (empty($chosenTask) || $chosenTask == 'index') {
119 $chosenTask = 'taskcenter.tasks';
120 }
121 // Render the task
122 list($extKey, $taskClass) = explode('.', $chosenTask, 2);
123 $title = $this->getLanguageService()->sL($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['taskcenter'][$extKey][$taskClass]['title']);
124 if (class_exists($taskClass)) {
125 $taskInstance = GeneralUtility::makeInstance($taskClass, $this);
126 if ($taskInstance instanceof \TYPO3\CMS\Taskcenter\TaskInterface) {
127 // Check if the task is restricted to admins only
128 if ($this->checkAccess($extKey, $taskClass)) {
129 $actionContent .= $taskInstance->getTask();
130 } else {
131 $flashMessage = GeneralUtility::makeInstance(
132 FlashMessage::class,
133 $this->getLanguageService()->getLL('error-access', TRUE),
134 $this->getLanguageService()->getLL('error_header'),
135 FlashMessage::ERROR
136 );
137 $actionContent .= $flashMessage->render();
138 }
139 } else {
140 // Error if the task is not an instance of \TYPO3\CMS\Taskcenter\TaskInterface
141 $flashMessage = GeneralUtility::makeInstance(
142 FlashMessage::class,
143 sprintf($this->getLanguageService()->getLL('error_no-instance', TRUE), $taskClass, \TYPO3\CMS\Taskcenter\TaskInterface::class),
144 $this->getLanguageService()->getLL('error_header'),
145 FlashMessage::ERROR
146 );
147 $actionContent .= $flashMessage->render();
148 }
149 } else {
150 $flashMessage = GeneralUtility::makeInstance(
151 FlashMessage::class,
152 $this->getLanguageService()->sL('LLL:EXT:taskcenter/task/locallang_mod.xlf:mlang_labels_tabdescr'),
153 $this->getLanguageService()->sL('LLL:EXT:taskcenter/task/locallang_mod.xlf:mlang_tabs_tab'),
154 FlashMessage::INFO
155 );
156 $actionContent .= $flashMessage->render();
157 }
158 $content = '<div id="taskcenter-main">
159 <div id="taskcenter-menu">' . $this->indexAction() . '</div>
160 <div id="taskcenter-item" class="' . htmlspecialchars(($extKey . '-' . $taskClass)) . '">' . $actionContent . '
161 </div>
162 </div>';
163 $this->content .= $content;
164 }
165
166 /**
167 * Generates the information content
168 *
169 * @return void
170 */
171 protected function renderInformationContent() {
172 $content = $this->description($this->getLanguageService()->getLL('mlang_tabs_tab'), $this->getLanguageService()->sL('LLL:EXT:taskcenter/task/locallang_mod.xlf:mlang_labels_tabdescr'));
173 $content .= $this->getLanguageService()->getLL('taskcenter-about');
174 if ($this->getBackendUser()->isAdmin()) {
175 $content .= '<br /><br />' . $this->description($this->getLanguageService()->getLL('taskcenter-adminheader'), $this->getLanguageService()->getLL('taskcenter-admin'));
176 }
177 $this->content .= $content;
178 }
179
180 /**
181 * Render the headline of a task including a title and an optional description.
182 *
183 * @param string $title Title
184 * @param string $description Description
185 * @return string formatted title and description
186 */
187 public function description($title, $description = '') {
188 $content = '<h1>' . nl2br(htmlspecialchars($title)) . '</h1>';
189 if (!empty($description)) {
190 $content .= '<p class="description">' . nl2br(htmlspecialchars($description)) . '</p>';
191 }
192 return $content;
193 }
194
195 /**
196 * Render a list of items as a nicely formated definition list including a
197 * link, icon, title and description.
198 * The keys of a single item are:
199 * - title: Title of the item
200 * - link: Link to the task
201 * - icon: Path to the icon or Icon as HTML if it begins with <img
202 * - description: Description of the task, using htmlspecialchars()
203 * - descriptionHtml: Description allowing HTML tags which will override the
204 * description
205 *
206 * @param array $items List of items to be displayed in the definition list.
207 * @param bool $mainMenu Set it to TRUE to render the main menu
208 * @return string Fefinition list
209 */
210 public function renderListMenu($items, $mainMenu = FALSE) {
211 $content = ($section = '');
212 $count = 0;
213 // Change the sorting of items to the user's one
214 if ($mainMenu) {
215 $this->doc->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Taskcenter/Taskcenter');
216 $userSorting = unserialize($this->getBackendUser()->uc['taskcenter']['sorting']);
217 if (is_array($userSorting)) {
218 $newSorting = array();
219 foreach ($userSorting as $item) {
220 if (isset($items[$item])) {
221 $newSorting[] = $items[$item];
222 unset($items[$item]);
223 }
224 }
225 $items = $newSorting + $items;
226 }
227 }
228 if (is_array($items) && count($items) > 0) {
229 foreach ($items as $item) {
230 $title = htmlspecialchars($item['title']);
231 $icon = ($additionalClass = ($collapsedStyle = ''));
232 // Check for custom icon
233 if (!empty($item['icon'])) {
234 if (strpos($item['icon'], '<img ') === FALSE) {
235 $absIconPath = GeneralUtility::getFileAbsFilename($item['icon']);
236 // If the file indeed exists, assemble relative path to it
237 if (file_exists($absIconPath)) {
238 $icon = $GLOBALS['BACK_PATH'] . '../' . str_replace(PATH_site, '', $absIconPath);
239 $icon = '<img src="' . $icon . '" title="' . $title . '" alt="' . $title . '" />';
240 }
241 if (@is_file($icon)) {
242 $icon = '<img' . \TYPO3\CMS\Backend\Utility\IconUtility::skinImg($GLOBALS['BACK_PATH'], $icon, 'width="16" height="16"') . ' title="' . $title . '" alt="' . $title . '" />';
243 }
244 } else {
245 $icon = $item['icon'];
246 }
247 }
248 $description = $item['descriptionHtml'] ?: '<p>' . nl2br(htmlspecialchars($item['description'])) . '</p>';
249 $id = $this->getUniqueKey($item['uid']);
250 // Collapsed & expanded menu items
251 if ($mainMenu && isset($this->getBackendUser()->uc['taskcenter']['states'][$id]) && $this->getBackendUser()->uc['taskcenter']['states'][$id]) {
252 $collapsedStyle = 'style="display:none"';
253 $additionalClass = 'collapsed';
254 } else {
255 $additionalClass = 'expanded';
256 }
257 // First & last menu item
258 if ($count == 0) {
259 $additionalClass .= ' first-item';
260 } elseif ($count + 1 === count($items)) {
261 $additionalClass .= ' last-item';
262 }
263 // Active menu item
264 $active = (string)$this->MOD_SETTINGS['function'] == $item['uid'] ? ' active-task' : '';
265 // Main menu: Render additional syntax to sort tasks
266 if ($mainMenu) {
267 $dragIcon = \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('actions-document-move', array('title' => $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.move', TRUE)));
268 $section = '<div class="down">&nbsp;</div>
269 <div class="drag">' . $dragIcon . '</div>';
270 $backgroundClass = 't3-row-header ';
271 }
272 $content .= '<li class="' . $additionalClass . $active . '" id="el_' . $id . '">
273 ' . $section . '
274 <div class="image">' . $icon . '</div>
275 <div class="' . $backgroundClass . 'link"><a href="' . $item['link'] . '">' . $title . '</a></div>
276 <div class="content " ' . $collapsedStyle . '>' . $description . '</div>
277 </li>';
278 $count++;
279 }
280 $navigationId = $mainMenu ? 'id="task-list"' : '';
281 $content = '<ul ' . $navigationId . ' class="task-list">' . $content . '</ul>';
282 }
283 return $content;
284 }
285
286 /**
287 * Shows an overview list of available reports.
288 *
289 * @return string List of available reports
290 */
291 protected function indexAction() {
292 $content = '';
293 $tasks = array();
294 $icon = ExtensionManagementUtility::extRelPath('taskcenter') . 'Resources/Public/Icons/module-taskcenter.png';
295 // Render the tasks only if there are any available
296 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['taskcenter']) && count($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['taskcenter']) > 0) {
297 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['taskcenter'] as $extKey => $extensionReports) {
298 foreach ($extensionReports as $taskClass => $task) {
299 if (!$this->checkAccess($extKey, $taskClass)) {
300 continue;
301 }
302 $link = BackendUtility::getModuleUrl('user_task') . '&SET[function]=' . $extKey . '.' . $taskClass;
303 $taskTitle = $this->getLanguageService()->sL($task['title']);
304 $taskDescriptionHtml = '';
305 // Check for custom icon
306 if (!empty($task['icon'])) {
307 $icon = GeneralUtility::getFileAbsFilename($task['icon']);
308 }
309 if (class_exists($taskClass)) {
310 $taskInstance = GeneralUtility::makeInstance($taskClass, $this);
311 if ($taskInstance instanceof \TYPO3\CMS\Taskcenter\TaskInterface) {
312 $taskDescriptionHtml = $taskInstance->getOverview();
313 }
314 }
315 // Generate an array of all tasks
316 $uniqueKey = $this->getUniqueKey($extKey . '.' . $taskClass);
317 $tasks[$uniqueKey] = array(
318 'title' => $taskTitle,
319 'descriptionHtml' => $taskDescriptionHtml,
320 'description' => $this->getLanguageService()->sL($task['description']),
321 'icon' => $icon,
322 'link' => $link,
323 'uid' => $extKey . '.' . $taskClass
324 );
325 }
326 }
327 $content .= $this->renderListMenu($tasks, TRUE);
328 } else {
329 $flashMessage = GeneralUtility::makeInstance(
330 FlashMessage::class,
331 $this->getLanguageService()->getLL('no-tasks', TRUE),
332 '',
333 FlashMessage::INFO
334 );
335 $this->content .= $flashMessage->render();
336 }
337 return $content;
338 }
339
340 /**
341 * Create the panel of buttons for submitting the form or otherwise
342 * perform operations.
343 *
344 * @return array All available buttons as an assoc. array
345 */
346 protected function getButtons() {
347 $buttons = array(
348 'csh' => \TYPO3\CMS\Backend\Utility\BackendUtility::cshItem('_MOD_web_func', ''),
349 'shortcut' => '',
350 'open_new_window' => $this->openInNewWindow()
351 );
352 // Shortcut
353 if ($this->getBackendUser()->mayMakeShortcut()) {
354 $buttons['shortcut'] = $this->doc->makeShortcutIcon('', 'function', $this->moduleName);
355 }
356 return $buttons;
357 }
358
359 /**
360 * Check the access to a task. Considered are:
361 * - Admins are always allowed
362 * - Tasks can be restriced to admins only
363 * - Tasks can be blinded for Users with TsConfig taskcenter.<extensionkey>.<taskName> = 0
364 *
365 * @param string $extKey Extension key
366 * @param string $taskClass Name of the task
367 * @return bool Access to the task allowed or not
368 */
369 protected function checkAccess($extKey, $taskClass) {
370 // Check if task is blinded with TsConfig (taskcenter.<extkey>.<taskName>
371 $tsConfig = $this->getBackendUser()->getTSConfig('taskcenter.' . $extKey . '.' . $taskClass);
372 if (isset($tsConfig['value']) && (int)$tsConfig['value'] === 0) {
373 return FALSE;
374 }
375 // Admins are always allowed
376 if ($this->getBackendUser()->isAdmin()) {
377 return TRUE;
378 }
379 // Check if task is restricted to admins
380 if ((int)$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['taskcenter'][$extKey][$taskClass]['admin'] === 1) {
381 return FALSE;
382 }
383 return TRUE;
384 }
385
386 /**
387 * Returns HTML code to dislay an url in an iframe at the right side of the taskcenter
388 *
389 * @param string $url Url to display
390 * @param int $max
391 * @return string Code that inserts the iframe (HTML)
392 */
393 public function urlInIframe($url, $max = 0) {
394 return '<iframe scrolling="auto" width="100%" src="' . $url . '" name="list_frame" id="list_frame" frameborder="no"></iframe>';
395 }
396
397 /**
398 * Create a unique key from a string which can be used in Prototype's Sortable
399 * Therefore '_' are replaced
400 *
401 * @param string $string string which is used to generate the identifier
402 * @return string Modified string
403 */
404 protected function getUniqueKey($string) {
405 $search = array('.', '_');
406 $replace = array('-', '');
407 return str_replace($search, $replace, $string);
408 }
409
410 /**
411 * This method prepares the link for opening the devlog in a new window
412 *
413 * @return string Hyperlink with icon and appropriate JavaScript
414 */
415 protected function openInNewWindow() {
416 $url = GeneralUtility::getIndpEnv('TYPO3_REQUEST_URL');
417 $onClick = 'devlogWin=window.open(' . GeneralUtility::quoteJSvalue($url) . ',\'taskcenter\',\'width=790,status=0,menubar=1,resizable=1,location=0,scrollbars=1,toolbar=0\');return false;';
418 $content = '<a href="#" onclick="' . htmlspecialchars($onClick) . '">' .
419 IconUtility::getSpriteIcon('actions-window-open', array('title' => $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.openInNewWindow', TRUE))) .
420 '</a>';
421 return $content;
422 }
423
424 /**
425 * Returns the current BE user.
426 *
427 * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
428 */
429 protected function getBackendUser() {
430 return $GLOBALS['BE_USER'];
431 }
432
433 /**
434 * Returns LanguageService
435 *
436 * @return \TYPO3\CMS\Lang\LanguageService
437 */
438 protected function getLanguageService() {
439 return $GLOBALS['LANG'];
440 }
441
442 }