1<?php
2/* Copyright (c) 1998-2013 ILIAS open source, Extended GPL, see docs/LICENSE */
3
4include_once("./Services/UIComponent/Explorer2/classes/class.ilTreeExplorerGUI.php");
5
6/**
7 * Explorer for selecting repository items.
8 *
9 * The implementation starts as a replacement for the often (ab)used ilSearchRootSelector class.
10 * Clicking items triggers a "selection" command.
11 * However ajax/checkbox/radio and use in an inputgui class should be implemented in the future, too.
12 *
13 * @author	Alex Killing <alex.killing@gmx.de>
14 * @version	$Id$
15 *
16 * @ingroup ServicesRepository
17 */
18class ilRepositorySelectorExplorerGUI extends ilTreeExplorerGUI
19{
20    /**
21     * @var ilObjectDefinition
22     */
23    protected $obj_definition;
24
25    /**
26     * @var ilLanguage
27     */
28    protected $lng;
29
30    protected $type_grps = array();
31    protected $session_materials = array();
32    protected $highlighted_node = null;
33    protected $clickable_types = array();
34
35    /**
36     * @var ilCtrl
37     */
38    protected $ctrl;
39
40    /**
41     * @var ilAccessHandler
42     */
43    protected $access;
44
45    /**
46     * @var callable
47     */
48    protected $nc_modifier = null;
49
50    /**
51     * @var object
52     */
53    protected $selection_gui = null;
54
55    /**
56     * @var string
57     */
58    protected $selection_par;
59
60    /**
61     * @var string
62     */
63    protected $selection_cmd;
64
65    /**
66     * Constructor
67     *
68     * @param object $a_parent_obj parent gui object
69     * @param string $a_parent_cmd parent cmd that renders the explorer
70     * @param object/string $a_selection_gui gui class that should be called for the selection command
71     * @param string $a_selection_cmd selection command
72     * @param string $a_selection_par selection parameter
73     */
74    public function __construct(
75        $a_parent_obj,
76        $a_parent_cmd,
77        $a_selection_gui = null,
78        $a_selection_cmd = "selectObject",
79        $a_selection_par = "sel_ref_id",
80        $a_id = "rep_exp_sel"
81    ) {
82        global $DIC;
83
84        $this->tree = $DIC->repositoryTree();
85        $this->obj_definition = $DIC["objDefinition"];
86        $this->lng = $DIC->language();
87        $tree = $DIC->repositoryTree();
88        $ilSetting = $DIC->settings();
89        $objDefinition = $DIC["objDefinition"];
90
91        $this->access = $DIC->access();
92        $this->ctrl = $DIC->ctrl();
93
94        if (is_null($a_selection_gui)) {
95            $a_selection_gui = $a_parent_obj;
96        }
97
98        $this->selection_gui = is_object($a_selection_gui)
99            ? strtolower(get_class($a_selection_gui))
100            : strtolower($a_selection_gui);
101        $this->selection_cmd = $a_selection_cmd;
102        $this->selection_par = $a_selection_par;
103        parent::__construct($a_id, $a_parent_obj, $a_parent_cmd, $tree);
104
105        $this->setSkipRootNode(false);
106        $this->setAjax(true);
107        $this->setOrderField("title");
108
109        // per default: all object types, except item groups
110        $white = array();
111        foreach ($objDefinition->getSubObjectsRecursively("root") as $rtype) {
112            if ($rtype["name"] != "itgr" && !$objDefinition->isSideBlock($rtype["name"])) {
113                $white[] = $rtype["name"];
114            }
115        }
116        $this->setTypeWhiteList($white);
117
118        // always open the path to the current ref id
119        $this->setPathOpen((int) $this->tree->readRootId());
120        if ((int) $_GET["ref_id"] > 0) {
121            $this->setPathOpen((int) $_GET["ref_id"]);
122        }
123        $this->setChildLimit((int) $ilSetting->get("rep_tree_limit_number"));
124    }
125
126    /**
127     * Set node content modifier
128     *
129     * @param callable $a_val
130     */
131    public function setNodeContentModifier(callable $a_val)
132    {
133        $this->nc_modifier = $a_val;
134    }
135
136    /**
137     * Get node content modifier
138     *
139     * @return callable
140     */
141    public function getNodeContentModifier()
142    {
143        return $this->nc_modifier;
144    }
145
146    /**
147     * Get node content
148     *
149     * @param array $a_node node data
150     * @return string content
151     */
152    public function getNodeContent($a_node)
153    {
154        $lng = $this->lng;
155
156        $c = $this->getNodeContentModifier();
157        if (is_callable($c)) {
158            return $c($a_node);
159        }
160
161        $title = $a_node["title"];
162        if ($a_node["child"] == $this->getNodeId($this->getRootNode())) {
163            if ($title == "ILIAS") {
164                $title = $lng->txt("repository");
165            }
166        }
167
168        return $title;
169    }
170
171    /**
172     * Get node icon
173     *
174     * @param array $a_node node data
175     * @return string icon path
176     */
177    public function getNodeIcon($a_node)
178    {
179        $obj_id = ilObject::_lookupObjId($a_node["child"]);
180        return ilObject::_getIcon($obj_id, "tiny", $a_node["type"]);
181    }
182
183    /**
184     * Get node icon alt text
185     *
186     * @param array $a_node node data
187     * @return string alt text
188     */
189    public function getNodeIconAlt($a_node)
190    {
191        $lng = $this->lng;
192
193        if ($a_node["child"] == $this->getNodeId($this->getRootNode())) {
194            $title = $a_node["title"];
195            if ($title == "ILIAS") {
196                $title = $lng->txt("repository");
197            }
198            return $lng->txt("icon") . " " . $title;
199        }
200
201
202        return parent::getNodeIconAlt($a_node);
203    }
204
205    /**
206     * Is node highlighted?
207     *
208     * @param mixed $a_node node object/array
209     * @return boolean node visible true/false
210     */
211    public function isNodeHighlighted($a_node)
212    {
213        if ($this->getHighlightedNode()) {
214            if ($this->getHighlightedNode() == $a_node["child"]) {
215                return true;
216            }
217            return false;
218        }
219
220        if ($a_node["child"] == $_GET["ref_id"] ||
221            ($_GET["ref_id"] == "" && $a_node["child"] == $this->getNodeId($this->getRootNode()))) {
222            return true;
223        }
224        return false;
225    }
226
227    /**
228     * Get href for node
229     *
230     * @param mixed $a_node node object/array
231     * @return string href attribute
232     */
233    public function getNodeHref($a_node)
234    {
235        $ilCtrl = $this->ctrl;
236
237        if ($this->select_postvar == "") {
238            $ilCtrl->setParameterByClass($this->selection_gui, $this->selection_par, $a_node["child"]);
239            $link = $ilCtrl->getLinkTargetByClass($this->selection_gui, $this->selection_cmd);
240            $ilCtrl->setParameterByClass($this->selection_gui, $this->selection_par, "");
241        } else {
242            return "#";
243        }
244
245        return $link;
246    }
247
248    /**
249     * Is node visible
250     *
251     * @param array $a_node node data
252     * @return bool visible true/false
253     */
254    public function isNodeVisible($a_node)
255    {
256        $ilAccess = $this->access;
257
258        if (!$ilAccess->checkAccess('visible', '', $a_node["child"])) {
259            return false;
260        }
261
262        return true;
263    }
264
265    /**
266     * Sort childs
267     *
268     * @param array $a_childs array of child nodes
269     * @param int $a_parent_node_id parent node id
270     * @return array array of childs nodes
271     */
272    public function sortChilds($a_childs, $a_parent_node_id)
273    {
274        $objDefinition = $this->obj_definition;
275
276        $parent_obj_id = ilObject::_lookupObjId($a_parent_node_id);
277
278        if ($parent_obj_id > 0) {
279            $parent_type = ilObject::_lookupType($parent_obj_id);
280        } else {
281            $parent_type = "dummy";
282            $this->type_grps["dummy"] = array("root" => "dummy");
283        }
284
285        if (empty($this->type_grps[$parent_type])) {
286            $this->type_grps[$parent_type] =
287                $objDefinition->getGroupedRepositoryObjectTypes($parent_type);
288        }
289        $group = array();
290
291        foreach ($a_childs as $child) {
292            $g = $objDefinition->getGroupOfObj($child["type"]);
293            if ($g == "") {
294                $g = $child["type"];
295            }
296            $group[$g][] = $child;
297        }
298
299        // #14587 - $objDefinition->getGroupedRepositoryObjectTypes does NOT include side blocks!
300        $wl = $this->getTypeWhiteList();
301        if (is_array($wl) && in_array("poll", $wl)) {
302            $this->type_grps[$parent_type]["poll"] = array();
303        }
304
305        $childs = array();
306        foreach ($this->type_grps[$parent_type] as $t => $g) {
307            if (is_array($group[$t])) {
308                // do we have to sort this group??
309                include_once("./Services/Container/classes/class.ilContainer.php");
310                include_once("./Services/Container/classes/class.ilContainerSorting.php");
311                $sort = ilContainerSorting::_getInstance($parent_obj_id);
312                $group = $sort->sortItems($group);
313
314                // need extra session sorting here
315                if ($t == "sess") {
316                }
317
318                foreach ($group[$t] as $k => $item) {
319                    $childs[] = $item;
320                }
321            }
322        }
323
324        return $childs;
325    }
326
327    /**
328     * Get childs of node
329     *
330     * @param int $a_parent_node_id node id
331     * @return array childs array
332     */
333    public function getChildsOfNode($a_parent_node_id)
334    {
335        $ilAccess = $this->access;
336
337        if (!$ilAccess->checkAccess("read", "", $a_parent_node_id)) {
338            return array();
339        }
340
341        return parent::getChildsOfNode($a_parent_node_id);
342    }
343
344    /**
345     * Is node clickable?
346     *
347     * @param array $a_node node data
348     * @return boolean node clickable true/false
349     */
350    public function isNodeClickable($a_node)
351    {
352        $ilAccess = $this->access;
353
354        if ($this->select_postvar != "") {
355            // return false; #14354
356        }
357
358        if (!$ilAccess->hasUserRBACorAnyPositionAccess("read", $a_node["child"])) {
359            return false;
360        }
361
362        if (is_array($this->getClickableTypes()) && count($this->getClickableTypes()) > 0) {
363            return in_array($a_node["type"], $this->getClickableTypes());
364        }
365
366        return true;
367    }
368
369    /**
370     * set an alternate highlighted node if $_GET["ref_id"] is not set or wrong
371     *
372     * @param int $a_value ref_id
373     */
374    public function setHighlightedNode($a_value)
375    {
376        $this->highlighted_node = $a_value;
377    }
378
379    /**
380     * get an alternate highlighted node if $_GET["ref_id"] is not set or wrong
381     * Returns null if not set
382     *
383     * @return mixed ref_id
384     */
385    public function getHighlightedNode()
386    {
387        return $this->highlighted_node;
388    }
389
390    /**
391     * set Whitelist for clickable items
392     *
393     * @param array/string $a_types array type
394     */
395    public function setClickableTypes($a_types)
396    {
397        if (!is_array($a_types)) {
398            $a_types = array($a_types);
399        }
400        $this->clickable_types = $a_types;
401    }
402
403    /**
404     * get whitelist for clickable items
405     *
406     * @return array types
407     */
408    public function getClickableTypes()
409    {
410        return (array) $this->clickable_types;
411    }
412
413    /**
414     * Get HTML
415     *
416     * @param
417     * @return
418     */
419    /*	function getHTML()
420        {
421            global $ilCtrl, $tpl;
422
423            $add = "";
424            if ($ilCtrl->isAsynch())
425            {
426                $add = $this->getOnLoadCode();
427            }
428            else
429            {
430                $tpl->addOnloadCode($this->getOnLoadCode());
431            }
432
433            return parent::getHTML().$add;
434        }
435    */
436
437    /**
438     * set Whitelist for clickable items
439     *
440     * @param array/string $a_types array type
441     */
442    public function setSelectableTypes($a_types)
443    {
444        if (!is_array($a_types)) {
445            $a_types = array($a_types);
446        }
447        $this->selectable_types = $a_types;
448    }
449
450    /**
451     * get whitelist for clickable items
452     *
453     * @return array types
454     */
455    public function getSelectableTypes()
456    {
457        return (array) $this->selectable_types;
458    }
459
460    /**
461     * Is node selectable?
462     *
463     * @param mixed $a_node node object/array
464     * @return boolean node selectable true/false
465     */
466    protected function isNodeSelectable($a_node)
467    {
468        if (count($this->getSelectableTypes())) {
469            return in_array($a_node['type'], $this->getSelectableTypes());
470        }
471        return true;
472    }
473}
474