ILIAS  trunk Revision v12.0_alpha-1227-g7ff6d300864
class.ItemBlockSequenceGenerator.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
22
30
37{
38 protected array $omit_ref_ids = [];
39 protected ?string $lang = null;
41 protected bool $include_empty_blocks;
43 protected \ilAccessHandler $access;
44 protected int $block_limit;
49 protected \ilContainer $container;
50 protected ?ItemBlockSequence $sequence = null;
51 protected bool $has_other_block = false;
53 protected array $accumulated_ref_ids = [];
55 protected static array $item_group_ref_ids = [];
57 protected array $all_item_group_item_ref_ids = [];
58 protected array $all_ref_ids = [];
59
60 protected \ilLOTestAssignments $test_assignments;
61
62 public function __construct(
69 bool $include_empty_blocks = true,
70 ?string $lang = null,
71 array $omit_ref_ids = []
72 ) {
73 $this->access = $domain_service->access();
74 $this->data_service = $data_service;
75 $this->domain_service = $domain_service;
76 $this->copage_resources = $copage_resources;
77 $this->block_sequence = $block_sequence;
78 $this->item_set_manager = $item_set_manager;
79 $this->container = $container;
80 $this->mode_manager = $this->domain_service->content()->mode($container);
81 $this->include_empty_blocks = $include_empty_blocks;
82 $this->block_limit = 0;
83 $this->lang = $lang;
84 if (!$this->mode_manager->isActiveItemOrdering()) {
85 $this->block_limit = (int) \ilContainer::_lookupContainerSetting($container->getId(), "block_limit");
86 }
87 $this->test_assignments = \ilLOTestAssignments::getInstance($this->container->getId());
88 $this->omit_ref_ids = $omit_ref_ids;
89 }
90
91 public function setOmitRefIds(array $omit_ref_ids): void
92 {
93 $this->omit_ref_ids = $omit_ref_ids;
94 }
95
96 public function getSequence(): ItemBlockSequence
97 {
98 if (is_null($this->sequence)) {
100 $item_blocks = [];
101 $sorted_blocks = [];
102
103 // get blocks from block sequence parts (item groups, by type, objective)
104 foreach ($this->block_sequence->getParts() as $part) {
105 foreach ($this->getBlocksForPart($part) as $block) {
106 $item_blocks[$block->getId()] = $block;
107 }
108 }
109
110 // get blocks of page, put them to the start
111 $embedded_ids = $this->getPageEmbeddedBlockIds();
112 $other_is_page_embedded = false;
113 foreach ($embedded_ids as $id) {
114 if (isset($item_blocks[$id])) {
115 $item_blocks[$id]->setPageEmbedded(true);
116 $sorted_blocks[] = $item_blocks[$id];
117 unset($item_blocks[$id]);
118 } elseif (!is_numeric($id)) {
119 // add item blocks of page, even if originally not in the block set
120 if ($id === "_other") {
121 $this->has_other_block = true;
122 $other_is_page_embedded = true;
123 } else {
124 $ref_ids = $this->item_set_manager->getRefIdsOfType($id);
125 $this->accumulateRefIds($ref_ids);
126 $block_items = $this->determineBlockItems($ref_ids, true);
127 // we remove this check to prevent [list-cat] stuff from appearing in the list
128 // this will output a message (is empty) in editing mode and
129 // remove the block (empty string) in presentation mode
130 if ($this->include_empty_blocks || count($block_items->getRefIds()) > 0) {
131 $block = $this->data_service->itemBlock(
132 $id,
133 $this->data_service->typeBlock($id),
134 $block_items->getRefIds(),
135 $block_items->getLimitExhausted()
136 );
137 $block->setPageEmbedded(true);
138 $sorted_blocks[] = $block;
139 }
140 }
141 } else {
142 // e.g. deleted item group
143 //throw new \ilException("Missing item group data.");
144 }
145 }
146
147 // get other block
148 $other_block = $this->getOtherBlock();
149 if (!is_null($other_block)) {
150 if ($other_is_page_embedded) {
151 $other_block->setPageEmbedded(true);
152 }
153 $item_blocks["_other"] = $other_block;
154 }
155
156 // manual sorting
157 $pos = 10;
158 $sorting = \ilContainerSorting::_getInstance($this->container->getId());
159 foreach ($sorting->getBlockPositions() as $id) {
160 if (isset($item_blocks[$id])) {
161 $item_blocks[$id]->setPosition($pos);
162 $sorted_blocks[] = $item_blocks[$id];
163 unset($item_blocks[$id]);
164 $pos += 10;
165 }
166 }
167
168 // rest in order of base block sequence
169 foreach ($item_blocks as $block) {
170 $block->setPosition($pos);
171 $sorted_blocks[] = $block;
172 $pos += 10;
173 }
174 $this->sequence = new ItemBlockSequence($sorted_blocks);
175 }
176 return $this->sequence;
177 }
178
179 protected function preloadSessionandItemGroupItemData(): void
180 {
181 foreach ($this->block_sequence->getParts() as $part) {
182 // SessionBlock
183 if ($part instanceof Content\SessionBlock) {
184 /*
185 $ref_ids = $this->item_set_manager->getRefIdsOfType("sess");
186 $block_items = $this->determineBlockItems($ref_ids);
187 if (count($block_items->getRefIds()) > 0) {
188 yield $this->data_service->itemBlock(
189 "sess",
190 $this->data_service->sessionBlock(),
191 $block_items->getRefIds(),
192 $block_items->getLimitExhausted()
193 );
194 }*/
195 }
196 // ItemGroupBlock
197 if ($part instanceof Content\ItemGroupBlock) {
198 $item_ref_ids = $this->getItemGroupItemRefIds($part->getRefId());
199 $this->all_item_group_item_ref_ids = array_unique(array_merge($this->all_item_group_item_ref_ids, $item_ref_ids));
200 }
201 // ItemGroupBlocks
202 if ($part instanceof Content\ItemGroupBlocks) {
203 foreach ($this->item_set_manager->getRefIdsOfType("itgr") as $item_group_ref_id) {
204 $item_ref_ids = $this->getItemGroupItemRefIds($item_group_ref_id);
205 $this->all_item_group_item_ref_ids = array_unique(array_merge($this->all_item_group_item_ref_ids, $item_ref_ids));
206 }
207 }
208 }
209 }
210
214 protected function getBlocksForPart(BlockSequencePart $part): \Iterator
215 {
216 // TypeBlocks
217 if ($part instanceof Content\TypeBlocks) {
218 foreach ($this->getGroupedObjTypes() as $type) {
219 $ref_ids = $this->item_set_manager->getRefIdsOfType($type);
220 $this->accumulateRefIds($ref_ids);
221 $block_items = $this->determineBlockItems($ref_ids, true);
222 if ($type !== "itgr" && count($block_items->getRefIds()) > 0) {
223 yield $this->data_service->itemBlock(
224 $type,
225 $this->data_service->typeBlock($type),
226 $block_items->getRefIds(),
227 $block_items->getLimitExhausted()
228 );
229 }
230 }
231 }
232 // TypeBlock
233 if ($part instanceof Content\TypeBlock) {
234 $ref_ids = $this->item_set_manager->getRefIdsOfType($part->getType());
235 $this->accumulateRefIds($ref_ids);
236 $block_items = $this->determineBlockItems($ref_ids, true);
237 if (count($block_items->getRefIds()) > 0) {
238 yield $this->data_service->itemBlock(
239 $part->getType(),
240 $this->data_service->typeBlock($part->getType()),
241 $block_items->getRefIds(),
242 $block_items->getLimitExhausted()
243 );
244 }
245 }
246 // SessionBlock
247 if ($part instanceof Content\SessionBlock) {
248 $ref_ids = $this->item_set_manager->getRefIdsOfType("sess");
249 $this->accumulateRefIds($ref_ids);
250 $block_items = $this->determineBlockItems($ref_ids);
251 if (count($block_items->getRefIds()) > 0) {
252 yield $this->data_service->itemBlock(
253 "sess",
254 $this->data_service->sessionBlock(),
255 $block_items->getRefIds(),
256 $block_items->getLimitExhausted()
257 );
258 }
259 }
260 // ItemGroupBlock
261 if ($part instanceof Content\ItemGroupBlock) {
262 $block = $this->getItemGroupBlock($part->getRefId());
263 if (!is_null($block)) {
264 yield $block;
265 }
266 }
267 // ObjectivesBlock
268 if ($part instanceof Content\ObjectivesBlock) {
269 // in admin mode, we do not include the objectives block
270 // -> all items will be presented in item group/other block
271 if (!$this->mode_manager->isAdminMode()) {
272 $objective_ids = \ilCourseObjective::_getObjectiveIds($this->container->getId(), true);
273 $ref_ids = [];
274 foreach ($objective_ids as $objective_id) {
275 foreach (\ilObjectActivation::getItemsByObjective((int) $objective_id) as $data) {
276 $ref_ids[] = (int) $data["ref_id"];
277 }
278
279 // assigned tests -> accumulated ref ids to hide from other
280 $test_ref_ids = [];
281 $test_ref_ids[] = $this->test_assignments->getTestByObjective($objective_id, \ilLOSettings::TYPE_TEST_INITIAL);
282 $test_ref_ids[] = $this->test_assignments->getTestByObjective($objective_id, \ilLOSettings::TYPE_TEST_QUALIFIED);
283 $this->accumulateRefIds(array_filter($test_ref_ids, static function ($i) {
284 return $i > 0;
285 }));
286 }
287 $this->accumulateRefIds($ref_ids);
288 yield $this->data_service->itemBlock(
289 "_lobj",
290 $part,
291 $ref_ids,
292 false,
294 );
295 }
296 }
297 // ItemGroupBlocks
298 if ($part instanceof Content\ItemGroupBlocks) {
299 foreach ($this->item_set_manager->getRefIdsOfType("itgr") as $item_group_ref_id) {
300 $block = $this->getItemGroupBlock($item_group_ref_id);
301 if (!is_null($block)) {
302 yield $block;
303 }
304 }
305 }
306 // ItemGroupBlocks
307 if ($part instanceof Content\OtherBlock) {
308 $this->has_other_block = true;
309 }
310 }
311
312 protected function determineBlockItems(
313 array $ref_ids,
314 $filter_session_and_item_group_items = false,
315 bool $prevent_duplicats = false
316 ): BlockItemsInfo {
317 $exhausted = false;
318 $accessible_ref_ids = [];
319 foreach ($ref_ids as $ref_id) {
320 if ($prevent_duplicats && in_array($ref_id, $this->all_ref_ids)) {
321 continue;
322 }
324 continue;
325 }
326 $this->all_ref_ids[] = $ref_id;
327 if ($exhausted) {
328 break;
329 }
330 if ($this->access->checkAccess('visible', '', $ref_id)) {
331 if ($this->block_limit > 0 && count($accessible_ref_ids) >= $this->block_limit) {
332 $exhausted = true;
333 } elseif (!$filter_session_and_item_group_items || !in_array($ref_id, $this->all_item_group_item_ref_ids)) {
334 if (!in_array($ref_id, $this->omit_ref_ids)) {
335 $accessible_ref_ids[] = $ref_id;
336 }
337 }
338 }
339 }
340 return $this->data_service->blockItemsInfo(
341 $accessible_ref_ids,
342 $exhausted
343 );
344 }
345
346 protected function accumulateRefIds(array $ref_ids): void
347 {
348 foreach ($ref_ids as $ref_id) {
349 $this->accumulated_ref_ids[$ref_id] = $ref_id;
350 }
351 }
352
353 protected function getOtherBlock(): ?ItemBlock
354 {
355 if (!$this->has_other_block) {
356 return null;
357 }
358
359 $remaining_ref_ids = array_filter(
360 $this->item_set_manager->getAllRefIds(),
361 fn($i) => (!isset($this->accumulated_ref_ids[$i]) && !$this->item_set_manager->isSideBlockItem($i))
362 );
363 $block_items = $this->determineBlockItems($remaining_ref_ids, true, true);
364 // we remove this check to prevent [list-_other] stuff from appearing in the list
365 // this will output a message (is empty) in editing mode and
366 // remove the block (empty string) in presentation mode
367 if ($this->include_empty_blocks || count($block_items->getRefIds()) > 0) {
368 return $this->data_service->itemBlock(
369 "_other",
370 $this->data_service->otherBlock(),
371 $block_items->getRefIds(),
372 $block_items->getLimitExhausted()
373 );
374 }
375 return null;
376 }
377
382 protected function getGroupedObjTypes(): \Iterator
383 {
384 foreach (\ilObjectDefinition::getGroupedRepositoryObjectTypes($this->container->getType()) as $key => $type) {
385 yield $key;
386 }
387 }
388
389 protected function getItemGroupItemRefIds(int $item_group_ref_id): array
390 {
391 if (!isset(self::$item_group_ref_ids[$item_group_ref_id])) {
393 $this->container->getId()
394 )->sortSubItems('itgr', \ilObject::_lookupObjId($item_group_ref_id), \ilObjectActivation::getItemsByItemGroup($item_group_ref_id));
395
396 self::$item_group_ref_ids[$item_group_ref_id] = array_map(static function ($i) {
397 return (int) $i["child"];
398 }, $items);
399 }
400 return self::$item_group_ref_ids[$item_group_ref_id];
401 }
402
403 protected function getItemGroupBlock(int $item_group_ref_id): ?ItemBlock
404 {
405 $ref_ids = $this->getItemGroupItemRefIds($item_group_ref_id);
406 $this->accumulateRefIds($ref_ids);
407 $block_items = $this->determineBlockItems($ref_ids);
408 // #16493
409 if (!$this->access->checkAccess("visible", "", $item_group_ref_id) ||
410 !$this->access->checkAccess("read", "", $item_group_ref_id)) {
411 return null;
412 }
413 // otherwise empty item groups will simply "vanish" from the repository
414 if (count($block_items->getRefIds()) > 0 || $this->access->checkAccess('write', '', $item_group_ref_id)) {
415 return $this->data_service->itemBlock(
416 (string) $item_group_ref_id,
417 $this->data_service->itemGroupBlock($item_group_ref_id),
418 $block_items->getRefIds(),
419 $block_items->getLimitExhausted()
420 );
421 }
422 return null;
423 }
424
428 public function getPageEmbeddedBlockIds(): array
429 {
430 $page = $this->domain_service->page(
431 $this->container,
432 $this->lang
433 );
434 $dom = $page->getDom();
435
436 $ids = [];
437
438 if ($dom) {
439 $ids = $this->copage_resources->getResourceIds($dom);
440 }
441
442 return $ids;
443 }
444}
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
determineBlockItems(array $ref_ids, $filter_session_and_item_group_items=false, bool $prevent_duplicats=false)
__construct(DataService $data_service, InternalDomainService $domain_service, ResourcesManager $copage_resources, \ilContainer $container, BlockSequence $block_sequence, ItemSetManager $item_set_manager, bool $include_empty_blocks=true, ?string $lang=null, array $omit_ref_ids=[])
A block that holds a single item group.
Represents all item groups of a container.
A block that holds all objectives and their items.
A block that holds all other "remaining" items.
A block that holds session in a special presentation.
A single block containing items of a (grouped) repo type.
Represents all "by type" blocks of a container.
static _getInstance(int $a_obj_id)
Class ilContainer.
static _lookupContainerSetting(int $a_id, string $a_keyword, ?string $a_default_value=null)
static _getObjectiveIds(int $course_id, bool $a_activated_only=false)
static getInstance(int $a_container_id)
static getItemsByObjective(int $objective_id)
Get objective items.
static getItemsByItemGroup(int $item_group_ref_id)
Get materials of item group.
static getGroupedRepositoryObjectTypes($parent_obj_type)
static _lookupType(int $id, bool $reference=false)
static _lookupObjId(int $ref_id)
$ref_id
Definition: ltiauth.php:66