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