1<?php
2/* Copyright (c) 1998-2010 ILIAS open source, Extended GPL, see docs/LICENSE */
3
4include_once('./Services/Table/classes/class.ilTable2GUI.php');
5include_once './Services/AccessControl/classes/class.ilPermissionGUI.php';
6require_once('./Services/Repository/classes/class.ilObjectPlugin.php');
7
8/**
9* Table for object role permissions
10*
11* @author Stefan Meyer <meyer@leifos.com>
12*
13* @version $Id$
14*
15* @ingroup ServicesAccessControl
16*/
17class ilObjectRolePermissionTableGUI extends ilTable2GUI
18{
19    const ROLE_FILTER_ALL = 1;
20    const ROLE_FILTER_GLOBAL = 2;
21    const ROLE_FILTER_LOCAL = 3;
22    const ROLE_FILTER_LOCAL_POLICY = 4;
23    const ROLE_FILTER_LOCAL_OBJECT = 5;
24
25    private $ref_id = null;
26    private $roles = array();
27
28    private $tree_path_ids = array();
29
30    private $activeOperations = array();
31    private $visible_roles = array();
32
33    /**
34     * Constructor
35     * @return
36     */
37    public function __construct($a_parent_obj, $a_parent_cmd, $a_ref_id)
38    {
39        global $DIC;
40
41        $ilCtrl = $DIC['ilCtrl'];
42        $rbacreview = $DIC['rbacreview'];
43        $tpl = $DIC['tpl'];
44        $tree = $DIC['tree'];
45
46        parent::__construct($a_parent_obj, $a_parent_cmd);
47
48        $this->lng->loadLanguageModule('rbac');
49
50        $this->ref_id = $a_ref_id;
51        $this->tree_path_ids = $tree->getPathId($this->ref_id);
52
53        $this->setId('objroleperm_' . $this->ref_id);
54
55        $tpl->addJavaScript('./Services/AccessControl/js/ilPermSelect.js');
56
57        $this->setTitle($this->lng->txt('permission_settings'));
58        $this->setEnableHeader(true);
59        $this->disable('sort');
60        $this->setFormAction($ilCtrl->getFormAction($a_parent_obj, $a_parent_cmd));
61        $this->disable('numinfo');
62        $this->setRowTemplate("tpl.obj_role_perm_row.html", "Services/AccessControl");
63        $this->setLimit(100);
64        $this->setShowRowsSelector(false);
65        $this->setDisableFilterHiding(true);
66        $this->setNoEntriesText($this->lng->txt('msg_no_roles_of_type'));
67
68        $this->addCommandButton('savePermissions', $this->lng->txt('save'));
69
70        $this->initFilter();
71    }
72
73
74    /**
75     * Get tree path ids
76     * @return array
77     */
78    public function getPathIds()
79    {
80        return (array) $this->tree_path_ids;
81    }
82
83    /**
84     * Get ref id of current object
85     * @return
86     */
87    public function getRefId()
88    {
89        return $this->ref_id;
90    }
91
92    /**
93     * Get obj id
94     * @return
95     */
96    public function getObjId()
97    {
98        return ilObject::_lookupObjId($this->getRefId());
99    }
100
101    /**
102     * get obj type
103     * @return
104     */
105    public function getObjType()
106    {
107        return ilObject::_lookupType($this->getObjId());
108    }
109
110    /**
111     * Add active operation
112     * @param int $a_ops_id
113     * @return
114     */
115    public function addActiveOperation($a_ops_id)
116    {
117        $this->activeOperations[] = $a_ops_id;
118    }
119
120    /**
121     * get active operations
122     * @return
123     */
124    public function getActiveOperations()
125    {
126        return (array) $this->activeOperations;
127    }
128
129    /**
130     * Set Visible roles
131     * @param object $a_ar
132     * @return
133     */
134    public function setVisibleRoles($a_ar)
135    {
136        $this->visible_roles = $a_ar;
137    }
138
139    /**
140     * get visible roles
141     * @return
142     */
143    public function getVisibleRoles()
144    {
145        return $this->visible_roles;
146    }
147
148    /**
149     * Init role filter
150     * @return
151     */
152    public function initFilter()
153    {
154        global $DIC;
155
156        $tree = $DIC['tree'];
157
158        $roles = $this->addFilterItemByMetaType(
159            'role',
160            ilTable2GUI::FILTER_SELECT
161        );
162
163        // Limit filter to local roles only for objects with group or course in path
164        if (!$roles->getValue()) {
165            if ($tree->checkForParentType($this->getRefId(), 'crs') or
166                $tree->checkForParentType($this->getRefId(), 'grp')) {
167                $roles->setValue(self::ROLE_FILTER_LOCAL);
168            } else {
169                $roles->setValue(self::ROLE_FILTER_ALL);
170            }
171        }
172
173
174        $roles->setOptions(
175            array(
176                self::ROLE_FILTER_ALL => $this->lng->txt('filter_all_roles'),
177                self::ROLE_FILTER_GLOBAL => $this->lng->txt('filter_global_roles'),
178                self::ROLE_FILTER_LOCAL => $this->lng->txt('filter_local_roles'),
179                self::ROLE_FILTER_LOCAL_POLICY => $this->lng->txt('filter_roles_local_policy'),
180                self::ROLE_FILTER_LOCAL_OBJECT => $this->lng->txt('filter_local_roles_object')
181            )
182        );
183    }
184
185    /**
186     * Fill one permission row
187     * @param object $row
188     * @return
189     */
190    public function fillRow($row)
191    {
192        global $DIC;
193
194        $objDefinition = $DIC['objDefinition'];
195
196
197        // local policy
198        if (isset($row['show_local_policy_row'])) {
199            foreach ($row['roles'] as $role_id => $role_info) {
200                $this->tpl->setCurrentBlock('role_option');
201                $this->tpl->setVariable('INHERIT_ROLE_ID', $role_id);
202                $this->tpl->setVariable('INHERIT_CHECKED', $role_info['local_policy'] ? 'checked=checked' : '');
203                $this->tpl->setVariable('INHERIT_DISABLED', ($role_info['protected'] or $role_info['isLocal'] or $role_info['blocked']) ? 'disabled="disabled"' : '');
204                $this->tpl->setVariable('TXT_INHERIT', $this->lng->txt('rbac_local_policy'));
205                $this->tpl->setVariable('INHERIT_LONG', $this->lng->txt('perm_use_local_policy_desc'));
206                $this->tpl->parseCurrentBlock();
207            }
208            return true;
209        }
210        // protected
211        if (isset($row['show_protected_row'])) {
212            foreach ($row['roles'] as $role_id => $role_info) {
213                $this->tpl->setCurrentBlock('role_protect');
214                $this->tpl->setVariable('PROTECT_ROLE_ID', $role_id);
215                $this->tpl->setVariable('PROTECT_CHECKED', $role_info['protected_status'] ? 'checked=checked' : '');
216                $this->tpl->setVariable('PROTECT_DISABLED', $role_info['protected_allowed'] ? '' : 'disabled="disabled"');
217                $this->tpl->setVariable('TXT_PROTECT', $this->lng->txt('role_protect_permissions'));
218                $this->tpl->setVariable('PROTECT_LONG', $this->lng->txt('role_protect_permissions_desc'));
219                $this->tpl->parseCurrentBlock();
220            }
221            return true;
222        }
223
224        // block role
225        if (isset($row['show_block_row'])) {
226            foreach ($this->getVisibleRoles() as $counter => $role_info) {
227                $this->tpl->setCurrentBlock('role_block');
228                $this->tpl->setVariable('BLOCK_ROLE_ID', $role_info['obj_id']);
229                $this->tpl->setVariable('TXT_BLOCK', $this->lng->txt('role_block_role'));
230                $this->tpl->setVariable('BLOCK_LONG', $this->lng->txt('role_block_role_desc'));
231                if ($role_info['blocked']) {
232                    $this->tpl->setVariable('BLOCK_CHECKED', 'checked="checked"');
233                }
234                if (
235                    ($role_info['protected'] == 'y') ||
236                    ($role_info['assign'] == 'y' and ($role_info['parent'] == $this->getRefId()))
237                ) {
238                    $this->tpl->setVariable('BLOCK_DISABLED', 'disabled="disabled');
239                }
240
241                $this->tpl->parseCurrentBlock();
242            }
243            return true;
244        }
245
246        // Select all
247        if (isset($row['show_select_all'])) {
248            foreach ($this->getVisibleRoles() as $role) {
249                $this->tpl->setCurrentBlock('role_select_all');
250                $this->tpl->setVariable('JS_ROLE_ID', $role['obj_id']);
251                $this->tpl->setVariable('JS_SUBID', $row['subtype']);
252                $this->tpl->setVariable('JS_ALL_PERMS', "['" . implode("','", $row['ops']) . "']");
253                $this->tpl->setVariable('JS_FORM_NAME', $this->getFormName());
254                $this->tpl->setVariable('TXT_SEL_ALL', $this->lng->txt('select_all'));
255                $this->tpl->parseCurrentBlock();
256            }
257            return true;
258        }
259
260        // Object permissions
261        if (isset($row['show_start_info'])) {
262            $this->tpl->setCurrentBlock('section_info');
263            $this->tpl->setVariable('SECTION_TITLE', $this->lng->txt('perm_class_object'));
264            $this->tpl->setVariable('SECTION_DESC', $this->lng->txt('perm_class_object_desc'));
265            $this->tpl->parseCurrentBlock();
266
267            return true;
268        }
269
270        if (isset($row['show_create_info'])) {
271            $this->tpl->setCurrentBlock('section_info');
272            $this->tpl->setVariable('SECTION_TITLE', $this->lng->txt('perm_class_create'));
273            $this->tpl->setVariable('SECTION_DESC', $this->lng->txt('perm_class_create_desc'));
274            $this->tpl->parseCurrentBlock();
275
276            return true;
277        }
278
279        foreach ((array) $row['roles'] as $role_id => $role_info) {
280            $perm = "";
281            $this->tpl->setCurrentBlock('role_td');
282            $this->tpl->setVariable('PERM_ROLE_ID', $role_id);
283            $this->tpl->setVariable('PERM_PERM_ID', $row['perm']['ops_id']);
284
285
286            if (substr($row['perm']['operation'], 0, 6) == 'create') {
287                if ($objDefinition->isPlugin(substr($row['perm']['operation'], 7))) {
288                    $perm = ilObjectPlugin::lookupTxtById(
289                        substr($row['perm']['operation'], 7),
290                        "obj_" . substr($row['perm']['operation'], 7)
291                    );
292                } else {
293                    $perm = $this->lng->txt('obj_' . substr($row['perm']['operation'], 7));
294                }
295            } else {
296                if ($objDefinition->isPlugin($this->getObjType())) {
297                    if (ilPlugin::langExitsById($this->getObjType(), $row['perm']['operation'])) {
298                        $perm = ilObjectPlugin::lookupTxtById($this->getObjType(), $row['perm']['operation']);
299                    }
300                }
301
302                if (!$perm) {
303                    if ($this->lng->exists($this->getObjType() . '_' . $row['perm']['operation'] . '_short')) {
304                        $perm = $this->lng->txt($this->getObjType() . '_' . $row['perm']['operation'] . '_short');
305                    } else {
306                        $perm = $this->lng->txt($row['perm']['operation']);
307                    }
308                }
309            }
310
311            $this->tpl->setVariable('TXT_PERM', $perm);
312
313            if ($objDefinition->isPlugin($this->getObjType())) {
314                $this->tpl->setVariable('PERM_LONG', ilObjectPlugin::lookupTxtById(
315                    $this->getObjType(),
316                    $this->getObjType() . "_" . $row['perm']['operation']
317                ));
318            } elseif (substr($row['perm']['operation'], 0, 6) == 'create') {
319                $this->tpl->setVariable('PERM_LONG', $this->lng->txt('rbac_' . $row['perm']['operation']));
320            } else {
321                $this->tpl->setVariable('PERM_LONG', $this->lng->txt($this->getObjType() . '_' . $row['perm']['operation']));
322            }
323
324            if ($role_info['protected'] || $role_info['blocked']) {
325                $this->tpl->setVariable('PERM_DISABLED', 'disabled="disabled"');
326            }
327            if ($role_info['permission_set']) {
328                $this->tpl->setVariable('PERM_CHECKED', 'checked="checked"');
329            }
330
331            $this->tpl->parseCurrentBlock();
332        }
333    }
334
335
336    /**
337     * Parse
338     * @return
339     */
340    public function parse()
341    {
342        global $DIC;
343
344        $rbacreview = $DIC['rbacreview'];
345        $objDefinition = $DIC['objDefinition'];
346
347        $this->initColumns();
348
349        $perms = array();
350        $roles = array();
351
352        if (!count($this->getVisibleRoles())) {
353            return $this->setData(array());
354        }
355
356        // Read operations of role
357        $operations = array();
358        foreach ($this->getVisibleRoles() as $role_data) {
359            $operations[$role_data['obj_id']] = $rbacreview->getActiveOperationsOfRole($this->getRefId(), $role_data['obj_id']);
360        }
361
362        $counter = 0;
363
364        // Local policy
365        if (ilPermissionGUI::hasContainerCommands($this->getObjType())) {
366            $roles = array();
367            $local_roles = $rbacreview->getRolesOfObject($this->getRefId());
368            foreach ($this->getVisibleRoles() as $role_id => $role_data) {
369                $roles[$role_data['obj_id']] = array(
370                    'blocked' => $role_data['blocked'],
371                    'protected' => $role_data['protected'],
372                    'local_policy' => in_array($role_data['obj_id'], $local_roles),
373                    'isLocal' => ($this->getRefId() == $role_data['parent']) && $role_data['assign'] == 'y'
374                );
375            }
376            $perms[$counter]['roles'] = $roles;
377            $perms[$counter]['show_local_policy_row'] = 1;
378
379            $counter++;
380        }
381
382        // Protect permissions
383        if (ilPermissionGUI::hasContainerCommands($this->getObjType())) {
384            $roles = array();
385            foreach ($this->getVisibleRoles() as $role_id => $role_data) {
386                $roles[$role_data['obj_id']] = array(
387                    'blocked' => $role_data['blocked'],
388                    'protected_allowed' => $rbacreview->isAssignable($role_data['obj_id'], $this->getRefId()),
389                    'protected_status' => $rbacreview->isProtected($role_data['parent'], $role_data['obj_id']),
390                    'isLocal' => ($this->getRefId() == $role_data['parent']) && $role_data['assign'] == 'y'
391                );
392            }
393            $perms[$counter]['roles'] = $roles;
394            $perms[$counter]['show_protected_row'] = 1;
395
396            $counter++;
397        }
398        // Block role
399        if (ilPermissionGUI::hasContainerCommands($this->getObjType())) {
400            $perms[$counter++]['show_block_row'] = 1;
401        }
402
403
404        if (ilPermissionGUI::hasContainerCommands($this->getObjType())) {
405            $perms[$counter++]['show_start_info'] = true;
406        }
407
408        // no creation permissions
409        $no_creation_operations = array();
410        foreach ($rbacreview->getOperationsByTypeAndClass($this->getObjType(), 'object') as $operation) {
411            $this->addActiveOperation($operation);
412            $no_creation_operations[] = $operation;
413
414            $roles = array();
415            foreach ($this->getVisibleRoles() as $role_data) {
416                $roles[$role_data['obj_id']] =
417                    array(
418                        'blocked' => $role_data['blocked'],
419                        'protected' => $role_data['protected'],
420                        'permission_set' => in_array($operation, (array) $operations[$role_data['obj_id']]),
421                        'isLocal' => ($this->getRefId() == $role_data['parent']) && $role_data['assign'] == 'y'
422                    );
423            }
424
425            $op = $rbacreview->getOperation($operation);
426
427            $perms[$counter]['roles'] = $roles;
428            $perms[$counter]['perm'] = $op;
429            $counter++;
430        }
431
432        /*
433         * Select all
434         */
435        if ($no_creation_operations) {
436            $perms[$counter]['show_select_all'] = 1;
437            $perms[$counter]['ops'] = $no_creation_operations;
438            $perms[$counter]['subtype'] = 'nocreation';
439            $counter++;
440        }
441
442
443        if ($objDefinition->isContainer($this->getObjType())) {
444            $perms[$counter++]['show_create_info'] = true;
445        }
446
447        // Get creatable objects
448        $objects = $objDefinition->getCreatableSubObjects($this->getObjType());
449        $ops_ids = ilRbacReview::lookupCreateOperationIds(array_keys($objects));
450        $creation_operations = array();
451        foreach ($objects as $type => $info) {
452            $ops_id = $ops_ids[$type];
453
454            if (!$ops_id) {
455                continue;
456            }
457
458            $this->addActiveOperation($ops_id);
459            $creation_operations[] = $ops_id;
460
461            $roles = array();
462            foreach ($this->getVisibleRoles() as $role_data) {
463                $roles[$role_data['obj_id']] =
464                    array(
465                        'blocked' => $role_data['blocked'],
466                        'protected' => $role_data['protected'],
467                        'permission_set' => in_array($ops_id, (array) $operations[$role_data['obj_id']]),
468                        'isLocal' => ($this->getRefId() == $role_data['parent']) && $role_data['assign'] == 'y'
469
470                    );
471            }
472
473            $op = $rbacreview->getOperation($ops_id);
474
475            $perms[$counter]['roles'] = $roles;
476            $perms[$counter]['perm'] = $op;
477            $counter++;
478        }
479
480
481
482        // Select all
483        if (count($creation_operations)) {
484            $perms[$counter]['show_select_all'] = 1;
485            $perms[$counter]['ops'] = $creation_operations;
486            $perms[$counter]['subtype'] = 'creation';
487            $counter++;
488        }
489
490        $this->setData($perms);
491    }
492
493    /**
494     * init Columns
495     * @return
496     */
497    protected function initColumns()
498    {
499        global $DIC;
500
501        $rbacreview = $DIC['rbacreview'];
502        $ilCtrl = $DIC['ilCtrl'];
503
504        $roles = $rbacreview->getParentRoleIds($this->getRefId());
505        $roles = $this->getParentObject()->applyRoleFilter(
506            $roles,
507            $this->getFilterItemByPostVar('role')->getValue()
508        );
509
510        $possible_roles = array();
511        foreach ($roles as $role) {
512            if ($rbacreview->isBlockedInUpperContext($role['obj_id'], $this->getRefId())) {
513                ilLoggerFactory::getLogger('ac')->debug('Ignoring blocked role: ' . $role['obj_id']);
514                continue;
515            }
516            $possible_roles[] = $role;
517        }
518
519
520        if (count($possible_roles)) {
521            $column_width = 100 / count($possible_roles);
522            $column_width .= '%';
523        } else {
524            $column_widht = "0%";
525        }
526
527        $all_roles = array();
528        foreach ($possible_roles as $role) {
529            if ($role['obj_id'] == SYSTEM_ROLE_ID) {
530                continue;
531            }
532
533            $role['blocked'] = (bool) $rbacreview->isBlockedAtPosition($role['obj_id'], $this->getRefId());
534            $role['role_type'] = $rbacreview->isGlobalRole($role['obj_id']) ? 'global' : 'local';
535
536            // TODO check filter
537            $this->addColumn(
538                $this->createTitle($role),
539                $role['obj_id'],
540                '',
541                '',
542                false,
543                $this->createTooltip($role)
544            );
545            $all_roles[] = $role;
546        }
547
548        $this->setVisibleRoles($all_roles);
549        return true;
550    }
551
552    /**
553     * Create a linked title for roles with local policy
554     * @param object $role
555     * @return
556     */
557    protected function createTooltip($role)
558    {
559        global $DIC;
560
561        $rbacreview = $DIC['rbacreview'];
562        $tree = $DIC['tree'];
563        $objDefinition = $DIC['objDefinition'];
564
565        #vd($role);
566        $protected_status = $rbacreview->isProtected($role['parent'], $role['obj_id']) ? 'protected_' : '';
567        if ($role['role_type'] == 'global') {
568            $tp = $this->lng->txt('perm_' . $protected_status . 'global_role');
569        } else {
570            $tp = $this->lng->txt('perm_' . $protected_status . 'local_role');
571        }
572
573        $inheritance_seperator = ': ';
574
575        // Show create at info
576        if (
577            ($role['assign'] == 'y' and $role['role_type'] != 'global') or
578            ($role['assign'] == 'n' and $role['role_type'] != 'global')
579        ) {
580            $tp .= ': ';
581
582            $obj = $rbacreview->getObjectOfRole($role['obj_id']);
583            if ($obj) {
584                $type = ilObject::_lookupType($this->getRefId(), true);
585                if ($objDefinition->isPlugin($type)) {
586                    $type_text = ilObjectPlugin::lookupTxtById($type, 'obj_' . $type);
587                } else {
588                    $type_text = $this->lng->txt('obj_' . ilObject::_lookupType($obj));
589                }
590
591                $tp .= sprintf(
592                    $this->lng->txt('perm_role_path_info_created'),
593                    $type_text,
594                    ilObject::_lookupTitle($obj)
595                );
596                $inheritance_seperator = ', ';
597            }
598        }
599
600        $path_hierarchy = $rbacreview->getObjectsWithStopedInheritance(
601            $role['obj_id'],
602            $tree->getPathId($this->getRefId())
603        );
604
605        $reduced_path_hierarchy = (array) array_diff(
606            $path_hierarchy,
607            array(
608                $this->getRefId(),
609                $rbacreview->getObjectReferenceOfRole($role['obj_id'])
610            )
611        );
612
613
614        // Inheritance
615        if ($role['assign'] == 'n' and count($reduced_path_hierarchy)) {
616            $tp .= $inheritance_seperator;
617
618            $parent = end($reduced_path_hierarchy);
619            $p_type = ilObject::_lookupType(ilObject::_lookupObjId($parent));
620            $p_title = ilObject::_lookupTitle(ilObject::_lookupObjId($parent));
621            $tp .= sprintf($this->lng->txt('perm_role_path_info_inheritance'), $this->lng->txt('obj_' . $p_type), $p_title);
622        }
623
624        return $tp;
625    }
626
627    /**
628     * Create (linked) title
629     * @param array $role
630     * @return
631     */
632    protected function createTitle($role)
633    {
634        global $DIC;
635
636        $ilCtrl = $DIC['ilCtrl'];
637        $objDefinition = $DIC['objDefinition'];
638
639        include_once './Services/AccessControl/classes/class.ilObjRole.php';
640        $role_title = ilObjRole::_getTranslation($role['title']);
641
642        // No local policies
643        if ($role['parent'] != $this->getRefId()) {
644            return $role_title;
645        }
646
647        $type = ilObject::_lookupType($this->getRefId(), true);
648        if ($objDefinition->isPlugin($type)) {
649            if (preg_match("/^il_./", $role["title"])) {
650                $role_title = ilObjectPlugin::lookupTxtById($type, ilObjRole::_removeObjectId($role["title"]));
651            }
652        }
653
654        if ($role['blocked']) {
655            return $role_title;
656        }
657        $ilCtrl->setParameterByClass('ilobjrolegui', 'obj_id', $role['obj_id']);
658
659        return '<a class="tblheader" href="' . $ilCtrl->getLinkTargetByClass('ilobjrolegui', '') . '" >' . $role_title . '</a>';
660    }
661}
662