1<?php
2/* Copyright (c) 1998-2013 ILIAS open source, Extended GPL, see docs/LICENSE */
3
4// Config must be included generally for availability of constants
5require_once('Services/UIComponent/CharSelector/classes/ilCharSelectorConfig.php');
6
7/**
8* This shows a character selector
9*/
10class ilCharSelectorGUI
11{
12    /**
13     * @var ilLanguage
14     */
15    protected $lng;
16
17    /**
18     * @var ilCtrl
19     */
20    protected $ctrl;
21
22    /**
23     * @var ilTemplate
24     */
25    protected $tpl;
26
27    /**
28     * @static list of command classes for which the char selector is allowed
29     * (can also be a parent class of the actual command class)
30     */
31    private static $allowed_guis = array(
32        'assQuestionGUI',
33        'ilAssQuestionFeedbackEditingGUI',
34        'ilAssQuestionHintGUI',
35        'ilObjTestSettingsGeneralGUI',
36        'ilTestScoringGUI'
37    );
38
39    /**
40     * @static ilCharSelectorGUI	instance used for the current selector
41     */
42    private static $current_gui;
43
44    /**
45     * @var ilCharSelectorConfig	configuration object
46     */
47    private $config = null;
48
49    /**
50     * @var boolean	selector is already added to the page
51     */
52    private $added_to_page = false;
53
54
55    /**
56     * Constructor
57     * @param string	configuration context
58     */
59    public function __construct($a_context = ilCharSelectorConfig::CONTEXT_NONE)
60    {
61        global $DIC;
62
63        $this->lng = $DIC->language();
64        $this->ctrl = $DIC->ctrl();
65        $this->tpl = $DIC["tpl"];
66        $this->config = new ilCharSelectorConfig($a_context);
67    }
68
69    /**
70     * Check if the CharSelector is allowed for the current GUI
71     * @return boolean CharSelector is allowed
72     */
73    public static function _isAllowed()
74    {
75        global $DIC;
76
77        $ilCtrl = $DIC->ctrl();
78
79        // get the command class
80        // with correct case for checking parent classes
81        foreach ($ilCtrl->getCallHistory() as $call) {
82            if ($call['mode'] == 'execComm') {
83                $class = $call['class'];
84            }
85        }
86
87        // check the class and her parent classes
88        while ($class != false) {
89            if (in_array($class, self::$allowed_guis)) {
90                return true;
91            }
92            $class = get_parent_class($class);
93        }
94
95        return false;
96    }
97
98    /**
99     * Get the GUI that is used for the currently available selector
100     * (other GUI instances may exist for configuration in property forms)
101     *
102     * @param	object	(optional) current running test
103     * @return	object
104     */
105    public static function _getCurrentGUI(ilObjTest $a_test_obj = null)
106    {
107        if (!isset(self::$current_gui)) {
108            self::$current_gui = new ilCharSelectorGUI();
109            self::$current_gui->setConfig(ilCharSelectorConfig::_getCurrentConfig($a_test_obj));
110        }
111        return self::$current_gui;
112    }
113
114    /**
115     * Set the configuraton object
116     * @param ilCharSelectorConfig
117     */
118    public function setConfig(ilCharSelectorConfig $a_config)
119    {
120        $this->config = $a_config;
121    }
122
123    /**
124     * Get the configuraton object
125     * @return ilCharSelectorConfig
126     */
127    public function getConfig()
128    {
129        return $this->config;
130    }
131
132    /**
133     * add the configuration elements to a property form
134     * @param object	property form
135     */
136    public function addFormProperties(ilPropertyFormGUI $a_form)
137    {
138        $lng = $this->lng;
139        $lng->loadLanguageModule('adve');
140
141        require_once('Services/UIComponent/CharSelector/classes/class.ilCharSelectorRadioGroupInputGUI.php');
142        $availability = new ilCharSelectorRadioGroupInputGUI($lng->txt('char_selector_' . $this->config->getContext()), 'char_selector_availability');
143        $inactive = new ilRadioOption($lng->txt('char_selector_inactive_' . $this->config->getContext()), ilCharSelectorConfig::INACTIVE);
144        $inactive->setInfo($lng->txt('char_selector_inactive_info_' . $this->config->getContext()));
145        $inherit = new ilRadioOption($lng->txt('char_selector_inherit_' . $this->config->getContext()), ilCharSelectorConfig::INHERIT);
146        $inherit->setInfo($lng->txt('char_selector_inherit_info_' . $this->config->getContext()));
147        $enabled = new ilRadioOption($lng->txt('char_selector_enabled_' . $this->config->getContext()), ilCharSelectorConfig::ENABLED);
148        $enabled->setInfo($lng->txt('char_selector_enabled_info_' . $this->config->getContext()));
149        $disabled = new ilRadioOption($lng->txt('char_selector_disabled_' . $this->config->getContext()), ilCharSelectorConfig::DISABLED);
150        $disabled->setInfo($lng->txt('char_selector_disabled_info_' . $this->config->getContext()));
151
152        $blocks = new ilSelectInputGUI($lng->txt('char_selector_blocks'), 'char_selector_blocks');
153        $blocks->setInfo($lng->txt('char_selector_blocks_info'));
154        $blocks->setOptions($this->config->getBlockOptions());
155        $blocks->setMulti(true);
156        $enabled->addSubItem($blocks);
157
158        $custom_items = new ilTextAreaInputGUI($lng->txt('char_selector_custom_items'), 'char_selector_custom_items');
159        $tpl = new ilTemplate("tpl.char_selector_custom_info.html", true, true, "Services/UIComponent/CharSelector");
160        $tpl->setVariable('1', $lng->txt('char_selector_custom_items_info1'));
161        $tpl->setVariable('2a', $lng->txt('char_selector_custom_items_info2a'));
162        $tpl->setVariable('2b', $lng->txt('char_selector_custom_items_info2b'));
163        $tpl->setVariable('3a', $lng->txt('char_selector_custom_items_info3a'));
164        $tpl->setVariable('3b', $lng->txt('char_selector_custom_items_info3b'));
165        $tpl->setVariable('4a', $lng->txt('char_selector_custom_items_info4a'));
166        $tpl->setVariable('4b', $lng->txt('char_selector_custom_items_info4b'));
167        $tpl->setVariable('5a', $lng->txt('char_selector_custom_items_info5a'));
168        $tpl->setVariable('5b', $lng->txt('char_selector_custom_items_info5b'));
169        $tpl->setVariable('6a', $lng->txt('char_selector_custom_items_info6a'));
170        $tpl->setVariable('6b', $lng->txt('char_selector_custom_items_info6b'));
171        $custom_items->setInfo($tpl->get());
172        $enabled->addSubItem($custom_items);
173
174        switch ($this->config->getContext()) {
175            case ilCharSelectorConfig::CONTEXT_ADMIN:
176                $availability->addOption($inactive);
177                $availability->addOption($enabled);
178                $availability->addOption($disabled);
179                $a_form->addItem($availability);
180                break;
181
182            case ilCharSelectorConfig::CONTEXT_USER:
183            case ilCharSelectorConfig::CONTEXT_TEST:
184                $availability->addOption($inherit);
185                $availability->addOption($enabled);
186                $availability->addOption($disabled);
187                $a_form->addItem($availability);
188                break;
189        }
190    }
191
192
193    /**
194     * Set the values in a property form based on the configuration
195     * @param object		property form
196     * @param string		context of the form
197     */
198    public function setFormValues(ilPropertyFormGUI $a_form)
199    {
200        $a_form->getItemByPostVar('char_selector_availability')->setValue($this->config->getAvailability());
201        $a_form->getItemByPostVar('char_selector_blocks')->setValue($this->config->getAddedBlocks());
202        $a_form->getItemByPostVar('char_selector_custom_items')->setValue($this->config->getCustomItems());
203    }
204
205
206    /**
207     * Set the configuration based on the values of a property form
208     * @param object		property form
209     * @param string		context of the form
210     */
211    public function getFormValues(ilPropertyFormGUI $a_form)
212    {
213        $this->config->setAvailability($a_form->getInput('char_selector_availability'));
214        $this->config->setAddedBlocks($a_form->getInput('char_selector_blocks'));
215        $this->config->setCustomItems($a_form->getInput('char_selector_custom_items'));
216    }
217
218    /**
219     * Adds the the character selector to the ilias page
220     * Initializes the selector according to the state saved in the user session
221     * @see self::saveState()
222     */
223    public function addToPage()
224    {
225        $ilCtrl = $this->ctrl;
226        $tpl = $this->tpl;
227        $lng = $this->lng;
228
229        // don't add the panel twice
230        if ($this->added_to_page) {
231            return;
232        }
233
234        $lng->loadLanguageModule('adve');
235
236        // prepare the configuration for the js script
237        $this->jsconfig = new stdClass();
238        $this->jsconfig->pages = $this->config->getCharPages();
239        $this->jsconfig->ajax_url = $ilCtrl->getLinkTargetByClass("ilcharselectorgui", "saveState", "", true);
240        $this->jsconfig->open = (int) $_SESSION['char_selector_open'];
241        $this->jsconfig->current_page = (int) $_SESSION['char_selector_current_page'];
242        $this->jsconfig->current_subpage = (int) $_SESSION['char_selector_current_subpage'];
243
244        // provide texts to be dynamically rendered in the js script
245        $this->jstexts = new stdClass();
246        $this->jstexts->page = $lng->txt('page');
247        // fau: testNav - add texts for open/close char selector actions in the question menu
248        $this->jstexts->open = $lng->txt('char_selector_menu_open');
249        $this->jstexts->close = $lng->txt('char_selector_menu_close');
250        // fau.
251
252        // add everything neded to the page
253        // addLightbox() is just used to add the panel template outside the body
254        // The panel template is added as <script> to be not included in the DOM by default
255        // It will be included by js below the main header when the selector is switched on
256        $tpl->addCss(ilUtil::getStyleSheetLocation('', 'char_selector_style.css', 'Services/UIComponent/CharSelector'));
257        $tpl->addJavascript('./Services/UIComponent/CharSelector/js/ilCharSelector.js');
258        $tpl->addLightbox($this->getSelectorHTML(), 2);
259        $tpl->addOnLoadCode('il.CharSelector.init(' . json_encode($this->jsconfig) . ',' . json_encode($this->jstexts) . ')');
260        $this->added_to_page = true;
261    }
262
263    /**
264     * Get the HTML code of the selector panel
265     * @return string	panel html code
266     */
267    public function getSelectorHTML()
268    {
269        $lng = $this->lng;
270        $tpl = new ilTemplate("tpl.char_selector_panel.html", true, true, "Services/UIComponent/CharSelector");
271
272        if (count($this->jsconfig->pages) > 1) {
273            $index = 0;
274            foreach ($this->jsconfig->pages as $page) {
275                $tpl->setCurrentBlock('page_option');
276                $tpl->setVariable("PAGE_INDEX", $index);
277                $tpl->setVariable("PAGE_NAME", $page[0]);
278                $tpl->parseCurrentBlock();
279                $index++;
280            }
281        }
282
283        $tpl->setVariable('TXT_PREVIOUS_PAGE', $lng->txt('previous'));
284        $tpl->setVariable('TXT_NEXT_PAGE', $lng->txt('next'));
285        $tpl->setVariable('TXT_PAGE', $lng->txt('page'));
286
287        $tpl->touchBlock('chars');
288        return '<script type="text/html" id="ilCharSelectorTemplate">' . $tpl->get() . '</script>';
289    }
290
291
292    /**
293     * Save the selector panel state in the user session
294     * (This keeps the panel state between page moves)
295     * @see self::addToPage()
296     */
297    public function saveState()
298    {
299        $_SESSION['char_selector_open'] = (int) $_GET['open'];
300        $_SESSION['char_selector_current_page'] = (int) $_GET['current_page'];
301        $_SESSION['char_selector_current_subpage'] = (int) $_GET['current_subpage'];
302
303        // debugging output (normally ignored by the js part)
304        echo json_encode(array(
305            'open' => $_SESSION['char_selector_open'],
306            'current_page' => $_SESSION['char_selector_current_page'],
307            'current_subpage' => $_SESSION['char_selector_current_subpage'],
308        ));
309        exit;
310    }
311
312    /**
313    * execute command
314    */
315    public function executeCommand()
316    {
317        $ilCtrl = $this->ctrl;
318        $cmd = $ilCtrl->getCmd("saveState");
319        switch ($cmd) {
320            case 'saveState':
321                $this->$cmd();
322                break;
323            default:
324                return;
325        }
326    }
327}
328