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