ILIAS  release_10 Revision v10.1-43-ga1241a92c2f
class.ilLPCollectionOfRepositoryObjects.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=0);
4 
5 /* Copyright (c) 1998-2010 ILIAS open source, Extended GPL, see docs/LICENSE */
6 
13 {
14  protected static array $possible_items = array();
15 
16  protected ilTree $tree;
18 
19  public function __construct(int $a_obj_id, int $a_mode)
20  {
21  global $DIC;
22 
23  $this->tree = $DIC->repositoryTree();
24  $this->objDefinition = $DIC['objDefinition'];
25 
26  parent::__construct($a_obj_id, $a_mode);
27  }
28 
29  public function getPossibleItems(
30  int $a_ref_id,
31  bool $a_full_data = false
32  ): array {
33  global $DIC;
34 
35  $cache_idx = $a_ref_id . "__" . $a_full_data;
36  if (!isset(self::$possible_items[$cache_idx])) {
37  $all_possible = array();
38 
39  if (!$this->tree->isDeleted($a_ref_id)) {
40  if (!$a_full_data) {
41  $data = $this->tree->getRbacSubtreeInfo($a_ref_id);
42  } else {
43  $node = $this->tree->getNodeData($a_ref_id);
44  $data = $this->tree->getSubTree($node);
45  }
46  foreach ($data as $node) {
47  if (!$a_full_data) {
48  $item_ref_id = (int) $node['child'];
49  } else {
50  $item_ref_id = (int) $node['ref_id'];
51  }
52 
53  // avoid recursion
54  if ($item_ref_id == $a_ref_id || !$this->validateEntry(
55  $item_ref_id
56  )) {
57  continue;
58  }
59 
60  switch ($node['type']) {
61  case 'sess':
62  case 'exc':
63  case 'fold':
64  case 'grp':
65  case 'sahs':
66  case 'lm':
67  case 'tst':
68  case 'file':
69  case 'mcst':
70  case 'htlm':
71  case 'svy':
72  case "prg":
73  case 'iass':
74  case 'copa':
75  case 'frm':
76  case 'cmix':
77  case 'lti':
78  case 'lso':
79  case 'crsr':
80  if (!$a_full_data) {
81  $all_possible[] = $item_ref_id;
82  } else {
83  $all_possible[$item_ref_id] = array(
84  'ref_id' => (int) $item_ref_id,
85  'obj_id' => (int) $node['obj_id'],
86  'title' => (string) $node['title'],
87  'description' => (string) $node['description'],
88  'type' => (string) $node['type']
89  );
90  }
91  break;
92 
93  // repository plugin object?
94  case $this->objDefinition->isPluginTypeName(
95  $node['type']
96  ):
97  $only_active = false;
98  if (!$this->isAssignedEntry($item_ref_id)) {
99  $only_active = true;
100  }
102  $node['type'],
103  $only_active
104  )) {
105  if (!$a_full_data) {
106  $all_possible[] = $item_ref_id;
107  } else {
108  $all_possible[$item_ref_id] = array(
109  'ref_id' => (int) $item_ref_id,
110  'obj_id' => (int) $node['obj_id'],
111  'title' => (string) $node['title'],
112  'description' => (string) $node['description'],
113  'type' => (string) $node['type']
114  );
115  }
116  }
117  break;
118  }
119  }
120  }
121 
122  self::$possible_items[$cache_idx] = $all_possible;
123  }
124 
125  return self::$possible_items[$cache_idx];
126  }
127 
128  protected function validateEntry(int $a_item_id): bool
129  {
130  $a_item_type = ilObject::_lookupType($a_item_id, true);
131  // this is hardcoded so we do not need to call all ObjectLP types
132  if ($a_item_type == 'tst') {
133  // Check anonymized
134  $item_obj_id = ilObject::_lookupObjId($a_item_id);
135  $olp = ilObjectLP::getInstance($item_obj_id);
136  if ($olp->isAnonymized()) {
137  return false;
138  }
139  }
140  return true;
141  }
142 
143  public function cloneCollection(int $a_target_id, int $a_copy_id): void
144  {
145  parent::cloneCollection($a_target_id, $a_copy_id);
146 
147  $cwo = ilCopyWizardOptions::_getInstance($a_copy_id);
148  $mappings = $cwo->getMappings();
149 
150  $target_obj_id = ilObject::_lookupObjId($a_target_id);
151  $target_collection = new static($target_obj_id, $this->mode);
152 
153  // clone (active) groupings
154  foreach ($this->getGroupedItemsForLPStatus(
155  ) as $grouping_id => $group) {
156  $target_item_ids = array();
157  foreach ($group["items"] as $item) {
158  if (!isset($mappings[$item]) or !$mappings[$item]) {
159  continue;
160  }
161 
162  $target_item_ids[] = $mappings[$item];
163  }
164 
165  // grouping - if not only single item left after copy?
166  if ($grouping_id && sizeof($target_item_ids) > 1) {
167  // should not be larger than group
168  $num_obligatory = min(
169  sizeof($target_item_ids),
170  $group["num_obligatory"]
171  );
172 
173  $target_collection->createNewGrouping(
174  $target_item_ids,
175  $num_obligatory
176  );
177  } else {
178  // #15487 - single items
179  foreach ($target_item_ids as $item_id) {
180  $this->addEntry($item_id);
181  }
182  }
183  }
184  }
185 
186  protected function read(int $a_obj_id): void
187  {
188  $items = array();
189 
190  $ref_ids = ilObject::_getAllReferences($a_obj_id);
191  $ref_id = end($ref_ids);
192  $possible = $this->getPossibleItems($ref_id);
193 
194  $res = $this->db->query(
195  "SELECT utc.item_id, obd.type" .
196  " FROM ut_lp_collections utc" .
197  " JOIN object_reference obr ON item_id = ref_id" .
198  " JOIN object_data obd ON obr.obj_id = obd.obj_id" .
199  " WHERE utc.obj_id = " . $this->db->quote($a_obj_id, "integer") .
200  " AND active = " . $this->db->quote(1, "integer") .
201  " ORDER BY title"
202  );
203  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
204  if (in_array($row->item_id, $possible) &&
205  $this->validateEntry((int) $row->item_id)) {
206  $items[] = $row->item_id;
207  } else {
208  $this->deleteEntry((int) $row->item_id);
209  }
210  }
211 
212  $this->items = $items;
213  }
214 
215  protected function addEntry(int $a_item_id): bool
216  {
217  // only active entries are assigned!
218  if (!$this->isAssignedEntry($a_item_id)) {
219  // #13278 - because of grouping inactive items may exist
220  $this->deleteEntry($a_item_id);
221 
222  $query = "INSERT INTO ut_lp_collections" .
223  " (obj_id, lpmode, item_id, grouping_id, num_obligatory, active)" .
224  " VALUES (" . $this->db->quote($this->obj_id, "integer") .
225  ", " . $this->db->quote($this->mode, "integer") .
226  ", " . $this->db->quote($a_item_id, "integer") .
227  ", " . $this->db->quote(0, "integer") .
228  ", " . $this->db->quote(0, "integer") .
229  ", " . $this->db->quote(1, "integer") .
230  ")";
231  $this->db->manipulate($query);
232  $this->items[] = $a_item_id;
233  }
234  return true;
235  }
236 
237  protected function deleteEntry(int $a_item_id): bool
238  {
239  $query = "DELETE FROM ut_lp_collections " .
240  " WHERE obj_id = " . $this->db->quote($this->obj_id, "integer") .
241  " AND item_id = " . $this->db->quote($a_item_id, "integer") .
242  " AND grouping_id = " . $this->db->quote(0, "integer");
243  $this->db->manipulate($query);
244  return true;
245  }
246 
247  public static function hasGroupedItems(int $a_obj_id): bool
248  {
249  global $DIC;
250 
251  $ilDB = $DIC['ilDB'];
252  $query = "SELECT item_id FROM ut_lp_collections" .
253  " WHERE obj_id = " . $ilDB->quote($a_obj_id, "integer") .
254  " AND grouping_id > " . $ilDB->quote(0, "integer");
255  $res = $ilDB->query($query);
256  return $res->numRows() ? true : false;
257  }
258 
259  protected function getNonGroupedItems(array $a_item_ids): array
260  {
261  $grouped_item_ids = [];
262 
263  $query = "SELECT item_id FROM ut_lp_collections" .
264  " WHERE obj_id = " . $this->db->quote($this->obj_id, ilDBConstants::T_INTEGER) .
265  " AND " . $this->db->in("item_id", $a_item_ids, false, ilDBConstants::T_INTEGER) .
266  " AND grouping_id > " . $this->db->quote(0, ilDBConstants::T_INTEGER);
267  $res = $this->db->query($query);
268  while ($row = $res->fetchObject()) {
269  $grouped_item_ids[] = $row->item_id;
270  }
271 
272  return array_diff($a_item_ids, $grouped_item_ids);
273  }
274 
275  protected function getGroupingIds(array $a_item_ids): array
276  {
277  $grouping_ids = [];
278 
279  $query = "SELECT grouping_id FROM ut_lp_collections" .
280  " WHERE obj_id = " . $this->db->quote($this->obj_id, ilDBConstants::T_INTEGER) .
281  " AND " . $this->db->in("item_id", $a_item_ids, false, ilDBConstants::T_INTEGER) .
282  " AND grouping_id > " . $this->db->quote(0, ilDBConstants::T_INTEGER);
283  $res = $this->db->query($query);
284  while ($row = $res->fetchObject()) {
285  $grouping_ids[] = $row->grouping_id;
286  }
287 
288  return $grouping_ids;
289  }
290 
291  public function deactivateEntries(array $a_item_ids): void
292  {
293  parent::deactivateEntries($a_item_ids);
294 
295  $grouping_ids = $this->getGroupingIds($a_item_ids);
296  if ($grouping_ids) {
297  $query = "UPDATE ut_lp_collections" .
298  " SET active = " . $this->db->quote(0, "integer") .
299  " WHERE " . $this->db->in(
300  "grouping_id",
301  $grouping_ids,
302  false,
303  "integer"
304  ) .
305  " AND obj_id = " . $this->db->quote($this->obj_id, "integer");
306  $this->db->manipulate($query);
307  }
308  }
309 
310  public function activateEntries(array $a_item_ids): void
311  {
312  // 44683: only activate non-grouped items via parent
313  $non_grouped_ids = $this->getNonGroupedItems($a_item_ids);
314  parent::activateEntries($non_grouped_ids);
315 
316  $grouping_ids = $this->getGroupingIds($a_item_ids);
317  if ($grouping_ids) {
318  $query = "UPDATE ut_lp_collections" .
319  " SET active = " . $this->db->quote(1, "integer") .
320  " WHERE " . $this->db->in(
321  "grouping_id",
322  $grouping_ids,
323  false,
324  "integer"
325  ) .
326  " AND obj_id = " . $this->db->quote($this->obj_id, "integer");
327  $this->db->manipulate($query);
328  }
329  }
330 
331  public function createNewGrouping(
332  array $a_item_ids,
333  int $a_num_obligatory = 1
334  ): void {
335  $this->activateEntries($a_item_ids);
336 
337  $all_item_ids = array();
338  $grouping_ids = $this->getGroupingIds($a_item_ids);
339  $query = "SELECT item_id FROM ut_lp_collections" .
340  " WHERE obj_id = " . $this->db->quote($this->obj_id, "integer") .
341  " AND " . $this->db->in(
342  "grouping_id",
343  $grouping_ids,
344  false,
345  "integer"
346  );
347  $res = $this->db->query($query);
348  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
349  $all_item_ids[] = $row->item_id;
350  }
351 
352  $all_item_ids = array_unique(array_merge($all_item_ids, $a_item_ids));
353 
354  $this->releaseGrouping($a_item_ids);
355 
356  // Create new grouping
357  $query = "SELECT MAX(grouping_id) grp FROM ut_lp_collections" .
358  " WHERE obj_id = " . $this->db->quote($this->obj_id, "integer") .
359  " GROUP BY obj_id";
360  $res = $this->db->query($query);
361  $row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT);
362  $grp_id = $row->grp;
363  ++$grp_id;
364 
365  $query = "UPDATE ut_lp_collections SET" .
366  " grouping_id = " . $this->db->quote($grp_id, "integer") .
367  ", num_obligatory = " . $this->db->quote(
368  $a_num_obligatory,
369  "integer"
370  ) .
371  ", active = " . $this->db->quote(1, "integer") .
372  " WHERE obj_id = " . $this->db->quote($this->obj_id, "integer") .
373  " AND " . $this->db->in("item_id", $all_item_ids, false, "integer");
374  $this->db->manipulate($query);
375  }
376 
377  public function releaseGrouping(array $a_item_ids): void
378  {
379  $grouping_ids = $this->getGroupingIds($a_item_ids);
380 
381  $query = "UPDATE ut_lp_collections" .
382  " SET grouping_id = " . $this->db->quote(0, "integer") .
383  ", num_obligatory = " . $this->db->quote(0, "integer") .
384  " WHERE obj_id = " . $this->db->quote($this->obj_id, "integer") .
385  " AND " . $this->db->in(
386  "grouping_id",
387  $grouping_ids,
388  false,
389  "integer"
390  );
391  $this->db->manipulate($query);
392  }
393 
394  public function saveObligatoryMaterials(array $a_obl): void
395  {
396  foreach ($a_obl as $grouping_id => $num) {
397  $query = "SELECT count(obj_id) num FROM ut_lp_collections" .
398  " WHERE obj_id = " . $this->db->quote(
399  $this->obj_id,
400  "integer"
401  ) .
402  " AND grouping_id = " . $this->db->quote(
403  $grouping_id,
404  'integer'
405  ) .
406  " GROUP BY obj_id";
407  $res = $this->db->query($query);
408  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
409  if ($num <= 0 || $num >= $row->num) {
410  throw new UnexpectedValueException();
411  }
412  }
413  }
414  foreach ($a_obl as $grouping_id => $num) {
415  $query = "UPDATE ut_lp_collections" .
416  " SET num_obligatory = " . $this->db->quote($num, "integer") .
417  " WHERE obj_id = " . $this->db->quote(
418  $this->obj_id,
419  "integer"
420  ) .
421  " AND grouping_id = " . $this->db->quote(
422  $grouping_id,
423  "integer"
424  );
425  $this->db->manipulate($query);
426  }
427  }
428 
429  public function getTableGUIData(int $a_parent_ref_id): array
430  {
431  $items = $this->getPossibleItems($a_parent_ref_id, true);
432 
433  $data = array();
434  $done = array();
435  foreach ($items as $item_id => $item) {
436  if (in_array($item_id, $done)) {
437  continue;
438  }
439 
440  $table_item = $this->parseTableGUIItem($item_id, $item);
441 
442  // grouping
443  $table_item['grouped'] = array();
444  $grouped_items = $this->getTableGUItemGroup($item_id);
445  if (count((array) ($grouped_items['items'] ?? [])) > 1) {
446  foreach ($grouped_items['items'] as $grouped_item_id) {
447  if ($grouped_item_id == $item_id ||
448  !is_array($items[$grouped_item_id] ?? false)) { // #15498
449  continue;
450  }
451 
452  $table_item['grouped'][] = $this->parseTableGUIItem(
453  $grouped_item_id,
454  $items[$grouped_item_id]
455  );
456  $table_item['num_obligatory'] = $grouped_items['num_obligatory'];
457  $table_item['grouping_id'] = $grouped_items['grouping_id'];
458 
459  $done[] = $grouped_item_id;
460  }
461  }
462  $data[] = $table_item;
463  }
464  return $data;
465  }
466 
467  protected function parseTableGUIItem(int $a_id, array $a_item): array
468  {
469  $table_item = $a_item;
470  $table_item['id'] = $a_id;
471  $table_item['status'] = $this->isAssignedEntry($a_id);
472 
473  $olp = ilObjectLP::getInstance($a_item['obj_id']);
474  $table_item['mode_id'] = $olp->getCurrentMode();
475  $table_item['mode'] = $olp->getModeText($table_item['mode_id']);
476  $table_item['anonymized'] = $olp->isAnonymized();
477 
478  return $table_item;
479  }
480 
481  protected function getTableGUItemGroup(int $item_id): array
482  {
483  $items = array();
484  $query = "SELECT grouping_id FROM ut_lp_collections" .
485  " WHERE obj_id = " . $this->db->quote($this->obj_id, "integer") .
486  " AND item_id = " . $this->db->quote($item_id, "integer");
487  $res = $this->db->query($query);
488  $grouping_id = 0;
489  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
490  $grouping_id = (int) $row->grouping_id;
491  }
492  if ($grouping_id > 0) {
493  $query = "SELECT item_id, num_obligatory FROM ut_lp_collections" .
494  " WHERE obj_id = " . $this->db->quote(
495  $this->obj_id,
496  "integer"
497  ) .
498  " AND grouping_id = " . $this->db->quote(
499  $grouping_id,
500  "integer"
501  );
502  $res = $this->db->query($query);
503  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
504  $items['items'][] = (int) $row->item_id;
505  $items['num_obligatory'] = (int) $row->num_obligatory;
506  $items['grouping_id'] = (int) $grouping_id;
507  }
508  }
509  return $items;
510  }
511 
512  public function getGroupedItemsForLPStatus(): array
513  {
514  $items = $this->getItems();
515  $query = " SELECT * FROM ut_lp_collections" .
516  " WHERE obj_id = " . $this->db->quote($this->obj_id, "integer") .
517  " AND active = " . $this->db->quote(1, "integer");
518  $res = $this->db->query($query);
519 
520  $grouped = array();
521  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
522  if (in_array($row->item_id, $items)) {
523  $grouped[$row->grouping_id]['items'][] = (int) $row->item_id;
524  $grouped[$row->grouping_id]['num_obligatory'] = (int) $row->num_obligatory;
525  }
526  }
527  return $grouped;
528  }
529 }
$res
Definition: ltiservices.php:69
createNewGrouping(array $a_item_ids, int $a_num_obligatory=1)
static _getAllReferences(int $id)
get all reference ids for object ID
isAssignedEntry(int $a_item_id)
static _lookupObjId(int $ref_id)
$ref_id
Definition: ltiauth.php:66
global $DIC
Definition: shib_login.php:25
LP collection base class.
static isTypePluginWithLP(string $a_type, bool $a_active_status=true)
__construct(Container $dic, ilPlugin $plugin)
static _getInstance(int $a_copy_id)
static _lookupType(int $id, bool $reference=false)
static getInstance(int $obj_id)
getPossibleItems(int $a_ref_id, bool $a_full_data=false)