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