ILIAS  release_8 Revision v8.24
class.ilECSCourseCreationHandler.php
Go to the documentation of this file.
1<?php
2
18declare(strict_types=1);
19
24{
27 private ilTree $tree;
28
29
33 private bool $object_created = false;
34 private array $courses_created = array();
35
36 private int $mid;
37
38 public function __construct(ilECSSetting $server, int $a_mid)
39 {
40 global $DIC;
41
42 $this->logger = $DIC->logger()->wsrv();
43 $this->lng = $DIC->language();
44 $this->tree = $DIC->repositoryTree();
45
46 $this->server = $server;
47 $this->mid = $a_mid;
48 $this->mapping = ilECSNodeMappingSettings::getInstanceByServerMid($this->server->getServerId(), $this->getMid());
49
50 $this->course_url = new ilECSCourseUrl();
51 }
52
53
57 public function getServer(): ilECSSetting
58 {
59 return $this->server;
60 }
61
67 {
68 return $this->mapping;
69 }
70
75 public function getCourseUrl(): ?\ilECSCourseUrl
76 {
77 return $this->course_url;
78 }
79
83 public function isObjectCreated(): bool
84 {
86 }
87
91 public function setObjectCreated(bool $a_status): void
92 {
93 $this->object_created = $a_status;
94 }
95
99 protected function getCreatedCourses(): array
100 {
102 }
103
107 public function getMid(): int
108 {
109 return $this->mid;
110 }
111
116 public function handle(int $a_content_id, $course): bool
117 {
118 // prepare course url
119 // if any object (course group) will be created, a list of all course urls
120 // will be sent to ecs.
121 $this->setObjectCreated(false);
122 $this->course_url->setECSId($a_content_id);
123
124
125 if ($this->getMapping()->isAttributeMappingEnabled()) {
126 $this->logger->debug('Handling advanced attribute mapping');
127 return $this->doAttributeMapping($a_content_id, $course);
128 }
129
130 if ($this->getMapping()->isAllInOneCategoryEnabled()) {
131 $this->logger->debug('Handling course all in one category setting');
132 $this->doSync($a_content_id, $course, ilObject::_lookupObjId($this->getMapping()->getAllInOneCategory()));
133 return true;
134 }
135
136 $parent_obj_id = $this->syncParentContainer($a_content_id, $course);
137 if ($parent_obj_id) {
138 $this->logger->info('Using already mapped category: ' . ilObject::_lookupTitle($parent_obj_id));
139 $this->doSync($a_content_id, $course, $parent_obj_id);
140 return true;
141 }
142 $this->logger->info('Using course default category');
143 $this->doSync($a_content_id, $course, ilObject::_lookupObjId($this->getMapping()->getDefaultCourseCategory()));
144 return true;
145 }
146
150 protected function doAttributeMapping($a_content_id, $course): bool
151 {
152 // Check if course is already created
153 $course_id = $course->lectureID;
154 $obj_id = $this->getImportId((int) $course_id);
155
156 if ($obj_id) {
157 // do update
158 $this->logger->debug('Performing update of already imported course.');
159
160 $refs = ilObject::_getAllReferences($obj_id);
161 $ref = end($refs);
162
163 $this->doSync(
164 $a_content_id,
165 $course,
166 ilObject::_lookupObjId($this->tree->getParentId($ref))
167 );
168 return true;
169 }
170
171 // Get all rules
172 $matching_rules = [];
173 foreach (ilECSCourseMappingRule::getRuleRefIds($this->getServer()->getServerId(), $this->getMid()) as $ref_id) {
174 $matching_index = ilECSCourseMappingRule::isMatching(
175 $course,
176 $this->getServer()->getServerId(),
177 $this->getMid(),
178 $ref_id
179 );
180 if (strcmp($matching_index, '0') !== 0) {
181 $matching_rules[$matching_index] = $ref_id;
182 }
183 }
184 ksort($matching_rules);
185
186 $this->logger->dump($matching_rules);
187
188 if (!count($matching_rules)) {
189 // Put course in default category
190 $this->logger->debug('No matching attribute mapping rule found.');
191 $this->logger->info('Using course default category');
192 $this->doSync($a_content_id, $course, ilObject::_lookupObjId($this->getMapping()->getDefaultCourseCategory()));
193 return true;
194 }
195
196 $this->logger->debug('Matching rules:');
197 $this->logger->dump($matching_rules, ilLogLevel::DEBUG);
198
199 $all_parent_refs = [];
200 foreach ($matching_rules as $matching_rule) {
201 $this->logger->debug('Handling matching rule: ' . $matching_rule);
203 $course,
204 $this->getServer()->getServerId(),
205 $this->getMid(),
206 $matching_rule
207 );
208 // map according mapping rules
209 $this->logger->debug('Adding parent references: ' . print_r($parent_refs, true));
210 if (count($parent_refs)) {
211 $all_parent_refs = array_unique(array_merge($all_parent_refs, $parent_refs));
212 }
213 }
214
215 // parent refs are an array of created categories
216 // the first ref should contain the main course or parallel courses.
217 // all other refs wil contain course references.
218 $first = true;
219 foreach ($all_parent_refs as $category_ref) {
220 if ($first) {
221 $this->logger->debug('Creating new course instance in: ' . $category_ref);
222 $this->doSync($a_content_id, $course, ilObject::_lookupObjId($category_ref));
223 $first = false;
224 continue;
225 }
226 $this->logger->debug('Creating new course reference instance in: ' . $category_ref);
227 $this->createCourseReferenceObjects($category_ref);
228 }
229 return true;
230 }
231
235 protected function createCourseReferenceObjects(int $a_parent_ref_id): void
236 {
237 $this->logger->debug('Created new course reference in : ' . ilObject::_lookupTitle(ilObject::_lookupObjId($a_parent_ref_id)));
238 foreach ($this->getCreatedCourses() as $ref_id) {
239 $crsr = new ilObjCourseReference();
240 $crsr->setOwner(SYSTEM_USER_ID);
241 $crsr->setTargetRefId($ref_id);
242 $crsr->setTargetId(ilObject::_lookupObjId($ref_id));
243 $crsr->create();
244 $crsr->update();
245 $crsr->createReference();
246 $crsr->putInTree($a_parent_ref_id);
247 $crsr->setPermissions($a_parent_ref_id);
248
249 $this->logger->debug('Created new course reference for : ' . ilObject::_lookupTitle(ilObject::_lookupObjId($ref_id)));
250 }
251 }
252
256 protected function syncParentContainer($a_content_id, $course): int
257 {
258 if (!is_array($course->allocations)) {
259 $this->logger->debug('No allocation in course defined.');
260 return 0;
261 }
262 if (!$course->allocations[0]->parentID) {
263 $this->logger->debug('No allocation parent in course defined.');
264 return 0;
265 }
266 $parent_id = $course->allocations[0]->parentID;
267
268 $parent_tid = ilECSCmsData::lookupFirstTreeOfNode($this->getServer()->getServerId(), $this->getMid(), $parent_id);
269 return $this->syncNodetoTop($parent_tid, $parent_id);
270 }
271
276 protected function syncNodeToTop($tree_id, $cms_id): int
277 {
278 $obj_id = $this->getImportId($cms_id);
279 if ($obj_id) {
280 // node already imported
281 return $obj_id;
282 }
283
284 $tobj_id = ilECSCmsData::lookupObjId(
285 $this->getServer()->getServerId(),
286 $this->getMid(),
287 $tree_id,
288 $cms_id
289 );
290
291 // node is not imported
292 $this->logger->debug('ecs node with id ' . $cms_id . ' is not imported for mid ' . $this->getMid() . ' tree_id ' . $tree_id);
293
294 // check for mapping: if mapping is available create category
296 $this->getServer()->getServerId(),
297 $this->getMid(),
298 $tree_id,
299 $tobj_id
300 );
301
302 if ($ass->isMapped()) {
303 $this->logger->debug('node is mapped');
304 return $this->syncCategory($tobj_id, $ass->getRefId());
305 }
306
307 // Start recursion to top
308 $tree = new ilECSCmsTree($tree_id);
309 $parent_tobj_id = $tree->getParentId($tobj_id);
310 if ($parent_tobj_id) {
311 $cms_ids = ilECSCmsData::lookupCmsIds(array($parent_tobj_id));
312 $obj_id = $this->syncNodeToTop($tree_id, $cms_ids[0]);
313 }
314
315 if ($obj_id) {
316 $refs = ilObject::_getAllReferences($obj_id);
317 $ref_id = end($refs);
318 return $this->syncCategory($tobj_id, $ref_id);
319 }
320 return 0;
321 }
322
326 protected function syncCategory($tobj_id, $parent_ref_id): int
327 {
328 $data = new ilECSCmsData($tobj_id);
329
330 $cat = new ilObjCategory();
331 $cat->setOwner(SYSTEM_USER_ID);
332 $cat->setTitle($data->getTitle());
333 $cat->create(); // true for upload
334 $cat->createReference();
335 $cat->putInTree($parent_ref_id);
336 $cat->setPermissions($parent_ref_id);
337 $cat->deleteTranslation($this->lng->getDefaultLanguage());
338 $cat->addTranslation(
339 $data->getTitle(),
340 $cat->getLongDescription(),
341 $this->lng->getDefaultLanguage(),
342 $this->lng->getDefaultLanguage()
343 );
344
345 // set imported
346 $import = new ilECSImport(
347 $this->getServer()->getServerId(),
348 $cat->getId()
349 );
350 $import->setMID($this->getMid());
351 $import->setContentId($data->getCmsId());
352 $import->setImported(true);
353 $import->save();
354
355 return $cat->getId();
356 }
357
363 protected function doSync($a_content_id, $course, $a_parent_obj_id): bool
364 {
365 // Check if course is already created
366 $course_id = $course->lectureID;
367 $this->course_url->setCmsLectureId((string) $course_id);
368
369 $obj_id = $this->getImportId((int) $course_id);
370
371 $this->logger->debug('Found obj_id ' . $obj_id . ' for course_id ' . $course_id);
372
373 // Handle parallel groups
374 if ($obj_id) {
375 // update multiple courses/groups according to parallel scenario
376 $this->logger->debug('Group scenario ' . $course->groupScenario);
377 switch ((int) $course->groupScenario) {
379 $this->logger->debug('Performing update for parallel groups in course.');
380 $this->updateParallelGroups($a_content_id, $course, $obj_id);
381 break;
382
384 $this->logger->debug('Performing update for parallel courses.');
385 $this->updateParallelCourses($a_content_id, $course, $a_parent_obj_id);
386 break;
387
389 default:
390 // nothing to do
391 break;
392
393 }
394
395 // do update
396 $this->updateCourseData($course, $obj_id);
397 } else {
398 switch ((int) $course->groupScenario) {
400 $this->logger->debug('Parallel scenario "groups in courses".');
401 $crs = $this->createCourseData($course);
402 $crs = $this->createCourseReference($crs, $a_parent_obj_id);
403 $this->setImported((int) $course_id, $crs, $a_content_id);
404
405 // Create parallel groups under crs
406 $this->createParallelGroups($a_content_id, $course, $crs->getRefId());
407 break;
408
410 $this->logger->debug('Parallel scenario "Courses foreach Lecturer".');
411 // Import empty to store the ecs ressource id (used for course member update).
412 $this->setImported((int) $course_id, null, $a_content_id);
413 break;
414
416 $this->logger->debug('Parallel scenario "Many courses".');
417 $refs = ilObject::_getAllReferences($a_parent_obj_id);
418 $ref = end($refs);
419 // do not create master course for this scenario
420 //$crs = $this->createCourseData($course);
421 //$this->createCourseReference($crs, $a_parent_obj_id);
422 //$this->setImported($course_id, $crs, $a_content_id);
423 $this->createParallelCourses($a_content_id, $course, $ref);
424 break;
425
426 default:
428 $this->logger->debug('Parallel scenario "One Course".');
429 $crs = $this->createCourseData($course);
430 $this->createCourseReference($crs, $a_parent_obj_id);
431 $this->setImported((int) $course_id, $crs, $a_content_id);
432 break;
433
434
435 }
436 }
437 // finally update course urls
438 $this->handleCourseUrlUpdate();
439 return true;
440 }
441
445 protected function createParallelCourses(int $a_content_id, $course, $parent_ref): bool
446 {
447 foreach ((array) $course->groups as $group) {
448 $this->createParallelCourse($a_content_id, $course, $group, $parent_ref);
449 }
450 return true;
451 }
452
456 protected function createParallelCourse($a_content_id, $course, $group, $parent_ref): bool
457 {
458 if ($this->getImportId((int) $course->lectureID, (string) $group->id)) {
459 $this->logger->debug('Parallel course already created');
460 return false;
461 }
462
463 $course_obj = new ilObjCourse();
464 $course_obj->setOwner(SYSTEM_USER_ID);
465 $title = $course->title;
466 if ($group->title !== '') {
467 $title .= ' (' . $group->title . ')';
468 }
469 $this->logger->debug('Creating new parallel course instance from ecs : ' . $title);
470 $course_obj->setTitle($title);
471 $course_obj->setSubscriptionMaxMembers((int) $group->maxParticipants);
472 $course_obj->setOfflineStatus(true);
473 $course_obj->create();
474
475 $this->createCourseReference($course_obj, ilObject::_lookupObjId($parent_ref));
476 $this->setImported((int) $course->lectureID, $course_obj, $a_content_id, $group->id);
477 $this->setObjectCreated(true);
478 return true;
479 }
480
484 protected function updateParallelCourses($a_content_id, $course, $parent_obj): bool
485 {
486 $parent_refs = ilObject::_getAllReferences($parent_obj);
487 $parent_ref = end($parent_refs);
488
489 foreach ((array) $course->groups as $group) {
490 $title = $course->title;
491 if ($group->title !== '') {
492 $title .= ' (' . $group->title . ')';
493 }
494
495 $obj_id = $this->getImportId((int) $course->lectureID, (string) $group->id);
496 $this->logger->debug('Imported obj id is ' . $obj_id);
497 if (!$obj_id) {
498 $this->createParallelCourse($a_content_id, $course, $group, $parent_ref);
499 } else {
500 $course_obj = ilObjectFactory::getInstanceByObjId($obj_id, false);
501 if ($course_obj instanceof ilObjCourse) {
502 $this->logger->debug('New title is ' . $title);
503 $course_obj->setTitle($title);
504 if(!is_null($group->maxParticipants)) {
505 $course_obj->setSubscriptionMaxMembers($group->maxParticipants);
506 }
507 $course_obj->update();
508 }
509 }
510 $this->addUrlEntry($this->getImportId((int) $course->lectureID, (string) $group->ID));
511 }
512 return true;
513 }
514
515
516
520 protected function createParallelGroups($a_content_id, $course, $parent_ref): bool
521 {
522 foreach ((array) $course->groups as $group) {
523 $this->createParallelGroup($a_content_id, $course, $group, $parent_ref);
524 }
525 return true;
526 }
527
531 protected function createParallelGroup($a_content_id, $course, $group, $parent_ref): void
532 {
533 $group_obj = new ilObjGroup();
534 $group_obj->setOwner(SYSTEM_USER_ID);
535 $title = $group->title !== '' ? $group->title : $course->title;
536 $group_obj->setTitle($title);
537 $group_obj->setMaxMembers((int) $group->maxParticipants);
538 $group_obj->create();
539 $group_obj->createReference();
540 $group_obj->putInTree($parent_ref);
541 $group_obj->setPermissions($parent_ref);
542 $group_obj->updateGroupType(ilGroupConstants::GRP_TYPE_CLOSED);
543 $this->setImported((int) $course->lectureID, $group_obj, $a_content_id, $group->id);
544 $this->setObjectCreated(true);
545 }
546
547
551 protected function updateParallelGroups($a_content_id, $course, int $parent_obj): void
552 {
553 $parent_refs = ilObject::_getAllReferences($parent_obj);
554 $parent_ref = end($parent_refs);
555
556 foreach ((array) $course->groups as $group) {
557 $obj_id = $this->getImportId((int) $course->lectureID, (string) $group->id);
558 $this->logger->debug('Imported obj id is ' . $obj_id);
559 if (!$obj_id) {
560 $this->createParallelGroup($a_content_id, $course, $group, $parent_ref);
561 } else {
562 $group_obj = ilObjectFactory::getInstanceByObjId($obj_id, false);
563 if ($group_obj instanceof ilObjGroup) {
564 $title = $group->title !== '' ? $group->title : $course->title;
565 $this->logger->debug('New title is ' . $title);
566 $group_obj->setTitle($title);
567 if(!is_null($group->maxParticipants)) {
568 $group_obj->setMaxMembers((int) $group->maxParticipants);
569 }
570 $group_obj->update();
571 }
572 }
573 $this->addUrlEntry($this->getImportId((int) $course->lectureID, (string) $group->id));
574 }
575 }
576
582 protected function getImportId(int $a_content_id, string $a_sub_id = null): int
583 {
584 return ilECSImportManager::getInstance()->lookupObjIdByContentId(
585 $this->getServer()->getServerId(),
586 $this->getMid(),
587 $a_content_id,
588 $a_sub_id
589 );
590 }
591
595 protected function updateCourseData($course, $obj_id): bool
596 {
597 // do update
598 $refs = ilObject::_getAllReferences($obj_id);
599 $ref_id = end($refs);
601 if (!$crs_obj instanceof ilObject) {
602 $this->logger->debug('Cannot instantiate course instance');
603 return true;
604 }
605
606 // Update title
607 $title = $course->title;
608 $this->logger->debug('new title is : ' . $title);
609
610 $crs_obj->setTitle($title);
611 $crs_obj->update();
612 return true;
613 }
614
618 protected function createCourseData($course): \ilObjCourse
619 {
620 $course_obj = new ilObjCourse();
621 $course_obj->setOwner(SYSTEM_USER_ID);
622 $title = $course->title;
623 $this->logger->debug('Creating new course instance from ecs : ' . $title);
624 $course_obj->setTitle($title);
625 $course_obj->setOfflineStatus(true);
626 $course_obj->create();
627 return $course_obj;
628 }
629
633 protected function createCourseReference(ilObjCourse $crs, int $a_parent_obj_id): \ilObjCourse
634 {
635 $ref_ids = ilObject::_getAllReferences($a_parent_obj_id);
636 $ref_id = end($ref_ids);
637
638 $crs->createReference();
639 $crs->putInTree($ref_id);
640 $crs->setPermissions($ref_id);
641
642 $this->setObjectCreated(true);
643 $this->addUrlEntry($crs->getId());
644
645 $this->courses_created[] = $crs->getRefId();
646
647 return $crs;
648 }
649
653 protected function setImported(int $a_content_id, $object, $a_ecs_id = 0, $a_sub_id = null): bool
654 {
655 $import = new ilECSImport(
656 $this->getServer()->getServerId(),
657 is_object($object) ? $object->getId() : 0
658 );
659
660
661 $import->setSubId((string) $a_sub_id);
662 $import->setMID($this->getMid());
663 $import->setEContentId((string) $a_ecs_id);
664 $import->setContentId((string) $a_content_id);
665 $import->setImported(true);
666 $import->save();
667 return true;
668 }
669
673 protected function addUrlEntry(int $a_obj_id): bool
674 {
675 $refs = ilObject::_getAllReferences($a_obj_id);
676 $ref_id = end($refs);
677
678 if (!$ref_id) {
679 return false;
680 }
681 $lms_url = new ilECSCourseLmsUrl();
682 $lms_url->setTitle(ilObject::_lookupTitle($a_obj_id));
683
684 $lms_url->setUrl(ilLink::_getLink($ref_id));
685 $this->course_url->addLmsCourseUrls($lms_url);
686 return true;
687 }
688
692 protected function handleCourseUrlUpdate(): void
693 {
694 $this->logger->debug('Starting course url update');
695 if ($this->isObjectCreated()) {
696 $this->logger->debug('Sending new course group url');
697 $this->course_url->send($this->getServer(), $this->getMid());
698 } else {
699 $this->logger->debug('No courses groups created. Aborting');
700 }
701 }
702}
putInTree(int $parent_ref_id)
maybe this method should be in tree object!?
static lookupObjId(int $a_server_id, int $a_mid, int $a_tree_id, string $cms_id)
static lookupCmsIds(array $a_obj_ids)
static lookupFirstTreeOfNode($a_server_id, $a_mid, $cms_id)
Lookup first obj_id of cms node.
syncCategory($tobj_id, $parent_ref_id)
Sync category.
updateCourseData($course, $obj_id)
Update course data.
getImportId(int $a_content_id, string $a_sub_id=null)
Get import id of remote course Return 0 if object isn't imported.
setImported(int $a_content_id, $object, $a_ecs_id=0, $a_sub_id=null)
Set new course object imported.
createCourseReferenceObjects(int $a_parent_ref_id)
Create course reference objects.
handle(int $a_content_id, $course)
Handle sync request.
updateParallelGroups($a_content_id, $course, int $parent_obj)
Update parallel group data.
createParallelGroups($a_content_id, $course, $parent_ref)
This create parallel groups.
doAttributeMapping($a_content_id, $course)
Sync attribute mapping.
createCourseData($course)
Create course data from json.
addUrlEntry(int $a_obj_id)
Add an url entry.
__construct(ilECSSetting $server, int $a_mid)
setObjectCreated(bool $a_status)
Set object created status.
createParallelGroup($a_content_id, $course, $group, $parent_ref)
Create parallel group.
createParallelCourses(int $a_content_id, $course, $parent_ref)
Create parallel courses.
isObjectCreated()
Check if an object (course / group) has been created.
createParallelCourse($a_content_id, $course, $group, $parent_ref)
Create parallel course.
createCourseReference(ilObjCourse $crs, int $a_parent_obj_id)
Create course reference.
updateParallelCourses($a_content_id, $course, $parent_obj)
Update parallel group data.
syncParentContainer($a_content_id, $course)
Sync parent container.
doSync($a_content_id, $course, $a_parent_obj_id)
Handle all in one setting.
syncNodeToTop($tree_id, $cms_id)
Sync node to top.
Represents a ecs course lms url.
static getRuleRefIds(int $a_sid, int $a_mid)
static doMappings($course, int $a_sid, int $a_mid, int $a_ref_id)
static isMatching($course, int $a_sid, int $a_mid, int $a_ref_id)
Check if rule matches.
Represents a ecs course url.
static getInstance()
Get the singleton instance of this ilECSImportManager.
Storage of ECS imported objects.
static getInstanceByServerMid(int $a_server_id, int $a_mid)
Get instance.
language handling
Component logger with individual log levels by component id.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Class ilObjGroup.
static getInstanceByRefId(int $ref_id, bool $stop_on_error=true)
get an instance of an Ilias object by reference id
static getInstanceByObjId(?int $obj_id, bool $stop_on_error=true)
get an instance of an Ilias object by object id
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
setPermissions(int $parent_ref_id)
createReference()
creates reference for object
static _getAllReferences(int $id)
get all reference ids for object ID
static _lookupObjId(int $ref_id)
static _lookupTitle(int $obj_id)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
getParentId(int $a_node_id)
get parent id of given node
const SYSTEM_USER_ID
This file contains constants for PHPStan analyis, see: https://phpstan.org/config-reference#constants...
Definition: constants.php:26
global $DIC
Definition: feed.php:28
$ref_id
Definition: ltiauth.php:67