Follow-up to 15691: Javascript Error in taskcenter
[Packages/TYPO3.CMS.git] / typo3 / sysext / taskcenter / task / index.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2010 Georg Ringer <typo3@ringerge.org>
6 * All rights reserved
7 *
8 * This script is part of the TYPO3 project. The TYPO3 project is
9 * free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
16 *
17 * This script is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * This copyright notice MUST APPEAR in all copies of the script!
23 ***************************************************************/
24
25
26 /**
27 * This class provides a taskcenter for BE users
28 *
29 * @author Georg Ringer <typo3@ringerge.org>
30 * @package TYPO3
31 * @subpackage taskcenter
32 *
33 */
34
35
36 $LANG->includeLLFile('EXT:taskcenter/task/locallang.xml');
37
38
39 $BE_USER->modAccess($MCONF, 1);
40
41
42 // ***************************
43 // Script Classes
44 // ***************************
45 class SC_mod_user_task_index extends t3lib_SCbase {
46
47 protected $pageinfo;
48
49 /**
50 * Initializes the Module
51 *
52 * @return void
53 */
54 public function __construct() {
55 parent::init();
56
57 // initialize document
58 $this->doc = t3lib_div::makeInstance('template');
59 $this->doc->setModuleTemplate(
60 t3lib_extMgm::extPath('taskcenter') . 'res/mod_template.html'
61 );
62 $this->doc->backPath = $GLOBALS['BACK_PATH'];
63 $this->doc->getPageRenderer()->loadScriptaculous('effects,dragdrop');
64 $this->doc->addStyleSheet(
65 'tx_taskcenter',
66 '../' . t3lib_extMgm::siteRelPath('taskcenter') . 'res/mod_styles.css'
67 );
68 }
69
70 /**
71 * Adds items to the ->MOD_MENU array. Used for the function menu selector.
72 *
73 * @return void
74 */
75 public function menuConfig() {
76 $this->MOD_MENU = array('mode' => array());
77
78 $this->MOD_MENU['mode']['information'] = $GLOBALS['LANG']->sL('LLL:EXT:taskcenter/locallang.xml:task_overview');
79 $this->MOD_MENU['mode']['tasks'] = 'Tasks';
80
81 parent::menuConfig();
82 }
83
84 /**
85 * Creates the module's content. In this case it rather acts as a kind of #
86 * dispatcher redirecting requests to specific tasks.
87 *
88 * @return void
89 */
90 public function main() {
91 $docHeaderButtons = $this->getButtons();
92 $markers = array();
93
94 $this->doc->JScodeArray[] = '
95 script_ended = 0;
96 function jumpToUrl(URL) {
97 document.location = URL;
98 }
99 ';
100 $this->doc->postCode='
101 <script language="javascript" type="text/javascript">
102 script_ended = 1;
103 if (top.fsMod) {
104 top.fsMod.recentIds["web"] = 0;
105 }
106 </script>
107 ';
108
109 // Render content depending on the mode
110 $mode = (string)$this->MOD_SETTINGS['mode'];
111 if ($mode == 'information') {
112 $this->renderInformationContent();
113 } else {
114 $this->renderModuleContent();
115 }
116
117 // compile document
118 $markers['FUNC_MENU'] = t3lib_BEfunc::getFuncMenu(
119 0,
120 'SET[mode]',
121 $this->MOD_SETTINGS['mode'],
122 $this->MOD_MENU['mode']
123 );
124 $markers['CONTENT'] = $this->content;
125
126 // Build the <body> for the module
127 $this->content = $this->doc->startPage($GLOBALS['LANG']->getLL('title'));
128 $this->content .= $this->doc->moduleBody($this->pageinfo, $docHeaderButtons, $markers);
129 $this->content .= $this->doc->endPage();
130 $this->content = $this->doc->insertStylesAndJS($this->content);
131 }
132
133 /**
134 * Prints out the module's HTML
135 *
136 * @return void
137 */
138 public function printContent() {
139 echo $this->content;
140 }
141
142 /**
143 * Generates the module content by calling the selected task
144 *
145 * @return void
146 */
147 protected function renderModuleContent() {
148 $title = $content = $actionContent = '';
149 $chosenTask = (string)$this->MOD_SETTINGS['function'];
150
151 // render the taskcenter task as default
152 if (empty($chosenTask) || $chosenTask == 'index') {
153 $chosenTask = 'taskcenter.tasks';
154 }
155
156 // remder the task
157 list($extKey, $taskClass) = explode('.', $chosenTask, 2);
158 $title = $GLOBALS['LANG']->sL($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['taskcenter'][$extKey][$taskClass]['title']);
159
160 if (class_exists($taskClass)) {
161 $taskInstance = t3lib_div::makeInstance($taskClass, $this);
162
163 if ($taskInstance instanceof tx_taskcenter_Task) {
164 // check if the task is restricted to admins only
165 if ($this->checkAccess($extKey, $taskClass)) {
166 $actionContent .= $taskInstance->getTask();
167 } else {
168 $flashMessage = t3lib_div::makeInstance(
169 't3lib_FlashMessage',
170 $GLOBALS['LANG']->getLL('error-access', TRUE),
171 $GLOBALS['LANG']->getLL('error_header'),
172 t3lib_FlashMessage::ERROR
173 );
174 $actionContent .= $flashMessage->render();
175 }
176 } else {
177 // error if the task is not an instance of tx_taskcenter_Task
178 $flashMessage = t3lib_div::makeInstance(
179 't3lib_FlashMessage',
180 sprintf($GLOBALS['LANG']->getLL('error_no-instance', TRUE), $taskClass, 'tx_taskcenter_Task'),
181 $GLOBALS['LANG']->getLL('error_header'),
182 t3lib_FlashMessage::ERROR
183 );
184 $actionContent .= $flashMessage->render();
185 }
186 } else {
187 $flashMessage = t3lib_div::makeInstance(
188 't3lib_FlashMessage',
189 $GLOBALS['LANG']->sL('LLL:EXT:taskcenter/task/locallang_mod.xml:mlang_labels_tabdescr'),
190 $GLOBALS['LANG']->sL('LLL:EXT:taskcenter/task/locallang_mod.xml:mlang_tabs_tab'),
191 t3lib_FlashMessage::INFO
192 );
193 $actionContent .= $flashMessage->render();
194 }
195
196 $content = '<div id="taskcenter-main">
197 <div id="taskcenter-menu">' . $this->indexAction() . '</div>
198 <div id="taskcenter-item" class="' . htmlspecialchars($extKey . '-' . $taskClass) . '">' .
199 $actionContent . '
200 </div>
201 </div>';
202
203 $this->content .= $content;
204 }
205
206 /**
207 * Generates the information content
208 *
209 * @return void
210 */
211 protected function renderInformationContent() {
212 $content = $this->description (
213 $GLOBALS['LANG']->getLL('mlang_tabs_tab'),
214 $GLOBALS['LANG']->sL('LLL:EXT:taskcenter/task/locallang_mod.xml:mlang_labels_tabdescr')
215 );
216
217 $content .= $GLOBALS['LANG']->getLL('taskcenter-about');
218
219 if ($GLOBALS['BE_USER']->isAdmin()) {
220 $content .= '<br /><br />' . $this->description (
221 $GLOBALS['LANG']->getLL('taskcenter-adminheader'),
222 $GLOBALS['LANG']->getLL('taskcenter-admin')
223 );
224 }
225
226 $this->content .= $content;
227 }
228
229 /**
230 * Render the headline of a task including a title and an optional description.
231 *
232 * @param string $title: Title
233 * @param string $description: Description
234 * @return string formatted title and description
235 */
236 public function description($title, $description='') {
237 if (!empty($description)) {
238 $description = '<p class="description">' . nl2br(htmlspecialchars($description)) . '</p><br />';
239 }
240 $content = $this->doc->section($title, $description, FALSE, TRUE);
241
242 return $content;
243 }
244
245 /**
246 * Render a list of items as a nicely formated definition list including a
247 * link, icon, title and description.
248 * The keys of a single item are:
249 * - title: Title of the item
250 * - link: Link to the task
251 * - icon: Path to the icon or Icon as HTML if it begins with <img
252 * - description: Description of the task, using htmlspecialchars()
253 * - descriptionHtml: Description allowing HTML tags which will override the
254 * description
255 *
256 * @param array $items: List of items to be displayed in the definition list.
257 * @param boolean $mainMenu: Set it to TRUE to render the main menu
258 * @return string definition list
259 */
260 public function renderListMenu($items, $mainMenu = FALSE) {
261 $content = $section = '';
262 $count = 0;
263
264 // change the sorting of items to the user's one
265 if ($mainMenu) {
266 $this->doc->getPageRenderer()->addJsFile(t3lib_extMgm::extRelPath('taskcenter') . 'res/tasklist.js');
267 $userSorting = unserialize($GLOBALS['BE_USER']->uc['taskcenter']['sorting']);
268 if (is_array($userSorting)) {
269 $newSorting = array();
270 foreach($userSorting as $item) {
271 if(isset($items[$item])) {
272 $newSorting[] = $items[$item];
273 unset($items[$item]);
274 }
275 }
276 $items = $newSorting + $items;
277 }
278 }
279
280 if (is_array($items) && count($items) > 0) {
281 foreach($items as $item) {
282 $title = htmlspecialchars($item['title']);
283
284 $icon = $additionalClass = $collapsedStyle = '';
285 // Check for custom icon
286 if (!empty($item['icon'])) {
287 if (strpos($item['icon'], '<img ') === FALSE) {
288 $absIconPath = t3lib_div::getFileAbsFilename($item['icon']);
289 // If the file indeed exists, assemble relative path to it
290 if (file_exists($absIconPath)) {
291 $icon = $GLOBALS['BACK_PATH'] . '../' . str_replace(PATH_site, '', $absIconPath);
292 $icon = '<img src="' . $icon . '" title="' . $title . '" alt="' . $title . '" />';
293 }
294 if (@is_file($icon)) {
295 $icon = '<img' . t3lib_iconworks::skinImg($GLOBALS['BACK_PATH'], $icon, 'width="16" height="16"') . ' title="' . $title . '" alt="' . $title . '" />';
296 }
297 } else {
298 $icon = $item['icon'];
299 }
300 }
301
302
303 $description = (!empty($item['descriptionHtml'])) ? $item['descriptionHtml'] : '<p>' . nl2br(htmlspecialchars($item['description'])) . '</p>';
304
305 $id = $this->getUniqueKey($item['uid']);
306
307 // collapsed & expanded menu items
308 if ($mainMenu && isset($GLOBALS['BE_USER']->uc['taskcenter']['states'][$id]) && $GLOBALS['BE_USER']->uc['taskcenter']['states'][$id]) {
309 $collapsedStyle = 'style="display:none"';
310 $additionalClass = 'collapsed';
311 } else {
312 $additionalClass = 'expanded';
313 }
314
315 // first & last menu item
316 if ($count == 0) {
317 $additionalClass .= ' first-item';
318 } elseif ($count + 1 === count($items)) {
319 $additionalClass .= ' last-item';
320 }
321
322 // active menu item
323 $active = ((string) $this->MOD_SETTINGS['function'] == $item['uid']) ? ' active-task' : '';
324
325 // Main menu: Render additional syntax to sort tasks
326 if ($mainMenu) {
327 $dragIcon = '<img' . t3lib_iconWorks::skinImg($GLOBALS['BACK_PATH'], 'gfx/move.gif', 'width="16" height="16" hspace="2"') . ' title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.move', 1) . '" alt="" />';
328 $section = '<div class="down">&nbsp;</div>
329 <div class="drag">' . $dragIcon . '</div>';
330 $backgroundClass = 't3-row-header ';
331 }
332
333 $content .= '<li class="' . $additionalClass . $active . '" id="el_' .$id . '">
334 ' . $section . '
335 <div class="image">' . $icon . '</div>
336 <div class="' . $backgroundClass . 'link"><a href="' . $item['link'] . '">' . $title . '</a></div>
337 <div class="content " ' . $collapsedStyle . '>' . $description . '</div>
338 </li>';
339
340 $count++;
341 }
342
343 $navigationId = ($mainMenu) ? 'id="task-list"' : '';
344
345 $content = '<ul ' . $navigationId . ' class="task-list">' . $content . '</ul>';
346
347 }
348
349 return $content;
350 }
351
352 /**
353 * Shows an overview list of available reports.
354 *
355 * @return string list of available reports
356 */
357 protected function indexAction() {
358 $content = '';
359 $tasks = array();
360 $icon = t3lib_extMgm::extRelPath('taskcenter') . 'task/task.gif';
361
362 // render the tasks only if there are any available
363 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['taskcenter']) && count($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['taskcenter']) > 0) {
364 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['taskcenter'] as $extKey => $extensionReports) {
365 foreach ($extensionReports as $taskClass => $task) {
366 if (!$this->checkAccess($extKey, $taskClass)) {
367 continue;
368 }
369 $link = 'mod.php?M=user_task&SET[function]=' . $extKey . '.' . $taskClass;
370 $taskTitle = $GLOBALS['LANG']->sL($task['title']);
371 $taskDescriptionHtml = '';
372
373 // Check for custom icon
374 if (!empty($task['icon'])) {
375 $icon = t3lib_div::getFileAbsFilename($task['icon']);
376 }
377
378 if (class_exists($taskClass)) {
379 $taskInstance = t3lib_div::makeInstance($taskClass, $this);
380 if ($taskInstance instanceof tx_taskcenter_Task) {
381 $taskDescriptionHtml = $taskInstance->getOverview();
382 }
383 }
384
385 // generate an array of all tasks
386 $uniqueKey = $this->getUniqueKey($extKey . '.' . $taskClass);
387 $tasks[$uniqueKey] = array(
388 'title' => $taskTitle,
389 'descriptionHtml' => $taskDescriptionHtml,
390 'description' => $GLOBALS['LANG']->sL($task['description']),
391 'icon' => $icon,
392 'link' => $link,
393 'uid' => $extKey . '.' . $taskClass
394 );
395 }
396 }
397
398 $content .= $this->renderListMenu($tasks, TRUE);
399 } else {
400 $flashMessage = t3lib_div::makeInstance(
401 't3lib_FlashMessage',
402 $GLOBALS['LANG']->getLL('no-tasks', TRUE),
403 '',
404 t3lib_FlashMessage::INFO
405 );
406 $this->content .= $flashMessage->render();
407 }
408
409 return $content;
410 }
411
412 /**
413 * Create the panel of buttons for submitting the form or otherwise
414 * perform operations.
415 *
416 * @return array all available buttons as an assoc. array
417 */
418 protected function getButtons() {
419 $buttons = array(
420 'csh' => t3lib_BEfunc::cshItem('_MOD_web_func', '', $GLOBALS['BACK_PATH']),
421 'shortcut' => '',
422 'open_new_window' => $this->openInNewWindow()
423 );
424
425 // Shortcut
426 if ($GLOBALS['BE_USER']->mayMakeShortcut()) {
427 $buttons['shortcut'] = $this->doc->makeShortcutIcon('', 'function', $this->MCONF['name']);
428 }
429
430 return $buttons;
431 }
432
433 /**
434 * Check the access to a task. Considered are:
435 * - Admins are always allowed
436 * - Tasks can be restriced to admins only
437 * - Tasks can be blinded for Users with TsConfig taskcenter.<extensionkey>.<taskName> = 0
438 *
439 * @param string $extKey: Extension key
440 * @param string $taskClass: Name of the task
441 * @return boolean Access to the task allowed or not
442 */
443 protected function checkAccess($extKey, $taskClass) {
444 // check if task is blinded with TsConfig (taskcenter.<extkey>.<taskName>
445 $tsConfig = $GLOBALS['BE_USER']->getTSConfig('taskcenter.' . $extKey . '.' . $taskClass);
446 if (isset($tsConfig['value']) && intval($tsConfig['value']) == 0) {
447 return FALSE;
448 }
449
450 // admins are always allowed
451 if ($GLOBALS['BE_USER']->isAdmin()) {
452 return TRUE;
453 }
454
455 // check if task is restricted to admins
456 if (intval($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['taskcenter'][$extKey][$taskClass]['admin']) == 1) {
457 return FALSE;
458 }
459
460 return TRUE;
461 }
462
463 /**
464 * Returns HTML code to dislay an url in an iframe at the right side of the taskcenter
465 *
466 * @param string $url: url to display
467 * @param int $max:
468 * @return string code that inserts the iframe (HTML)
469 */
470 public function urlInIframe($url, $max=0) {
471 $this->doc->JScodeArray[] =
472 'function resizeIframe(frame,max) {
473 var parent = $("typo3-docbody");
474 var parentHeight = $(parent).getHeight() - 0;
475 var parentWidth = $(parent).getWidth() - $("taskcenter-menu").getWidth() - 50;
476 $("list_frame").setStyle({height: parentHeight+"px", width: parentWidth+"px"});
477
478 }
479 // event crashes IE6 so he is excluded first
480 var version = parseFloat(navigator.appVersion.split(";")[1].strip().split(" ")[1]);
481 if (!(Prototype.Browser.IE && version == 6)) {
482 Event.observe(window, "resize", resizeIframe, false);
483 }';
484
485 return '<iframe onload="resizeIframe(this,' . $max . ');" scrolling="auto" width="100%" src="' . $url . '" name="list_frame" id="list_frame" frameborder="no" style="margin-top:-51px;border: none;"></iframe>';
486 }
487
488 /**
489 * Create a unique key from a string which can be used in Prototype's Sortable
490 * Therefore '_' are replaced
491 *
492 * @param string $string: string which is used to generate the identifier
493 * @return string modified string
494 */
495 protected function getUniqueKey($string) {
496 $search = array('.', '_');
497 $replace = array('-', '');
498
499 return str_replace($search, $replace, $string);
500 }
501
502 /**
503 * This method prepares the link for opening the devlog in a new window
504 *
505 * @return string Hyperlink with icon and appropriate JavaScript
506 */
507 protected function openInNewWindow() {
508 $url = t3lib_div::getIndpEnv('TYPO3_REQUEST_SCRIPT');
509 $onClick = "devlogWin=window.open('" . $url . "','taskcenter','width=790,status=0,menubar=1,resizable=1,location=0,scrollbars=1,toolbar=0');return false;";
510 $content = '<a href="#" onclick="' . htmlspecialchars($onClick).'">' .
511 '<img' . t3lib_iconWorks::skinImg($GLOBALS['BACK_PATH'],'gfx/open_in_new_window.gif', 'width="19" height="14"') . ' title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.openInNewWindow', 1) . '" class="absmiddle" alt="" />' .
512 '</a>';
513 return $content;
514 }
515
516
517 }
518
519
520 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/taskcenter/task/index.php']) {
521 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/taskcenter/task/index.php']);
522 }
523
524
525
526 // Make instance:
527 $SOBE = t3lib_div::makeInstance('SC_mod_user_task_index');
528 // Include files?
529 foreach($SOBE->include_once as $INC_FILE) {
530 include_once($INC_FILE);
531 }
532
533 $SOBE->main();
534 $SOBE->printContent();
535
536 ?>