ILIAS  release_10 Revision v10.1-43-ga1241a92c2f
class.ilDidacticTemplateLocalPolicyAction.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 /* Copyright (c) 1998-2009 ILIAS open source, Extended GPL, see docs/LICENSE */
5 
12 {
13  public const TPL_ACTION_OVERWRITE = 1;
14  public const TPL_ACTION_INTERSECT = 2;
15  public const TPL_ACTION_ADD = 3;
16  public const TPL_ACTION_SUBTRACT = 4;
17  public const TPL_ACTION_UNION = 5;
18 
20  private array $pattern = [];
21  private int $filter_type = self::FILTER_SOURCE_TITLE;
22  private int $role_template_type = self::TPL_ACTION_OVERWRITE;
23  private int $role_template_id = 0;
24 
25  public function __construct(int $action_id = 0)
26  {
28  }
29 
30  public function addFilterPattern(ilDidacticTemplateFilterPattern $pattern): void
31  {
32  $this->pattern[] = $pattern;
33  }
34 
39  public function setFilterPatterns(array $patterns): void
40  {
41  $this->pattern = $patterns;
42  }
43 
48  public function getFilterPattern(): array
49  {
50  return $this->pattern;
51  }
52 
53  public function setFilterType(int $a_type): void
54  {
55  $this->filter_type = $a_type;
56  }
57 
58  public function getFilterType(): int
59  {
60  return $this->filter_type;
61  }
62 
63  public function setRoleTemplateType(int $a_tpl_type): void
64  {
65  $this->role_template_type = $a_tpl_type;
66  }
67 
68  public function getRoleTemplateType(): int
69  {
71  }
72 
73  public function setRoleTemplateId(int $a_id): void
74  {
75  $this->role_template_id = $a_id;
76  }
77 
78  public function getRoleTemplateId(): int
79  {
81  }
82 
83  public function save(): int
84  {
85  if (!parent::save()) {
86  return 0;
87  }
88 
89  $query = 'INSERT INTO didactic_tpl_alp (action_id,filter_type,template_type,template_id) ' .
90  'VALUES( ' .
91  $this->db->quote($this->getActionId(), 'integer') . ', ' .
92  $this->db->quote($this->getFilterType(), 'integer') . ', ' .
93  $this->db->quote($this->getRoleTemplateType(), 'integer') . ', ' .
94  $this->db->quote($this->getRoleTemplateId(), 'integer') . ' ' .
95  ')';
96  $this->db->manipulate($query);
97 
98  foreach ($this->getFilterPattern() as $pattern) {
99  /* @var ilDidacticTemplateFilterPattern $pattern */
100  $pattern->setParentId($this->getActionId());
101  $pattern->setParentType(self::PATTERN_PARENT_TYPE);
102  $pattern->save();
103  }
104 
105  return $this->getActionId();
106  }
107 
108  public function delete(): void
109  {
110  parent::delete();
111  $query = 'DELETE FROM didactic_tpl_alp ' .
112  'WHERE action_id = ' . $this->db->quote($this->getActionId(), 'integer');
113  $this->db->manipulate($query);
114 
115  foreach ($this->getFilterPattern() as $pattern) {
116  $pattern->delete();
117  }
118  }
119 
120  public function apply(): bool
121  {
122  $source = $this->initSourceObject();
123  // Create a role folder for the new local policies
124  $roles = $this->filterRoles($source);
125 
126  // Create local policy for filtered roles
127  foreach ($roles as $role_id => $role) {
128  $this->getLogger()->debug('Apply to role: ' . $role['title']);
129  $this->getLogger()->debug('Role parent: ' . $role['parent']);
130  $this->getLogger()->debug('Source ref_id: ' . $source->getRefId());
131 
132  // No local policies for protected roles of higher context
133  if (
134  (int) $role['parent'] !== $source->getRefId() &&
135  $this->review->isProtected($role['parent'], $role_id)
136  ) {
137  $this->getLogger()->debug('Ignoring protected role.');
138  continue;
139  }
140  $this->createLocalPolicy($source, $role);
141  }
142 
143  return true;
144  }
145 
146  public function revert(): bool
147  {
148  $source = $this->initSourceObject();
149  $roles = $this->filterRoles($source);
150 
151  // Delete local policy for filtered roles
152  foreach ($roles as $role_id => $role) {
153  // Do not delete local policies of auto generated roles
154  if (!$this->review->isGlobalRole($role['obj_id']) &&
155  $this->review->isAssignable($role['obj_id'], $source->getRefId()) &&
156  $this->review->isSystemGeneratedRole($role['obj_id'])) {
157  $this->getLogger()->debug('Reverting local policy of auto generated role: ' . $role['title']);
158  $this->revertLocalPolicy($source, $role);
159  } else {
160  $this->getLogger()->debug('Reverting local policy and deleting local role: ' . $role['title']);
161 
162  // delete local role and change exiting objects
163  $this->admin->deleteLocalRole($role_id, $source->getRefId());
164 
165  // Change existing object
166  $role_obj = new ilObjRole($role_id);
167 
168  $protected = $this->review->isProtected($role['parent'], $role['rol_id']);
169 
170  $role_obj->changeExistingObjects(
171  $source->getRefId(),
172  $protected ?
175  ['all']
176  );
177  }
178  }
179 
180  return true;
181  }
182 
183  public function getType(): int
184  {
185  return self::TYPE_LOCAL_POLICY;
186  }
187 
188  public function toXml(ilXmlWriter $writer): void
189  {
190  $writer->xmlStartTag('localPolicyAction');
191 
192  switch ($this->getFilterType()) {
193  case self::FILTER_SOURCE_OBJ_ID:
194  $writer->xmlStartTag('roleFilter', ['source' => 'objId']);
195  break;
196 
197  case self::FILTER_PARENT_ROLES:
198  $writer->xmlStartTag('roleFilter', ['source' => 'parentRoles']);
199  break;
200 
201  case self::FILTER_LOCAL_ROLES:
202  $writer->xmlStartTag('roleFilter', ['source' => 'localRoles']);
203  break;
204 
205  case self::FILTER_SOURCE_TITLE:
206  default:
207  $writer->xmlStartTag('roleFilter', ['source' => 'title']);
208  break;
209  }
210 
211  foreach ($this->getFilterPattern() as $pattern) {
212  $pattern->toXml($writer);
213  }
214  $writer->xmlEndTag('roleFilter');
215 
216  $il_role_id = 'il_' . IL_INST_ID . '_' . ilObject::_lookupType($this->getRoleTemplateId()) . '_' . $this->getRoleTemplateId();
217 
218  switch ($this->getRoleTemplateType()) {
219  case self::TPL_ACTION_OVERWRITE:
220  $writer->xmlStartTag(
221  'localPolicyTemplate',
222  [
223  'type' => 'overwrite',
224  'id' => $il_role_id
225  ]
226  );
227  break;
228 
229  case self::TPL_ACTION_INTERSECT:
230  $writer->xmlStartTag(
231  'localPolicyTemplate',
232  [
233  'type' => 'intersect',
234  'id' => $il_role_id
235  ]
236  );
237  break;
238 
239  case self::TPL_ACTION_UNION:
240  $writer->xmlStartTag(
241  'localPolicyTemplate',
242  [
243  'type' => 'union',
244  'id' => $il_role_id
245  ]
246  );
247  break;
248  }
249 
250  $exp = new ilRoleXmlExport();
251  $exp->setMode(ilRoleXmlExport::MODE_DTPL);
252  $exp->addRole($this->getRoleTemplateId(), ROLE_FOLDER_ID);
253  $exp->write();
254  $writer->appendXML($exp->xmlDumpMem(false));
255  $writer->xmlEndTag('localPolicyTemplate');
256  $writer->xmlEndTag('localPolicyAction');
257  }
258 
259  public function __clone()
260  {
261  parent::__clone();
262 
263  $clones = [];
264  foreach ($this->getFilterPattern() as $pattern) {
265  $clones[] = clone $pattern;
266  }
267  $this->setFilterPatterns($clones);
268  }
269 
270  public function read(): void
271  {
272  parent::read();
273  $query = 'SELECT * FROM didactic_tpl_alp ' .
274  'WHERE action_id = ' . $this->db->quote($this->getActionId(), ilDBConstants::T_INTEGER);
275  $res = $this->db->query($query);
276  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
277  $this->setFilterType((int) $row->filter_type);
278  $this->setRoleTemplateType((int) $row->template_type);
279  $this->setRoleTemplateId((int) $row->template_id);
280  }
281  // Read filter
283  $this->getActionId(),
284  self::PATTERN_PARENT_TYPE
285  ) as $pattern) {
286  $this->addFilterPattern($pattern);
287  }
288  }
289 
290  protected function createLocalPolicy(ilObject $source, array $role): bool
291  {
292  // fetch role information
293  $role_data = [];
294  foreach ($this->review->getParentRoleIds($source->getRefId()) as $role_id => $tmp_role) {
295  if ((int) $role_id === (int) $role['obj_id']) {
296  $role_data = $tmp_role;
297  }
298  }
299 
300  // Add local policy
301  if (!$this->review->isRoleAssignedToObject((int) $role['obj_id'], $source->getRefId())) {
302  $this->admin->assignRoleToFolder(
303  (int) $role['obj_id'],
304  $source->getRefId(),
305  'n'
306  );
307  }
308 
309  // do nothing if role is protected in higher context
310  if (
311  (int) $role['parent'] !== $source->getRefId() &&
312  $this->review->isProtected($source->getRefId(), (int) $role['obj_id'])
313  ) {
314  $this->getLogger()->info('Ignoring protected role: ' . $role['title']);
315  return false;
316  }
317 
318  switch ($this->getRoleTemplateType()) {
319  case self::TPL_ACTION_UNION:
320 
321  $this->logger->info('Using ilRbacAdmin::copyRolePermissionUnion()');
322  $this->admin->copyRolePermissionUnion(
323  (int) $role_data['obj_id'],
324  (int) $role_data['parent'],
325  $this->getRoleTemplateId(),
327  (int) $role_data['obj_id'],
328  $source->getRefId()
329  );
330  break;
331 
332  case self::TPL_ACTION_OVERWRITE:
333 
334  $this->logger->info('Using ilRbacAdmin::copyRoleTemplatePermission()');
335  $this->admin->copyRoleTemplatePermissions(
336  $this->getRoleTemplateId(),
338  $source->getRefId(),
339  (int) $role_data['obj_id'],
340  true
341  );
342  break;
343 
344  case self::TPL_ACTION_INTERSECT:
345 
346  $this->logger->info('Using ilRbacAdmin::copyRolePermissionIntersection()' . $this->getRoleTemplateId());
347  $this->admin->copyRolePermissionIntersection(
348  (int) $role_data['obj_id'],
349  (int) $role_data['parent'],
350  $this->getRoleTemplateId(),
352  $source->getRefId(),
353  (int) $role_data['obj_id']
354  );
355  break;
356  }
357  // Change existing object
358  $role_obj = new ilObjRole((int) $role_data['obj_id']);
359  $role_obj->changeExistingObjects(
360  $source->getRefId(),
362  ['all']
363  );
364 
365  return true;
366  }
367 
368  protected function revertLocalPolicy(ilObject $source, array $role): bool
369  {
370  $this->logger->info('Reverting policy for role ' . $role['title']);
371  // Local policies can only be reverted for auto generated roles. Otherwise the
372  // original role settings are unknown
373  if (strpos($role['title'], 'il_') !== 0) {
374  $this->logger->warning('Cannot revert local policy for role ' . $role['title']);
375  return false;
376  }
377 
378  // No local policies
379  if (!$this->review->getLocalPolicies($source->getRefId())) {
380  return false;
381  }
382 
383  $exploded_title = explode('_', $role['title']);
384  $rolt_title = $exploded_title[0] . '_' . $exploded_title[1] . '_' . $exploded_title[2];
385 
386  // Lookup role template
387  $query = 'SELECT obj_id FROM object_data ' .
388  'WHERE title = ' . $this->db->quote($rolt_title, 'text') . ' ' .
389  'AND type = ' . $this->db->quote('rolt', 'text');
390  $res = $this->db->query($query);
391  $rolt_id = 0;
392  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
393  $rolt_id = (int) $row->obj_id;
394  }
395 
396  // No template found
397  if (!$rolt_id) {
398  return false;
399  }
400 
401  $this->admin->copyRoleTemplatePermissions(
402  $rolt_id,
404  $source->getRefId(),
405  (int) $role['obj_id'],
406  true
407  );
408 
409  // Change existing object
410  $role_obj = new ilObjRole((int) $role['obj_id']);
411  $role_obj->changeExistingObjects(
412  $source->getRefId(),
414  ['all']
415  );
416 
417  return true;
418  }
419 }
Class ilObjRole.
$res
Definition: ltiservices.php:69
const IL_INST_ID
Definition: constants.php:40
const MODE_PROTECTED_DELETE_LOCAL_POLICIES
appendXML(string $a_str)
append xml string to document
xmlEndTag(string $tag)
Writes an endtag.
addFilterPattern(ilDidacticTemplateFilterPattern $pattern)
const ROLE_FOLDER_ID
Definition: constants.php:34
Abstract class for template actions.
static lookupPatternsByParentId(int $a_parent_id, string $a_parent_type)
const MODE_UNPROTECTED_DELETE_LOCAL_POLICIES
__construct(Container $dic, ilPlugin $plugin)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
xmlStartTag(string $tag, ?array $attrs=null, bool $empty=false, bool $encode=true, bool $escape=true)
Writes a starttag.
static _lookupType(int $id, bool $reference=false)
Represents a filter pattern for didactic template actions.