ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
class.ilSoapObjectAdministration.php
Go to the documentation of this file.
1<?php
26{
30 public function getObjIdByImportId(string $sid, string $import_id)
31 {
32 $this->initAuth($sid);
33 $this->initIlias();
34
35 if (!$this->checkSession($sid)) {
36 return $this->raiseError($this->getMessage(), $this->getMessageCode());
37 }
38 if (!$import_id) {
39 return $this->raiseError(
40 'No import id given.',
41 'Client'
42 );
43 }
44
45 global $DIC;
46
47 $ilLog = $DIC['ilLog'];
48 $obj_id = ilObject::_lookupObjIdByImportId($import_id);
49 $ilLog->write("SOAP getObjIdByImportId(): import_id = " . $import_id . ' obj_id = ' . $obj_id);
50 return $obj_id ?: "0";
51 }
52
56 public function getRefIdsByImportId(string $sid, string $import_id)
57 {
58 $this->initAuth($sid);
59 $this->initIlias();
60
61 if (!$this->checkSession($sid)) {
62 return $this->raiseError($this->getMessage(), $this->getMessageCode());
63 }
64 if (!$import_id) {
65 return $this->raiseError(
66 'No import id given.',
67 'Client'
68 );
69 }
70
71 global $DIC;
72
73 $tree = $DIC->repositoryTree();
74 $obj_id = ilObject::_lookupObjIdByImportId($import_id);
75 $ref_ids = ilObject::_getAllReferences($obj_id);
76
77 $new_refs = [];
78 foreach ($ref_ids as $ref_id) {
79 if ($tree->isInTree($ref_id)) {
80 $new_refs[] = $ref_id;
81 }
82 }
83 return $new_refs;
84 }
85
89 public function getRefIdsByObjId(string $sid, int $obj_id)
90 {
91 $this->initAuth($sid);
92 $this->initIlias();
93
94 if (!$this->checkSession($sid)) {
95 return $this->raiseError($this->getMessage(), $this->getMessageCode());
96 }
97 if (!$obj_id) {
98 return $this->raiseError(
99 'No object id given.',
100 'Client'
101 );
102 }
103
104 $ref_ids = ilObject::_getAllReferences($obj_id);
105 $new_refs = [];
106 foreach ($ref_ids as $ref_id) {
107 $new_refs[] = $ref_id;
108 }
109 return $new_refs;
110 }
111
115 public function getObjIdsByRefIds(string $sid, array $ref_ids)
116 {
117 $this->initAuth($sid);
118 $this->initIlias();
119
120 if (!$this->checkSession($sid)) {
121 return $this->raiseError($this->getMessage(), $this->getMessageCode());
122 }
123
124 if (!count($ref_ids)) {
125 return $this->raiseError('No reference id(s) given.', 'Client');
126 }
127
128 $obj_ids = [];
129 foreach ($ref_ids as $ref_id) {
130 $ref_id = trim($ref_id);
131 if (!is_numeric($ref_id)) {
132 return $this->raiseError('Reference ID has to be numeric. Value: ' . $ref_id, 'Client');
133 }
134
136 if (!$obj_id) {
137 return $this->raiseError('No object found for reference ID. Value: ' . $ref_id, 'Client');
138 }
139 if (!ilObject::_hasUntrashedReference($obj_id)) {
140 return $this->raiseError(
141 'No untrashed reference found for reference ID. Value: ' . $ref_id,
142 'Client'
143 );
144 }
145 $obj_ids[] = $obj_id;
146 }
147
148 return $obj_ids;
149 }
150
154 public function getObjectByReference(string $sid, int $a_ref_id, ?int $user_id = null)
155 {
156 $this->initAuth($sid);
157 $this->initIlias();
158
159 if (!$this->checkSession($sid)) {
160 return $this->raiseError($this->getMessage(), $this->getMessageCode());
161 }
162
163 if (!$tmp_obj = ilObjectFactory::getInstanceByRefId($a_ref_id, false)) {
164 return $this->raiseError('Cannot create object instance!', 'Server');
165 }
166 if (ilObject::_isInTrash($a_ref_id)) {
167 return $this->raiseError("Object with ID $a_ref_id has been deleted.", 'Client');
168 }
169
170 $xml_writer = new ilObjectXMLWriter();
171 $xml_writer->enablePermissionCheck(true);
172 if (is_int($user_id)) {
173 $xml_writer->setUserId($user_id);
174 $xml_writer->enableOperations(true);
175 }
176 $xml_writer->setObjects(array($tmp_obj));
177 if ($xml_writer->start()) {
178 return $xml_writer->getXML();
179 }
180 return $this->raiseError('Cannot create object xml !', 'Server');
181 }
182
186 public function getObjectsByTitle(string $sid, string $a_title, ?int $user_id = null)
187 {
188 $this->initAuth($sid);
189 $this->initIlias();
190
191 if (!$this->checkSession($sid)) {
192 return $this->raiseError($this->getMessage(), $this->getMessageCode());
193 }
194 if ($a_title === '') {
195 return $this->raiseError(
196 'No valid query string given.',
197 'Client'
198 );
199 }
200 $query_parser = new ilQueryParser($a_title);
201 $query_parser->setMinWordLength(0);
202 $query_parser->setCombination(ilQueryParser::QP_COMBINATION_AND);
203 $query_parser->parse();
204 if (!$query_parser->validate()) {
205 return $this->raiseError(
206 $query_parser->getMessage(),
207 'Client'
208 );
209 }
210
211 $object_search = new ilLikeObjectSearch($query_parser);
212 $object_search->setFields(array('title'));
213 $object_search->appendToFilter('role');
214 $object_search->appendToFilter('rolt');
215 $res = $object_search->performSearch();
216 if ($user_id) {
217 $res->setUserId($user_id);
218 }
219
220 $res->filter(ROOT_FOLDER_ID, true);
221
222 $objs = array();
223 foreach ($res->getUniqueResults() as $entry) {
224 if ($entry['type'] === 'role' || $entry['type'] === 'rolt') {
225 if ($tmp = ilObjectFactory::getInstanceByObjId($entry['obj_id'], false)) {
226 $objs[] = $tmp;
227 }
228 continue;
229 }
230 if ($tmp = ilObjectFactory::getInstanceByRefId($entry['ref_id'], false)) {
231 $objs[] = $tmp;
232 }
233 }
234 if (!count($objs)) {
235 return '';
236 }
237
238 $xml_writer = new ilObjectXMLWriter();
239 $xml_writer->enablePermissionCheck(true);
240 if (is_int($user_id)) {
241 $xml_writer->setUserId($user_id);
242 $xml_writer->enableOperations(true);
243 }
244 $xml_writer->setObjects($objs);
245 if ($xml_writer->start()) {
246 return $xml_writer->getXML();
247 }
248 return $this->raiseError('Cannot create object xml !', 'Server');
249 }
250
254 public function searchObjects(string $sid, ?array $types, string $key, string $combination, ?int $user_id = null)
255 {
256 $this->initAuth($sid);
257 $this->initIlias();
258
259 if (!$this->checkSession($sid)) {
260 return $this->raiseError($this->getMessage(), $this->getMessageCode());
261 }
262
263 if ($combination !== 'and' && $combination !== 'or') {
264 return $this->raiseError(
265 'No valid combination given. Must be "and" or "or".',
266 'Client'
267 );
268 }
269
270 $highlighter = null;
271 if (ilSearchSettings::getInstance()->enabledLucene()) {
272 ilSearchSettings::getInstance()->setMaxHits(25);
273
274 $typeFilterQuery = '';
275 if (is_array($types)) {
276 foreach ($types as $objectType) {
277 if ($typeFilterQuery === '') {
278 $typeFilterQuery .= '+( ';
279 } else {
280 $typeFilterQuery .= 'OR';
281 }
282 $typeFilterQuery .= (' type:' . $objectType . ' ');
283 }
284 $typeFilterQuery .= ') ';
285 }
286
287 $query_parser = new ilLuceneQueryParser($typeFilterQuery . $key);
288 $query_parser->parse();
289
290 $searcher = ilLuceneSearcher::getInstance($query_parser);
291 $searcher->search();
292
294 $filter->setCandidates($searcher->getResult());
295 $filter->filter();
296
297 $result_ids = $filter->getResults();
298 $objs = array();
300 foreach ($result_ids as $ref_id => $obj_id) {
302 if ($obj instanceof ilObject) {
303 $objs[] = $obj;
304 }
305 }
306 $highlighter = new ilLuceneHighlighterResultParser();
307 if ($filter->getResultObjIds()) {
308 $highlighter = $searcher->highlight($filter->getResultObjIds());
309 }
310 } else {
311
312 $query_parser = new ilQueryParser($key);
313 $query_parser->setCombination($combination === 'and' ? ilQueryParser::QP_COMBINATION_AND : ilQueryParser::QP_COMBINATION_OR);
314 $query_parser->parse();
315 if (!$query_parser->validate()) {
316 return $this->raiseError(
317 $query_parser->getMessage(),
318 'Client'
319 );
320 }
321
322 $object_search = new ilLikeObjectSearch($query_parser);
323 $object_search->setFilter($types);
324 $res = $object_search->performSearch();
325 if (is_int($user_id)) {
326 $res->setUserId($user_id);
327 }
328 $res->setMaxHits(100);
329 $res->filter(ROOT_FOLDER_ID, $combination === 'and');
330 $counter = 0;
331 $objs = array();
332 foreach ($res->getUniqueResults() as $entry) {
333 $obj = ilObjectFactory::getInstanceByRefId($entry['ref_id'], false);
334 if ($obj instanceof ilObject) {
335 $objs[] = $obj;
336 }
337 }
338 }
339
340 if (!count($objs)) {
341 return '';
342 }
343
344 $xml_writer = new ilObjectXMLWriter();
345 if (ilSearchSettings::getInstance()->enabledLucene()) {
346 $xml_writer->enableReferences(false);
347 $xml_writer->setMode(ilObjectXMLWriter::MODE_SEARCH_RESULT);
348 $xml_writer->setHighlighter($highlighter);
349 }
350
351 $xml_writer->enablePermissionCheck(true);
352
353 if ($user_id) {
354 $xml_writer->setUserId($user_id);
355 $xml_writer->enableOperations(true);
356 }
357
358 $xml_writer->setObjects($objs);
359 if ($xml_writer->start()) {
360 return $xml_writer->getXML();
361 }
362
363 return $this->raiseError('Cannot create object xml !', 'Server');
364 }
365
369 public function getTreeChilds(string $sid, int $ref_id, ?array $types = null, ?int $user_id = null)
370 {
371 $this->initAuth($sid);
372 $this->initIlias();
373
374 if (!$this->checkSession($sid)) {
375 return $this->raiseError($this->getMessage(), $this->getMessageCode());
376 }
377
378 $all = false;
379
380 global $DIC;
381
382 $tree = $DIC['tree'];
383
384 if (!$target_obj = ilObjectFactory::getInstanceByRefId($ref_id, false)) {
385 return $this->raiseError(
386 'No valid reference id given.',
387 'Client'
388 );
389 }
390 if ($ref_id === SYSTEM_FOLDER_ID) {
391 return $this->raiseError(
392 'No valid reference id given.',
393 'Client'
394 );
395 }
396
397 if (!is_array($types) || empty($types)) {
398 $all = true;
399 }
400
401 $objs = array();
402
403 foreach ($tree->getChilds($ref_id, 'title') as $child) {
404 if ($all || in_array($child['type'], $types, true)) {
405 if ($tmp = ilObjectFactory::getInstanceByRefId($child['ref_id'], false)) {
406 $objs[] = $tmp;
407 }
408 }
409 }
410
411 $xml_writer = new ilObjectXMLWriter();
412 $xml_writer->enablePermissionCheck(true);
413 $xml_writer->setObjects($objs);
414 $xml_writer->enableOperations(true);
415 if (is_int($user_id)) {
416 $xml_writer->setUserId($user_id);
417 }
418
419 if ($xml_writer->start()) {
420 return $xml_writer->getXML();
421 }
422 return $this->raiseError('Cannot create object xml !', 'Server');
423 }
424
428 public function getXMLTree(string $sid, int $ref_id, ?array $types = null, ?int $user_id = null)
429 {
430 $this->initAuth($sid);
431 $this->initIlias();
432
433 if (!$this->checkSession($sid)) {
434 return $this->raiseError($this->getMessage(), $this->getMessageCode());
435 }
436
437 global $DIC;
438
439 $tree = $DIC['tree'];
440 $access = $DIC['ilAccess'];
441
442 $nodedata = $tree->getNodeData($ref_id);
443 $nodearray = $tree->getSubTree($nodedata);
444
445 $all = false;
446 if (!is_array($types) || empty($types)) {
447 $all = true;
448 }
449
450 $filter = $types;
451
452 global $DIC;
453
454 $objDefinition = $DIC['objDefinition'];
455 $nodes = [];
456 foreach ($nodearray as $node) {
457 if (
458 !$objDefinition->isAdministrationObject($node['type']) &&
459 !$objDefinition->isSystemObject($node['type']) &&
460 ($all || !in_array($node['type'], $filter, true)) &&
461 $access->checkAccess("read", "", (int) $node['ref_id']) &&
462 ($tmp = ilObjectFactory::getInstanceByRefId($node['ref_id'], false))) {
463 $nodes[] = $tmp;
464 }
465 }
466
467 $xml_writer = new ilObjectXMLWriter();
468 $xml_writer->enablePermissionCheck(true);
469 $xml_writer->setObjects($nodes);
470 $xml_writer->enableOperations(false);
471
472 if (is_int($user_id)) {
473 $xml_writer->setUserId($user_id);
474 }
475
476 if ($xml_writer->start()) {
477 return $xml_writer->getXML();
478 }
479
480 return $this->raiseError('Cannot create object xml !', 'Server');
481 }
482
486 public function addObject(string $sid, int $a_target_id, string $a_xml)
487 {
488 $this->initAuth($sid);
489 $this->initIlias();
490
491 if (!$this->checkSession($sid)) {
492 return $this->raiseError($this->getMessage(), $this->getMessageCode());
493 }
494 if ($a_xml === '') {
495 return $this->raiseError(
496 'No valid xml string given.',
497 'Client'
498 );
499 }
500
501 global $DIC;
502
503 $rbacsystem = $DIC['rbacsystem'];
504 $objDefinition = $DIC['objDefinition'];
505 $ilUser = $DIC['ilUser'];
506 $lng = $DIC['lng'];
507 $ilObjDataCache = $DIC['ilObjDataCache'];
508
509 if (!$target_obj = ilObjectFactory::getInstanceByRefId($a_target_id, false)) {
510 return $this->raiseError(
511 'No valid target given.',
512 'Client'
513 );
514 }
515
516 if (ilObject::_isInTrash($a_target_id)) {
517 return $this->raiseError("Parent with ID $a_target_id has been deleted.", 'Client');
518 }
519
520 $allowed_types = array('root', 'cat', 'grp', 'crs', 'fold');
521 if (!in_array($target_obj->getType(), $allowed_types)) {
522 return $this->raiseError(
523 'No valid target type. Target must be reference id of "course, group, category or folder"',
524 'Client'
525 );
526 }
527
528 $allowed_subtypes = $target_obj->getPossibleSubObjects();
529 $allowed = [];
530 foreach ($allowed_subtypes as $row) {
531 if ($row['name'] !== 'rolf') {
532 $allowed[] = $row['name'];
533 }
534 }
535
536
537 $xml_parser = new ilObjectXMLParser($a_xml, true);
538 try {
539 $xml_parser->startParsing();
540 } catch (ilSaxParserException $se) {
541 return $this->raiseError($se->getMessage(), 'Client');
542 } catch (ilObjectXMLException $e) {
543 return $this->raiseError($e->getMessage(), 'Client');
544 }
545
546 $newObj = null;
547 foreach ($xml_parser->getObjectData() as $object_data) {
548 $res = $this->validateReferences('create', $object_data, $a_target_id);
549 if ($this->isFault($res)) {
550 return $res;
551 }
552
553 // Check possible subtype
554 if (!in_array($object_data['type'], $allowed, true)) {
555 return $this->raiseError(
556 'Objects of type: ' . $object_data['type'] . ' are not allowed to be subobjects of type ' .
557 $target_obj->getType() . '!',
558 'Client'
559 );
560 }
561 if (!$rbacsystem->checkAccess('create', $a_target_id, $object_data['type'])) {
562 return $this->raiseError(
563 'No permission to create objects of type ' . $object_data['type'] . '!',
564 'Client'
565 );
566 }
567
568 // It's not possible to add objects with non unique import ids
569 if ($object_data['import_id'] != '' && ilObject::_lookupObjIdByImportId($object_data['import_id'])) {
570 return $this->raiseError(
571 'An object with import id ' . $object_data['import_id'] . ' already exists!',
572 'Server'
573 );
574 }
575
576 // call gui object method
577 $class_name = $objDefinition->getClassName($object_data['type']);
578 $location = $objDefinition->getLocation($object_data['type']);
579
580 $class_constr = "ilObj" . $class_name;
581
582 $newObj = new $class_constr();
583 if (isset($object_data['owner']) && $object_data['owner'] != '') {
584 if ((int) $object_data['owner']) {
585 if (ilObject::_exists((int) $object_data['owner']) &&
586 $ilObjDataCache->lookupType((int) $object_data['owner']) === 'usr') {
587 $newObj->setOwner((int) $object_data['owner']);
588 }
589 } else {
590 $usr_id = ilObjUser::_lookupId(trim($object_data['owner']));
591 if ((int) $usr_id) {
592 $newObj->setOwner((int) $usr_id);
593 }
594 }
595 }
596
597 $newObj->setType($object_data['type']);
598 if ($object_data['import_id'] != '') {
599 $newObj->setImportId($object_data['import_id']);
600 }
601
602 if ($objDefinition->supportsOfflineHandling($newObj->getType())) {
603 $newObj->setOfflineStatus((bool) $object_data['offline']);
604 }
605 $newObj->setTitle($object_data['title']);
606 $newObj->setDescription($object_data['description']);
607 $newObj->create(); // true for upload
608 $newObj->createReference();
609 $newObj->putInTree($a_target_id);
610 $newObj->setPermissions($a_target_id);
611
612 switch ($object_data['type']) {
613 case 'grp':
614 // Add member
615 $newObj->addMember(
616 $object_data['owner'] ?: $ilUser->getId(),
617 $newObj->getDefaultAdminRole()
618 );
619 break;
620
621 case 'crs':
622 $newObj->getMemberObject()->add($ilUser->getId(), ilParticipants::IL_CRS_ADMIN);
623 break;
624 case 'lm':
625 $newObj->createLMTree();
626 break;
627 case 'cat':
629 $newObj->addTranslation(
630 $object_data["title"],
631 $object_data["description"],
632 $lng->getLangKey(),
633 true
634 );
635 break;
636 }
637
638 $this->addReferences($newObj, $object_data);
639 }
640 if (!$newObj instanceof ilObject) {
641 return 0;
642 }
643 $ref_id = $newObj->getRefId();
644 return $ref_id ?: "0";
645 }
646
650 public function addReference(string $sid, int $a_source_id, int $a_target_id)
651 {
652 $this->initAuth($sid);
653 $this->initIlias();
654
655 if (!$this->checkSession($sid)) {
656 return $this->raiseError($this->getMessage(), $this->getMessageCode());
657 }
658
659 global $DIC;
660
661 $objDefinition = $DIC['objDefinition'];
662 $rbacsystem = $DIC['rbacsystem'];
663 $tree = $DIC['tree'];
664
665 if (!$source_obj = ilObjectFactory::getInstanceByRefId($a_source_id, false)) {
666 return $this->raiseError(
667 'No valid source id given.',
668 'Client'
669 );
670 }
671 if (!$target_obj = ilObjectFactory::getInstanceByRefId($a_target_id, false)) {
672 return $this->raiseError(
673 'No valid target id given.',
674 'Client'
675 );
676 }
677
678 if (!$objDefinition->allowLink($source_obj->getType()) and
679 $source_obj->getType() !== 'cat' and
680 $source_obj->getType() !== 'crs') {
681 return $this->raiseError(
682 'Linking of object type: ' . $source_obj->getType() . ' is not allowed',
683 'Client'
684 );
685 }
686
687 $allowed_subtypes = $target_obj->getPossibleSubObjects();
688 $allowed = [];
689 foreach ($allowed_subtypes as $row) {
690 if ($row['name'] !== 'rolf') {
691 $allowed[] = $row['name'];
692 }
693 }
694 if (!in_array($source_obj->getType(), $allowed, true)) {
695 return $this->raiseError(
696 'Objects of type: ' . $source_obj->getType() . ' are not allowed to be subobjects of type ' .
697 $target_obj->getType() . '!',
698 'Client'
699 );
700 }
701
702 // Permission checks
703 if (!$rbacsystem->checkAccess('create', $target_obj->getRefId(), $source_obj->getType())) {
704 return $this->raiseError(
705 'No permission to create objects of type ' . $source_obj->getType() . '!',
706 'Client'
707 );
708 }
709 if (!$rbacsystem->checkAccess('delete', $source_obj->getRefId())) {
710 return $this->raiseError(
711 'No permission to link object with id: ' . $source_obj->getRefId() . '!',
712 'Client'
713 );
714 }
715
716 if ($source_obj->getType() !== 'cat' and $source_obj->getType() !== 'crs') {
717 // check if object already linked to target
718 $possibleChilds = $tree->getChildsByType($target_obj->getRefId(), $source_obj->getType());
719 foreach ($possibleChilds as $child) {
720 if ((int) $child["obj_id"] === $source_obj->getId()) {
721 return $this->raiseError("Object already linked to target.", "Client");
722 }
723 }
724
725 // Finally link it to target position
726
727 $new_ref_id = $source_obj->createReference();
728 $source_obj->putInTree($target_obj->getRefId());
729 $source_obj->setPermissions($target_obj->getRefId());
730
731 return $new_ref_id ?: "0";
732 }
733
734 $new_ref = null;
735 switch ($source_obj->getType()) {
736 case 'cat':
737 $new_ref = new ilObjCategoryReference();
738 break;
739
740 case 'crs':
741 $new_ref = new ilObjCourseReference();
742 break;
743 case 'grp':
744 $new_ref = new ilObjGroupReference();
745 break;
746 }
747 $new_ref->create();
748 $new_ref_id = $new_ref->createReference();
749
750 $new_ref->putInTree($target_obj->getRefId());
751 $new_ref->setPermissions($target_obj->getRefId());
752
753 $new_ref->setTargetId($source_obj->getId());
754 $new_ref->update();
755
756 if (!$new_ref instanceof ilObject) {
757 return 0;
758 }
759
760 return $new_ref_id ?: 0;
761 }
762
766 public function deleteObject(string $sid, int $reference_id)
767 {
768 $this->initAuth($sid);
769 $this->initIlias();
770
771 if (!$this->checkSession($sid)) {
772 return $this->raiseError($this->getMessage(), $this->getMessageCode());
773 }
774
775 global $DIC;
776
777 $tree = $DIC->repositoryTree();
778 $rbacsystem = $DIC['rbacsystem'];
779 $rbacadmin = $DIC['rbacadmin'];
780 $user = $DIC->user();
781
782 if (!$del_obj = ilObjectFactory::getInstanceByRefId($reference_id, false)) {
783 return $this->raiseError(
784 'No valid reference id given.',
785 'Client'
786 );
787 }
788 if (!$rbacsystem->checkAccess('delete', $del_obj->getRefId())) {
789 return $this->raiseError(
790 'No permission to delete object with id: ' . $del_obj->getRefId() . '!',
791 'Client'
792 );
793 }
794
795 if ($tree->isDeleted($reference_id)) {
796 return $this->raiseError('Node already deleted', 'Server');
797 }
798
799 if ($del_obj->getType() === 'rolf') {
800 return $this->raiseError('Delete is not available for role folders.', 'Client');
801 }
802
803 $subnodes = $tree->getSubTree($tree->getNodeData($reference_id));
804 foreach ($subnodes as $subnode) {
805 $rbacadmin->revokePermission($subnode["child"]);
806 }
807 if (!$tree->moveToTrash($reference_id, true, $user->getId())) {
808 return $this->raiseError('Node already deleted', 'Client');
809 }
810 return true;
811 }
812
816 public function removeFromSystemByImportId(string $sid, string $import_id)
817 {
818 $this->initAuth($sid);
819 $this->initIlias();
820
821 if (!$this->checkSession($sid)) {
822 return $this->raiseError($this->getMessage(), $this->getMessageCode());
823 }
824 if ($import_id === '') {
825 return $this->raiseError(
826 'No import id given. Aborting!',
827 'Client'
828 );
829 }
830 global $DIC;
831
832 $rbacsystem = $DIC['rbacsystem'];
833 $tree = $DIC['tree'];
834 $ilLog = $DIC['ilLog'];
835
836 // get obj_id
837 if (!$obj_id = ilObject::_lookupObjIdByImportId($import_id)) {
838 return $this->raiseError(
839 'No object found with import id: ' . $import_id,
840 'Client'
841 );
842 }
843
844 // Check access
845 $permission_ok = false;
846 foreach ($ref_ids = ilObject::_getAllReferences($obj_id) as $ref_id) {
847 if ($rbacsystem->checkAccess('delete', $ref_id)) {
848 $permission_ok = true;
849 break;
850 }
851 }
852 if (!$permission_ok) {
853 return $this->raiseError(
854 'No permission to delete the object with import id: ' . $import_id,
855 'Server'
856 );
857 }
858
859 // Delete all references (delete permssions and entries in object_reference)
860 foreach ($ref_ids as $ref_id) {
861 // All subnodes
862 $node_data = $tree->getNodeData($ref_id);
863 $subtree_nodes = $tree->getSubtree($node_data);
864
865 foreach ($subtree_nodes as $node) {
866 $ilLog->write('Soap: removeFromSystemByImportId(). Deleting object with title id: ' . $node['title']);
867 $tmp_obj = ilObjectFactory::getInstanceByRefId($node['ref_id']);
868 if (!is_object($tmp_obj)) {
869 return $this->raiseError(
870 'Cannot create instance of reference id: ' . $node['ref_id'],
871 'Server'
872 );
873 }
874 $tmp_obj->delete();
875 }
876 // Finally delete tree
877 $tree->deleteTree($node_data);
878 }
879 return true;
880 }
881
885 public function updateObjects(string $sid, string $a_xml)
886 {
887 $this->initAuth($sid);
888 $this->initIlias();
889
890 if (!$this->checkSession($sid)) {
891 return $this->raiseError($this->getMessage(), $this->getMessageCode());
892 }
893 if ($a_xml === '') {
894 return $this->raiseError(
895 'No valid xml string given.',
896 'Client'
897 );
898 }
899
900 global $DIC;
901
902 $rbacreview = $DIC['rbacreview'];
903 $rbacsystem = $DIC['rbacsystem'];
904 $lng = $DIC['lng'];
905 $ilAccess = $DIC['ilAccess'];
906 $objDefinition = $DIC['objDefinition'];
907
908 $xml_parser = new ilObjectXMLParser($a_xml, true);
909 try {
910 $xml_parser->startParsing();
911 } catch (ilSaxParserException $se) {
912 return $this->raiseError($se->getMessage(), 'Client');
913 } catch (ilObjectXMLException $e) {
914 return $this->raiseError($e->getMessage(), 'Client');
915 }
916
917 // Validate incoming data
918 $object_datas = $xml_parser->getObjectData();
919 foreach ($object_datas as &$object_data) {
920 $res = $this->validateReferences('update', $object_data);
921 if ($this->isFault($res)) {
922 return $res;
923 }
924
925 if (!$object_data["obj_id"]) {
926 return $this->raiseError('No obj_id in xml found.', 'Client');
927 } elseif ((int) $object_data["obj_id"] === -1 && count($object_data["references"]) > 0) {
928 // object id might be unknown, resolve references instead to determine object id
929 // all references should point to the same object, so using the first one is ok.
930 foreach ($object_data["references"] as $refid) {
931 if (ilObject::_isInTrash($refid)) {
932 continue;
933 }
934 break;
935 }
936
937 $obj_id_from_refid = ilObject::_lookupObjectId($object_data["references"][0]);
938 if (!$obj_id_from_refid) {
939 return $this->raiseError(
940 'No obj_id found for reference id ' . $object_data["references"][0],
941 'CLIENT_OBJECT_NOT_FOUND'
942 );
943 }
944
945 $tmp_obj = ilObjectFactory::getInstanceByObjId($object_data['obj_id'], false);
946 $object_data["obj_id"] = $obj_id_from_refid;
947 }
948
949 $tmp_obj = ilObjectFactory::getInstanceByObjId($object_data['obj_id'], false);
950 if ($tmp_obj === null) {
951 return $this->raiseError(
952 'No object for id ' . $object_data['obj_id'] . '!',
953 'CLIENT_OBJECT_NOT_FOUND'
954 );
955 }
956
957 $object_data["instance"] = $tmp_obj;
958
959 if ($object_data['type'] === 'role') {
960 $rolf_ids = $rbacreview->getFoldersAssignedToRole($object_data['obj_id'], true);
961 $rolf_id = $rolf_ids[0];
962
963 if (!$rbacsystem->checkAccess('write', $rolf_id)) {
964 return $this->raiseError(
965 'No write permission for object with id ' . $object_data['obj_id'] . '!',
966 'Client'
967 );
968 }
969 } else {
970 $permission_ok = false;
971 foreach (ilObject::_getAllReferences($object_data['obj_id']) as $ref_id) {
972 if ($ilAccess->checkAccess('write', '', $ref_id)) {
973 $permission_ok = true;
974 break;
975 }
976 }
977 if (!$permission_ok) {
978 return $this->raiseError(
979 'No write permission for object with id ' . $object_data['obj_id'] . '!',
980 'Client'
981 );
982 }
983 }
984 }
985 unset($object_data);
986
987 // perform update
988 if (count($object_datas) > 0) {
989 foreach ($object_datas as $object_data) {
990 $this->updateReferences($object_data);
994 $tmp_obj = $object_data["instance"];
995 $tmp_obj->setTitle($object_data['title']);
996 $tmp_obj->setDescription($object_data['description']);
997
998 if ($objDefinition->supportsOfflineHandling($tmp_obj->getType())) {
999 $tmp_obj->setOfflineStatus($object_data['offline']);
1000 }
1001
1002 $tmp_obj->update();
1003 if ($object_data['owner'] != '' && is_numeric($object_data['owner'])) {
1004 $tmp_obj->setOwner($object_data['owner']);
1005 $tmp_obj->updateOwner();
1006 }
1007 }
1008 return true;
1009 }
1010 return false;
1011 }
1012
1016 public function moveObject(string $sid, int $ref_id, int $target_id)
1017 {
1018 $this->initAuth($sid);
1019 $this->initIlias();
1020
1021 if (!$this->checkSession($sid)) {
1022 return $this->raiseError($this->getMessage(), $this->getMessageCode());
1023 }
1024
1025 global $DIC;
1026
1027 $rbacreview = $DIC['rbacreview'];
1028 $rbacadmin = $DIC['rbacadmin'];
1029 $objDefinition = $DIC['objDefinition'];
1030 $rbacsystem = $DIC['rbacsystem'];
1031 $lng = $DIC['lng'];
1032 $ilUser = $DIC['ilUser'];
1033 $tree = $DIC['tree'];
1034
1035 // does source object exist
1036 if (!$source_object_type = ilObjectFactory::getTypeByRefId($ref_id, false)) {
1037 return $this->raiseError('No valid source given.', 'Client');
1038 }
1039
1040 // does target object exist
1041 if (!$target_object_type = ilObjectFactory::getTypeByRefId($target_id, false)) {
1042 return $this->raiseError('No valid target given.', 'Client');
1043 }
1044
1045 // check for trash
1046 if (ilObject::_isInTrash($ref_id)) {
1047 return $this->raiseError('Object is trashed.', 'Client');
1048 }
1049
1050 if (ilObject::_isInTrash($target_id)) {
1051 return $this->raiseError('Object is trashed.', 'Client');
1052 }
1053
1054 $canAddType = $this->canAddType($source_object_type, $target_object_type, $target_id);
1055 if ($this->isFault($canAddType)) {
1056 return $canAddType;
1057 }
1058
1059 // check if object already linked to target
1060 $possibleChilds = $tree->getChildsByType($target_id, $ref_id);
1061 foreach ($possibleChilds as $child) {
1062 if ((int) $child["obj_id"] === $ref_id) {
1063 return $this->raiseError("Object already exists in target.", "Client");
1064 }
1065 }
1066
1067 // CHECK IF PASTE OBJECT SHALL BE CHILD OF ITSELF
1068 if ($tree->isGrandChild($ref_id, $target_id)) {
1069 return $this->raiseError("Cannot move object into itself.", "Client");
1070 }
1071
1072 $old_parent = $tree->getParentId($ref_id);
1073 $tree->moveTree($ref_id, $target_id);
1074 $rbacadmin->adjustMovedObjectPermissions($ref_id, $old_parent);
1075
1077 return true;
1078 }
1079
1083 public function copyObject(string $sid, string $copy_settings_xml)
1084 {
1085 $this->initAuth($sid);
1086 $this->initIlias();
1087
1088 if (!$this->checkSession($sid)) {
1089 return $this->raiseError($this->getMessage(), $this->getMessageCode());
1090 }
1091
1092 global $DIC;
1093
1094 $rbacreview = $DIC['rbacreview'];
1095 $objDefinition = $DIC['objDefinition'];
1096 $rbacsystem = $DIC['rbacsystem'];
1097 $lng = $DIC['lng'];
1098 $ilUser = $DIC['ilUser'];
1099
1100 $xml_parser = new ilCopyWizardSettingsXMLParser($copy_settings_xml);
1101 try {
1102 $xml_parser->startParsing();
1103 } catch (ilSaxParserException $se) {
1104 return $this->raiseError($se->getMessage(), "Client");
1105 }
1106
1107 // checking copy permissions, objects and create permissions
1108 if (!$rbacsystem->checkAccess('copy', $xml_parser->getSourceId())) {
1109 return $this->raiseError(
1110 "Missing copy permissions for object with reference id " . $xml_parser->getSourceId(),
1111 'Client'
1112 );
1113 }
1114
1115 // checking copy permissions, objects and create permissions
1116 $source_id = $xml_parser->getSourceId();
1117 $target_id = $xml_parser->getTargetId();
1118
1119 // does source object exist
1120 if (!$source_object_type = ilObjectFactory::getTypeByRefId($source_id, false)) {
1121 return $this->raiseError('No valid source given.', 'Client');
1122 }
1123
1124 // does target object exist
1125 if (!$target_object_type = ilObjectFactory::getTypeByRefId($xml_parser->getTargetId(), false)) {
1126 return $this->raiseError('No valid target given.', 'Client');
1127 }
1128
1129 $canAddType = $this->canAddType($source_object_type, $target_object_type, $target_id);
1130 if ($this->isFault($canAddType)) {
1131 return $canAddType;
1132 }
1133
1134 // if is container object than clone with sub items
1135 $options = $xml_parser->getOptions();
1136 // print_r($options);
1137 $source_object = ilObjectFactory::getInstanceByRefId($source_id);
1138 if ($source_object instanceof ilContainer) {
1139 // get client id from sid
1140 $clientid = substr($sid, strpos($sid, "::") + 2);
1141 $sessionid = str_replace("::" . $clientid, "", $sid);
1142 // call container clone
1143 $ret = $source_object->cloneAllObject(
1144 $sessionid,
1145 $clientid,
1146 $source_object_type,
1147 $target_id,
1148 $source_id,
1149 $options,
1150 true
1151 );
1152
1153 return $ret['ref_id'];
1154 }
1155
1156 // create copy wizard settings
1158 $wizard_options = ilCopyWizardOptions::_getInstance($copy_id);
1159 $wizard_options->saveOwner($ilUser->getId());
1160 $wizard_options->saveRoot($source_id);
1161
1162 foreach ($options as $source_id => $option) {
1163 $wizard_options->addEntry($source_id, $option);
1164 }
1165 $wizard_options->read();
1166
1167 // call object clone
1168 $newObject = $source_object->cloneObject($xml_parser->getTargetId(), $copy_id);
1169 return is_object($newObject) ? $newObject->getRefId() : -1;
1170 }
1171
1175 public function getPathForRefId(string $sid, int $ref_id)
1176 {
1177 $this->initAuth($sid);
1178 $this->initIlias();
1179
1180 if (!$this->checkSession($sid)) {
1181 return $this->raiseError($this->getMessage(), $this->getMessageCode());
1182 }
1183
1184 global $DIC;
1185
1186 $ilAccess = $DIC['ilAccess'];
1187 $objDefinition = $DIC['objDefinition'];
1188 $rbacsystem = $DIC['rbacsystem'];
1189 $lng = $DIC['lng'];
1190 $ilUser = $DIC['ilUser'];
1191
1192 if (!$rbacsystem->checkAccess('read', $ref_id)) {
1193 return $this->raiseError("Missing read permissions for object with reference id " . $ref_id, 'Client');
1194 }
1195
1197 return $this->raiseError("Object is in Trash", 'Client');
1198 }
1199 global $DIC;
1200
1201 $tree = $DIC['tree'];
1202 $lng = $DIC['lng'];
1203 $items = $tree->getPathFull($ref_id);
1204
1205 $xmlResultSet = new ilXMLResultSet();
1206 $xmlResultSet->addColumn("ref_id");
1207 $xmlResultSet->addColumn("type");
1208 $xmlResultSet->addColumn("title");
1209
1210 $writer = new ilXMLResultSetWriter($xmlResultSet);
1211 foreach ($items as $item) {
1212 if ((int) $item["ref_id"] === $ref_id) {
1213 continue;
1214 }
1215 if ($item["title"] === "ILIAS" && $item["type"] === "root") {
1216 $item["title"] = $lng->txt("repository");
1217 }
1218
1219 $row = new ilXMLResultSetRow();
1220 $xmlResultSet->addRow($row);
1221 $row->setValue("ref_id", $item["ref_id"]);
1222 $row->setValue("type", $item["type"]);
1223 $row->setValue("title", $item["title"]);
1224 }
1225 $writer->start();
1226 return $writer->getXML();
1227 }
1228
1229 private function canAddType(string $type, string $target_type, int $target_id)
1230 {
1231 // checking for target subtypes. Can we add source to target
1232 global $DIC;
1233
1234 $objDefinition = $DIC['objDefinition'];
1235 $rbacsystem = $DIC['rbacsystem'];
1236
1237 $allowed_types = array('root', 'cat', 'grp', 'crs', 'fold');
1238 if (!in_array($target_type, $allowed_types, true)) {
1239 return $this->raiseError(
1240 'No valid target type. Target must be reference id of "course, group, category or folder"',
1241 'Client'
1242 );
1243 }
1244
1245 $allowed_subtypes = $objDefinition->getSubObjects($target_type);
1246 $allowed = array();
1247
1248 foreach ($allowed_subtypes as $row) {
1249 if ($row['name'] !== 'rolf') {
1250 $allowed[] = $row['name'];
1251 }
1252 }
1253
1254 if (!in_array($type, $allowed, true)) {
1255 return $this->raiseError(
1256 'Objects of type: ' . $type . ' are not allowed to be subobjects of type ' . $target_type . '!',
1257 'Client'
1258 );
1259 }
1260 if (!$rbacsystem->checkAccess('create', $target_id, $type)) {
1261 return $this->raiseError('No permission to create objects of type ' . $type . '!', 'Client');
1262 }
1263
1264 return true;
1265 }
1266
1267 private function validateReferences(string $a_action, array $a_object_data, int $a_target_id = 0)
1268 {
1269 global $DIC;
1270
1271 $ilAccess = $DIC['ilAccess'];
1272
1273 if (!isset($a_object_data['references']) || !count($a_object_data['references'])) {
1274 return true;
1275 }
1276 if ($a_action === 'create') {
1277 if (count($a_object_data['references']) > 1 && in_array(
1278 $a_object_data['type'],
1279 ['cat', 'crs', 'grp', 'fold'],
1280 true
1281 )) {
1282 return $this->raiseError(
1283 "Cannot create references for type " . $a_object_data['type'],
1284 'Client'
1285 );
1286 }
1287 if (count($a_object_data['references']) === 1 && $a_target_id != $a_object_data['references'][0]['parent_id']) {
1288 return $this->raiseError(
1289 "Cannot create references for type " . $a_object_data['type'],
1290 'Client'
1291 );
1292 }
1293
1294 foreach ($a_object_data['references'] as $ref_data) {
1295 if (!$ref_data['parent_id']) {
1296 return $this->raiseError('Element References: No parent Id given!', 'Client');
1297 }
1298
1299 $target_type = ilObject::_lookupType(ilObject::_lookupObjId($ref_data['parent_id']));
1300 $can_add_type = $this->canAddType($a_object_data['type'], $target_type, $ref_data['parent_id']);
1301 if ($this->isFault($can_add_type)) {
1302 return $can_add_type;
1303 }
1304 }
1305 return true;
1306 }
1307
1308 if ($a_action === 'update') {
1309 foreach ($a_object_data['references'] as $ref_data) {
1310 if (!$ref_data['ref_id']) {
1311 return $this->raiseError('Element References: No reference id given!', 'Client');
1312 }
1313 // check permissions
1314 if (!$ilAccess->checkAccess('write', '', $ref_data['ref_id'])) {
1315 return $this->raiseError(
1316 'No write permission for object with reference id ' . $ref_data['ref_id'] . '!',
1317 'Client'
1318 );
1319 }
1320 // TODO: check if all references belong to the same object
1321 }
1322 return true;
1323 }
1324 return true;
1325 }
1326
1327 private function updateReferences(array $a_object_data): void
1328 {
1329 global $DIC;
1330
1331 $tree = $DIC['tree'];
1332 $ilLog = $DIC['ilLog'];
1333
1334 if (!isset($a_object_data['references']) || !count($a_object_data['references'])) {
1335 return;
1336 }
1337
1338 foreach ($a_object_data['references'] as $ref_data) {
1339 if (isset($ref_data['time_target'])) {
1340 $old = ilObjectActivation::getItem($ref_data['ref_id']);
1341
1342 $items = new ilObjectActivation();
1343 $items->toggleChangeable($ref_data['time_target']['changeable'] ?? $old['changeable']);
1344 $items->setTimingStart($ref_data['time_target']['starting_time'] ?? $old['timing_start']);
1345 $items->setTimingEnd($ref_data['time_target']['ending_time'] ?? $old['timing_end']);
1346 $items->toggleVisible($ref_data['time_target']['timing_visibility'] ?? $old['visible']);
1347 $items->setSuggestionStart($ref_data['time_target']['suggestion_start'] ?? $old['suggestion_start']);
1348 $items->setSuggestionEnd($ref_data['time_target']['suggestion_end'] ?? $old['suggestion_end']);
1349
1350 switch ($ref_data['time_target']['timing_type']) {
1352 $ilLog->write(__METHOD__ . ilObjectActivation::TIMINGS_DEACTIVATED . ' ' . $ref_data['time_target']['timing_type']);
1353 $items->setTimingType(ilObjectActivation::TIMINGS_DEACTIVATED);
1354 break;
1355
1357 $ilLog->write(__METHOD__ . ilObjectActivation::TIMINGS_ACTIVATION . ' ' . $ref_data['time_target']['timing_type']);
1358 $items->setTimingType(ilObjectActivation::TIMINGS_ACTIVATION);
1359 break;
1360
1362 $ilLog->write(__METHOD__ . ilObjectActivation::TIMINGS_PRESETTING . ' ' . $ref_data['time_target']['timing_type']);
1363 $items->setTimingType(ilObjectActivation::TIMINGS_PRESETTING);
1364 break;
1365 }
1366 $items->update($ref_data['ref_id']);
1367 }
1368 }
1369 }
1370
1371 private function addReferences(ilObject $source, array $a_object_data): void
1372 {
1373 global $DIC;
1374
1375 $tree = $DIC->repositoryTree();
1376 $ilLog = $DIC['ilLog'];
1377
1378 if (!isset($a_object_data['references']) || !count($a_object_data['references'])) {
1379 return;
1380 }
1381
1382 $original_id = $source->getRefId();
1383
1384 foreach ($a_object_data['references'] as $ref_data) {
1385 $new_ref_id = $original_id;
1386 if ($tree->getParentId($original_id) !== (int) $ref_data['parent_id']) {
1387 // New reference requested => create it
1388 $new_ref_id = $source->createReference();
1389 $source->putInTree($ref_data['parent_id']);
1390 $source->setPermissions($ref_data['parent_id']);
1391 }
1392 if (isset($ref_data['time_target']) /* and ($crs_ref_id = $tree->checkForParentType($new_ref_id,'crs')) */) {
1393 if (!isset($ref_data['time_target']['starting_time'])) {
1394 $ref_data['time_target']['starting_time'] = time();
1395 }
1396 if (!isset($ref_data['time_target']['ending_time'])) {
1397 $ref_data['time_target']['ending_time'] = time();
1398 }
1399
1400 $items = new ilObjectActivation();
1401 $items->toggleChangeable($ref_data['time_target']['changeable']);
1402 $items->setTimingStart($ref_data['time_target']['starting_time']);
1403 $items->setTimingEnd($ref_data['time_target']['ending_time']);
1404 $items->toggleVisible($ref_data['time_target']['timing_visibility']);
1405 $items->setSuggestionStart($ref_data['time_target']['suggestion_start']);
1406 $items->setSuggestionEnd($ref_data['time_target']['suggestion_end']);
1407
1408 switch ($ref_data['time_target']['timing_type']) {
1410 $ilLog->write(__METHOD__ . ilObjectActivation::TIMINGS_DEACTIVATED . ' ' . $ref_data['time_target']['timing_type']);
1411 $items->setTimingType(ilObjectActivation::TIMINGS_DEACTIVATED);
1412 break;
1413
1415 $ilLog->write(__METHOD__ . ilObjectActivation::TIMINGS_ACTIVATION . ' ' . $ref_data['time_target']['timing_type']);
1416 $items->setTimingType(ilObjectActivation::TIMINGS_ACTIVATION);
1417 break;
1418
1420 $ilLog->write(__METHOD__ . ilObjectActivation::TIMINGS_PRESETTING . ' ' . $ref_data['time_target']['timing_type']);
1421 $items->setTimingType(ilObjectActivation::TIMINGS_PRESETTING);
1422 break;
1423 }
1424 $items->update($new_ref_id);
1425 }
1426 }
1427 }
1428}
$location
Definition: buildRTE.php:22
static _adjustMovedObjectConditions(int $a_ref_id)
In the moment it is not allowed to create preconditions on objects that are located outside of a cour...
Class ilContainer.
static _allocateCopyId()
Allocate a copy for further entries.
static _getInstance(int $a_copy_id)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Parses result XML from lucene search highlight.
static getInstance(ilLuceneQueryParser $qp)
Get singleton instance.
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...
static _lookupId(string|array $a_user_str)
Class ilObjectActivation.
static getItem(int $ref_id)
static getInstanceByRefId(int $ref_id, bool $stop_on_error=true)
get an instance of an Ilias object by reference id
static getTypeByRefId(int $ref_id, bool $stop_on_error=true)
get object type 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...
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 ilObject Basic functions for all objects.
static _lookupObjectId(int $ref_id)
static _lookupType(int $id, bool $reference=false)
setPermissions(int $parent_ref_id)
createReference()
creates reference for object
putInTree(int $parent_ref_id)
maybe this method should be in tree object!?
static _hasUntrashedReference(int $obj_id)
checks whether an object has at least one reference that is not in trash
static _getAllReferences(int $id)
get all reference ids for object ID
static _isInTrash(int $ref_id)
static _lookupObjIdByImportId(string $import_id)
Get (latest) object id for an import id.
static _exists(int $id, bool $reference=false, ?string $type=null)
checks if an object exists in object_data
static _lookupObjId(int $ref_id)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
raiseError(string $a_message, $a_code)
addReferences(ilObject $source, array $a_object_data)
getObjectsByTitle(string $sid, string $a_title, ?int $user_id=null)
addReference(string $sid, int $a_source_id, int $a_target_id)
validateReferences(string $a_action, array $a_object_data, int $a_target_id=0)
copyObject(string $sid, string $copy_settings_xml)
removeFromSystemByImportId(string $sid, string $import_id)
getRefIdsByImportId(string $sid, string $import_id)
deleteObject(string $sid, int $reference_id)
moveObject(string $sid, int $ref_id, int $target_id)
canAddType(string $type, string $target_type, int $target_id)
getObjIdByImportId(string $sid, string $import_id)
searchObjects(string $sid, ?array $types, string $key, string $combination, ?int $user_id=null)
getTreeChilds(string $sid, int $ref_id, ?array $types=null, ?int $user_id=null)
getXMLTree(string $sid, int $ref_id, ?array $types=null, ?int $user_id=null)
getObjIdsByRefIds(string $sid, array $ref_ids)
getObjectByReference(string $sid, int $a_ref_id, ?int $user_id=null)
Row Class for XMLResultSet.
XML Writer for XMLResultSet.
const SYSTEM_FOLDER_ID
Definition: constants.php:35
const ROOT_FOLDER_ID
Definition: constants.php:32
$ref_id
Definition: ltiauth.php:66
$res
Definition: ltiservices.php:69
global $lng
Definition: privfeed.php:31
global $DIC
Definition: shib_login.php:26
$counter