1<?php
2
3/* Copyright (c) 1998-2012 ILIAS open source, Extended GPL, see docs/LICENSE */
4
5/**
6* Tabs GUI
7*
8* @author Alex Killing <alex.killing@gmx.de>
9* @version $Id$
10*
11*/
12class ilTabsGUI
13{
14
15    /**
16     * @var ilCtrl
17     */
18    protected $ctrl;
19
20    public $target_script;
21    public $obj_type;
22    public $tpl;
23    public $lng;
24    public $tabs;
25    public $target = array();
26    public $sub_target = array();
27    public $non_tabbed_link = array();
28    public $setup_mode = false;
29
30    protected $force_one_tab = false;
31
32    /**
33    * Constructor
34    * @access	public
35    */
36    public function __construct()
37    {
38        global $DIC;
39
40        $this->ctrl = $DIC->ctrl();
41        $tpl = $DIC["tpl"];
42        $lng = $DIC->language();
43
44        $this->tpl = $tpl;
45        $this->lng = $lng;
46        $this->manual_activation = false;
47        $this->subtab_manual_activation = false;
48        $this->temp_var = "TABS";
49        $this->sub_tabs = false;
50        $this->back_title = "";
51        $this->back_target = "";
52        $this->back_2_target = "";
53        $this->back_2_title = "";
54    }
55
56    /**
57     * Set setup mode
58     *
59     * @param boolean $a_val setup mode
60     */
61    public function setSetupMode($a_val)
62    {
63        $this->setup_mode = $a_val;
64    }
65
66    /**
67     * Get setup mode
68     *
69     * @return boolean setup mode
70     */
71    public function getSetupMode()
72    {
73        return $this->setup_mode;
74    }
75
76    /**
77    * back target for upper context
78    */
79    public function setBackTarget($a_title, $a_target, $a_frame = "")
80    {
81        $this->back_title = $a_title;
82        $this->back_target = $a_target;
83        $this->back_frame = $a_frame;
84    }
85
86    /**
87    * back target for tow level upper context
88    */
89    public function setBack2Target($a_title, $a_target, $a_frame = "")
90    {
91        $this->back_2_title = $a_title;
92        $this->back_2_target = $a_target;
93        $this->back_2_frame = $a_frame;
94    }
95
96    /**
97     * Set force presentation of single tab
98     *
99     * @param bool $a_val force presentation of single tab
100     */
101    public function setForcePresentationOfSingleTab($a_val)
102    {
103        $this->force_one_tab = $a_val;
104    }
105
106    /**
107     * Get force presentation of single tab
108     *
109     * @return bool force presentation of single tab
110     */
111    public function getForcePresentationOfSingleTab()
112    {
113        return $this->force_one_tab;
114    }
115
116    /**
117    * @deprecated since version 5.0
118    *
119    * Use addTab/addSubTab and activateTab/activateSubTab.
120    *
121    * Add a target to the tabbed menu. If no target has set $a_activate to
122    * true, ILIAS tries to determine the current activated menu item
123    * automatically using $a_cmd and $a_cmdClass. If one item is set
124    * activated (and only one should be activated) the automatism is disabled.
125    *
126    * @param	string		$a_text			menu item text
127    * @param	string		$a_link			menu item link
128    * @param	string		$a_cmd			command, used for auto activation
129    * @param	string		$a_cmdClass		used for auto activation. String or array of cmd classes
130    * @param	string		$a_frame		frame target
131    * @param	boolean		$a_activate		activate this menu item
132    */
133    public function addTarget(
134        $a_text,
135        $a_link,
136        $a_cmd = "",
137        $a_cmdClass = "",
138        $a_frame = "",
139        $a_activate = false,
140        $a_dir_text = false
141    ) {
142        if (!$a_cmdClass) {
143            $a_cmdClass = array();
144        }
145        $a_cmdClass = !is_array($a_cmdClass) ? array(strtolower($a_cmdClass)) : $a_cmdClass;
146        #$a_cmdClass = strtolower($a_cmdClass);
147
148        if ($a_activate) {
149            $this->manual_activation = true;
150        }
151        $this->target[] = array("text" => $a_text, "link" => $a_link,
152            "cmd" => $a_cmd, "cmdClass" => $a_cmdClass, "frame" => $a_frame,
153            "activate" => $a_activate, "dir_text" => $a_dir_text, "id" => $a_text);
154    }
155
156    /**
157    * Add a Tab
158    *
159    * @param	string		id
160    * @param	string		text (no lang var!)
161    * @param	string		link
162    * @param	string		frame target
163    */
164    public function addTab($a_id, $a_text, $a_link, $a_frame = "")
165    {
166        $this->target[] = array("text" => $a_text, "link" => $a_link,
167            "frame" => $a_frame, "dir_text" => true, "id" => $a_id, "cmdClass" => array());
168    }
169
170    /**
171     * Remove a tab identified by its id.
172     *
173     * @param 	string	$a_id	Id of tab to remove
174     * @return bool	false if tab wasn't found
175     * @access public
176     */
177    public function removeTab($a_id)
178    {
179        foreach ($this->target as $key => $target) {
180            if ($target['id'] == $a_id) {
181                unset($this->target[$key]);
182                return true;
183            }
184        }
185        return false;
186    }
187
188    /**
189     * Remove a tab identified by its id.
190     *
191     * @param 	string	$a_id	Id of tab to remove
192     * @return bool	false if tab wasn't found
193     * @access public
194     */
195    public function removeSubTab($a_id)
196    {
197        foreach ($this->sub_target as $i => $sub_target) {
198            if ($this->sub_target[$i]['id'] == $a_id) {
199                unset($this->sub_target[$i]);
200                return true;
201            }
202        }
203        return false;
204    }
205
206    /**
207     * Replace a tab.
208     * In contrast to a combination of removeTab and addTab, the position is kept.
209     *
210     * @param string $a_old_id				old id of tab
211     * @param string $a_new_id				new id if tab
212     * @param string $a_text				tab text
213     * @param string $a_link				tab link
214     * @param string $a_frame[optional]		frame
215     * @return bool
216     */
217    public function replaceTab($a_old_id, $a_new_id, $a_text, $a_link, $a_frame = '')
218    {
219        for ($i = 0; $i < count($this->target); $i++) {
220            if ($this->target[$i]['id'] == $a_old_id) {
221                $this->target[$i] = array();
222                $this->target[$i] = array(
223                    "text" => $a_text,
224                    "link" => $a_link,
225                    "frame" => $a_frame,
226                    "dir_text" => true,
227                    "id" => $a_new_id,
228                    "cmdClass" => array());
229                return true;
230            }
231        }
232        return false;
233    }
234
235    /**
236    * clear all targets
237    */
238    public function clearTargets()
239    {
240        global $DIC;
241
242        $ilHelp = null;
243        if (isset($DIC["ilHelp"])) {
244            $ilHelp = $DIC["ilHelp"];
245        }
246
247        if (!$this->getSetupMode()) {
248            $ilHelp->setScreenIdComponent("");
249        }
250
251        $this->target = array();
252        $this->sub_target = array();
253        $this->non_tabbed_link = array();
254        $this->back_title = "";
255        $this->back_target = "";
256        $this->back_2_target = "";
257        $this->back_2_title = "";
258        $this->setTabActive("");
259        $this->setSubTabActive("");
260    }
261
262    /**
263    * DEPRECATED.
264    *
265    * Use addTab/addSubTab and activateTab/activateSubTab.
266    *
267    * Add a Subtarget to the tabbed menu. If no target has set $a_activate to
268    * true, ILIAS tries to determine the current activated menu item
269    * automatically using $a_cmd and $a_cmdClass. If one item is set
270    * activated (and only one should be activated) the automatism is disabled.
271    *
272    * @param	string		$a_text			menu item text
273    * @param	string		$a_link			menu item link
274    * @param	string		$a_cmd			command, used for auto activation
275    * @param	string		$a_cmdClass		used for auto activation. String or array of cmd classes
276    * @param	string		$a_frame		frame target
277    * @param	boolean		$a_activate		activate this menu item
278    * @param	boolean		$a_dir_text		text is direct text, no language variable
279    */
280    public function addSubTabTarget(
281        $a_text,
282        $a_link,
283        $a_cmd = "",
284        $a_cmdClass = "",
285        $a_frame = "",
286        $a_activate = false,
287        $a_dir_text = false
288    ) {
289        if (!$a_cmdClass) {
290            $a_cmdClass = array();
291        }
292        $a_cmdClass = !is_array($a_cmdClass) ? array(strtolower($a_cmdClass)) : $a_cmdClass;
293        #$a_cmdClass = strtolower($a_cmdClass);
294
295        if ($a_activate) {
296            $this->subtab_manual_activation = true;
297        }
298        $this->sub_target[] = array("text" => $a_text, "link" => $a_link,
299            "cmd" => $a_cmd, "cmdClass" => $a_cmdClass, "frame" => $a_frame,
300            "activate" => $a_activate, "dir_text" => $a_dir_text, "id" => $a_text);
301    }
302
303    /**
304    * Add a Subtab
305    *
306    * @param	string		id
307    * @param	string		text (no lang var!)
308    * @param	string		link
309    * @param	string		frame target
310    */
311    public function addSubTab($a_id, $a_text, $a_link, $a_frame = "")
312    {
313        $this->sub_target[] = array("text" => $a_text, "link" => $a_link,
314            "frame" => $a_frame, "dir_text" => true, "id" => $a_id, "cmdClass" => array());
315    }
316
317    /**
318     * DEPRECATED.
319     * @deprecated since version 5.2
320     *
321     * Use addTab/addSubTab and activateTab/activateSubTab.
322     *
323     * Activate a specific tab identified by name
324     * This method overrides the definition in YOUR_OBJECT::getTabs() and deactivates all other tabs.
325     *
326     * @param	string		$a_text			menu item text
327     */
328    public function setTabActive($a_id)
329    {
330        foreach ($this->target as $key => $target) {
331            $this->target[$key]['activate'] = $this->target[$key]['id'] == $a_id;
332        }
333        if ($a_id != "") {
334            $this->manual_activation = true;
335        } else {
336            $this->manual_activation = false;
337        }
338        return true;
339    }
340
341    /**
342    * Activate a specific tab identified its id
343    *
344    * @param	string		$a_text			menu item text
345    */
346    public function activateTab($a_id)
347    {
348        $this->setTabActive($a_id);
349    }
350
351    /**
352    * DEPRECATED.
353    *
354    * Use addTab/addSubTab and activateTab/activateSubTab.
355    *
356    * Activate a specific tab identified by name
357    * This method overrides the definition in YOUR_OBJECT::getTabs() and deactivates all other tabs.
358    *
359    * @param	string		$a_text			menu item text
360    * @param	boolean
361    */
362    public function setSubTabActive($a_text)
363    {
364        for ($i = 0; $i < count($this->sub_target);$i++) {
365            $this->sub_target[$i]['activate'] = $this->sub_target[$i]['id'] == $a_text;
366        }
367        $this->subtab_manual_activation = true;
368        return true;
369    }
370
371    /**
372    * Activate a specific subtab identified its id
373    *
374    * @param	string		$a_text			menu item text
375    */
376    public function activateSubTab($a_id)
377    {
378        $this->setSubTabActive($a_id);
379    }
380
381    /**
382    * Clear all already added sub tabs
383    *
384    * @param	boolean
385    */
386    public function clearSubTabs()
387    {
388        $this->sub_target = array();
389        return true;
390    }
391
392    /**
393    * get tabs code as html
394    */
395    public function getHTML($a_after_tabs_anchor = false)
396    {
397        return $this->__getHTML(false, $this->manual_activation, $a_after_tabs_anchor);
398    }
399
400    /**
401    * get sub tabs code as html
402    */
403    public function getSubTabHTML()
404    {
405        return $this->__getHTML(true, $this->subtab_manual_activation);
406    }
407
408    /**
409    * Add a non-tabbed link (outside of tabs at same level)
410    *
411    * @param	string		id
412    * @param	string		text (no lang var!)
413    * @param	string		link
414    * @param	string		frame target
415    */
416    public function addNonTabbedLink($a_id, $a_text, $a_link, $a_frame = "")
417    {
418        $this->non_tabbed_link[] = array("text" => $a_text, "link" => $a_link,
419            "frame" => $a_frame, "dir_text" => true, "id" => $a_id, "cmdClass" => array());
420    }
421
422    /**
423     * get tabs code as html
424     * @param bool choose tabs or sub tabs
425     * @param bool manual activation
426     * @access Private
427     */
428    public function __getHTML($a_get_sub_tabs, $a_manual, $a_after_tabs_anchor = false)
429    {
430        global $DIC;
431
432        $ilHelp = null;
433        if (isset($DIC["ilHelp"])) {
434            $ilHelp = $DIC["ilHelp"];
435        }
436
437        $ilCtrl = $this->ctrl;
438        $lng = $this->lng;
439        $ilUser = null;
440        if (isset($DIC["ilUser"])) {
441            $ilUser = $DIC->user();
442        }
443        $ilPluginAdmin = null;
444        if (isset($DIC["ilPluginAdmin"])) {
445            $ilPluginAdmin = $DIC["ilPluginAdmin"];
446        }
447
448        // user interface hook [uihk]
449        if (!$this->getSetupMode()) {
450            $pl_names = $ilPluginAdmin->getActivePluginsForSlot(IL_COMP_SERVICE, "UIComponent", "uihk");
451            foreach ($pl_names as $pl) {
452                $ui_plugin = ilPluginAdmin::getPluginObject(IL_COMP_SERVICE, "UIComponent", "uihk", $pl);
453                $gui_class = $ui_plugin->getUIClassInstance();
454                $resp = $gui_class->modifyGUI(
455                    "",
456                    $a_get_sub_tabs ? "sub_tabs" : "tabs",
457                    array("tabs" => $this)
458                );
459            }
460        }
461
462
463        // user interface hook [uihk]
464        if (!$this->getSetupMode()) {
465            $cmd = $ilCtrl->getCmd();
466            $cmdClass = $ilCtrl->getCmdClass();
467        }
468
469        if ($a_get_sub_tabs) {
470            $tpl = new ilTemplate("tpl.sub_tabs.html", true, true, "Services/UIComponent/Tabs");
471            $pre = "sub";
472            $pre2 = "SUB_";
473            $sr_pre = "sub_";
474        } else {
475            $tpl = new ilTemplate("tpl.tabs.html", true, true, "Services/UIComponent/Tabs");
476            if ($a_after_tabs_anchor) {
477                $tpl->touchBlock("after_tabs");
478            }
479            $pre = $pre2 = "";
480
481            include_once("./Services/UIComponent/Glyph/classes/class.ilGlyphGUI.php");
482
483            // back 2 tab
484            if ($this->back_2_title != "") {
485                $tpl->setCurrentBlock("back_2_tab");
486                $tpl->setVariable("BACK_2_ICON", ilGlyphGUI::get(ilGlyphGUI::PREVIOUS, ilGlyphGUI::NO_TEXT));
487                $tpl->setVariable("BACK_2_TAB_LINK", $this->back_2_target);
488                $tpl->setVariable("BACK_2_TAB_TEXT", $this->back_2_title);
489                if ($this->back_2_frame != "") {
490                    $tpl->setVariable("BACK_2_TAB_TARGET", ' target="'.$this->back_2_frame.'" ');
491                }
492
493                $tpl->parseCurrentBlock();
494            }
495
496            // back tab
497            if ($this->back_title != "") {
498                $tpl->setCurrentBlock("back_tab");
499                $tpl->setVariable("BACK_ICON", ilGlyphGUI::get(ilGlyphGUI::PREVIOUS, ilGlyphGUI::NO_TEXT));
500                $tpl->setVariable("BACK_TAB_LINK", $this->back_target);
501                $tpl->setVariable("BACK_TAB_TEXT", $this->back_title);
502                if ($this->back_frame != "") {
503                    $tpl->setVariable("BACK_TAB_TARGET", ' target="'.$this->back_frame.'" ');
504                }
505                $tpl->parseCurrentBlock();
506            }
507        }
508
509        $targets = $a_get_sub_tabs ? $this->sub_target : $this->target;
510
511        $i = 0;
512
513        // do not display one tab only
514        if ((count($targets) > 1 || $this->force_one_tab) || ($this->back_title != "" && !$a_get_sub_tabs)
515            || (count($this->non_tabbed_link) > 0 && !$a_get_sub_tabs)) {
516            foreach ($targets as $target) {
517                $i++;
518
519                if (!is_array($target["cmd"])) {
520                    $target["cmd"] = array($target["cmd"]);
521                }
522                if (!$a_manual &&
523                    (in_array($cmd, $target["cmd"]) || ($target["cmd"][0] == "" && count($target["cmd"]) == 1)) &&
524                    (in_array($cmdClass, $target["cmdClass"]) || !$target["cmdClass"])) {
525                    $tabtype = $pre . "tabactive";
526                } else {
527                    $tabtype = $pre . "tabinactive";
528                }
529
530                if ($a_manual && $target["activate"]) {
531                    $tabtype = $pre . "tabactive";
532                }
533
534                if ($tabtype == "tabactive" || $tabtype == "subtabactive") {
535                    $tpl->setCurrentBlock("sel_text");
536                    $tpl->setVariable("TXT_SELECTED", $lng->txt("stat_selected"));
537                    $tpl->parseCurrentBlock();
538
539                    if (!$this->getSetupMode()) {
540                        if ($a_get_sub_tabs) {
541                            $part = ilHelpGUI::ID_PART_SUB_SCREEN;
542                        } else {
543                            $part = ilHelpGUI::ID_PART_SCREEN;
544                        }
545                        $ilHelp->setDefaultScreenId($part, $target["id"]);
546                    }
547                }
548
549                $tpl->setCurrentBlock($pre . "tab");
550                $tpl->setVariable("ID", $pre . "tab_" . $target["id"]);
551
552                // tooltip
553                if (!$this->getSetupMode()) {
554                    $ttext = $ilHelp->getTabTooltipText($target["id"]);
555                    if ($ttext != "") {
556                        include_once("./Services/UIComponent/Tooltip/classes/class.ilTooltipGUI.php");
557                        ilTooltipGUI::addTooltip(
558                            $pre . "tab_" . $target["id"],
559                            $ttext,
560                            "",
561                            "bottom center",
562                            "top center",
563                            false
564                        );
565                    }
566                }
567
568                // bs-patch: start
569                $tabtype = in_array($tabtype, array("tabactive", "subtabactive"))
570                    ? "active"
571                    : "";
572                // bs-patch: end
573
574                $tpl->setVariable($pre2 . "TAB_TYPE", $tabtype);
575                if (!$this->getSetupMode()) {
576                    $hash = ($ilUser->getPref("screen_reader_optimization"))
577                        ? "#after_" . $sr_pre . "tabs"
578                        : "";
579                }
580
581                $tpl->setVariable($pre2 . "TAB_LINK", $target["link"] . $hash);
582                if ($target["dir_text"]) {
583                    $tpl->setVariable($pre2 . "TAB_TEXT", $target["text"]);
584                } else {
585                    $tpl->setVariable($pre2 . "TAB_TEXT", $lng->txt($target["text"]));
586                }
587                if ($target["frame"] != "") {
588                    $tpl->setVariable($pre2 . "TAB_TARGET", ' target="'.$target["frame"].'" ');
589                }
590                $tpl->parseCurrentBlock();
591            }
592
593            if ($a_get_sub_tabs) {
594                $tpl->setVariable("TXT_SUBTABS", $lng->txt("subtabs"));
595            } else {
596                $tpl->setVariable("TXT_TABS", $lng->txt("tabs"));
597
598                // non tabbed links
599                include_once("./Services/UIComponent/Glyph/classes/class.ilGlyphGUI.php");
600                foreach ($this->non_tabbed_link as $link) {
601                    $tpl->setCurrentBlock("tab");
602                    $tpl->setVariable("TAB_TYPE", "nontabbed");
603                    $tpl->setVariable("TAB_ICON", " " . ilGlyphGUI::get(ilGlyphGUI::NEXT, ilGlyphGUI::NO_TEXT));
604                    $tpl->setVariable("TAB_TEXT", $link["text"]);
605                    $tpl->setVariable("TAB_LINK", $link["link"]);
606                    $tpl->setVariable("TAB_TARGET", $link["frame"]);
607                    $tpl->setVariable("ID", "nontab_" . $link["id"]);
608                    $tpl->parseCurrentBlock();
609
610                    // tooltip
611                    if (!$this->getSetupMode()) {
612                        $ttext = $ilHelp->getTabTooltipText($link["id"]);
613                        if ($ttext != "") {
614                            include_once("./Services/UIComponent/Tooltip/classes/class.ilTooltipGUI.php");
615                            ilTooltipGUI::addTooltip(
616                                "nontab_" . $link["id"],
617                                $ttext,
618                                "",
619                                "bottom center",
620                                "top center",
621                                false
622                            );
623                        }
624                    }
625                }
626            }
627
628            return $tpl->get();
629        } else {
630            return "";
631        }
632    }
633
634    public function getActiveTab()
635    {
636        foreach ($this->target as $i => $target) {
637            if ($this->target[$i]['activate']) {
638                return $this->target[$i]['id'];
639            }
640        }
641    }
642
643    public function hasTabs()
644    {
645        return (bool) sizeof($this->target);
646    }
647}
648