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