1<?php
2  /*
3   +-----------------------------------------------------------------------------+
4   | ILIAS open source                                                           |
5   +-----------------------------------------------------------------------------+
6   | Copyright (c) 1998-2001 ILIAS open source, University of Cologne            |
7   |                                                                             |
8   | This program is free software; you can redistribute it and/or               |
9   | modify it under the terms of the GNU General Public License                 |
10   | as published by the Free Software Foundation; either version 2              |
11   | of the License, or (at your option) any later version.                      |
12   |                                                                             |
13   | This program is distributed in the hope that it will be useful,             |
14   | but WITHOUT ANY WARRANTY; without even the implied warranty of              |
15   | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |
16   | GNU General Public License for more details.                                |
17   |                                                                             |
18   | You should have received a copy of the GNU General Public License           |
19   | along with this program; if not, write to the Free Software                 |
20   | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. |
21   +-----------------------------------------------------------------------------+
22  */
23
24
25  /**
26   * Soap object administration methods
27   *
28   * @author Stefan Meyer <meyer@leifos.com>
29   * @author Stefan Hecken <stefan.hecken@concepts-and-training.de>
30   * @version $Id$
31   *
32   * @package ilias
33   */
34include_once './webservice/soap/classes/class.ilSoapAdministration.php';
35
36class ilSoapObjectAdministration extends ilSoapAdministration
37{
38    /**
39     * Add desktop items for user
40     * @param string $sid
41     * @param int $user_id
42     * @param int[] $reference_ids
43     * @return bool
44     *
45     */
46    public function addDesktopItems($sid, $user_id, $reference_ids)
47    {
48        return; // abandonded
49        $this->initAuth($sid);
50        $this->initIlias();
51
52        if (!$this->__checkSession($sid)) {
53            return $this->__raiseError($this->__getMessage(), $this->__getMessageCode());
54        }
55
56        global $DIC;
57
58        $access = $DIC->rbac()->system();
59        $logger = $DIC->logger()->wsrv();
60
61        if (!$access->checkAccess('edit_userassignment', ROLE_FOLDER_ID)) {
62            $logger->warning('Missing permission "edit_userassignment".');
63            return $this->__raiseError(
64                'Missing permission "edit_userassignment".',
65                'Client'
66            );
67        }
68
69        $user = ilObjectFactory::getInstanceByObjId($user_id, false);
70        if (!$user instanceof ilObjUser) {
71            $logger->warning('Invalid user id given. Cannot instantiate user for id: ' . $user_id);
72            return $this->__raiseError(
73                'Invalid user id given. Cannot instantiate user for id: ' . $user_id,
74                'Client'
75            );
76        }
77        $num_added = 0;
78        foreach ($reference_ids as $ref_id) {
79            // short "validation" of reference id
80            $ref_obj = ilObjectFactory::getInstanceByRefId($ref_id, false);
81            if (!$ref_obj instanceof ilObject) {
82                $logger->warning('Invalid reference id passed to SOAP::addDesktopItems: ' . $ref_id);
83                continue;
84            }
85
86            $num_added++;
87            /*			ilObjUser::_addDesktopItem(
88                            $user->getId(),
89                            $ref_id,
90                            ilObject::_lookupType($ref_id,true)
91                        );*/
92        }
93        return $num_added;
94    }
95
96    /**
97     * Remove desktop items for user
98     * @param string $sid
99     * @param int $user_id
100     * @param int[] $reference_ids
101     * @return bool
102     *
103     */
104    public function removeDesktopItems($sid, $user_id, $reference_ids)
105    {
106        return; // abandonded with 6.0
107        $this->initAuth($sid);
108        $this->initIlias();
109
110        if (!$this->__checkSession($sid)) {
111            return $this->__raiseError($this->__getMessage(), $this->__getMessageCode());
112        }
113
114        global $DIC;
115
116        $access = $DIC->rbac()->system();
117        $logger = $DIC->logger()->wsrv();
118
119        if (!$access->checkAccess('edit_userassignment', ROLE_FOLDER_ID)) {
120            $logger->warning('Missing permission "edit_userassignment".');
121            return $this->__raiseError(
122                'Missing permission "edit_userassignment".',
123                'Client'
124            );
125        }
126
127        $user = ilObjectFactory::getInstanceByObjId($user_id, false);
128        if (!$user instanceof ilObjUser) {
129            $logger->warning('Invalid user id given. Cannot instantiate user for id: ' . $user_id);
130            return $this->__raiseError(
131                'Invalid user id given. Cannot instantiate user for id: ' . $user_id,
132                'Client'
133            );
134        }
135        $num_removed = 0;
136        foreach ($reference_ids as $ref_id) {
137            // short "validation" of reference id
138            $ref_obj = ilObjectFactory::getInstanceByRefId($ref_id, false);
139            if (!$ref_obj instanceof ilObject) {
140                $logger->warning('Invalid reference id passed to SOAP::removeDesktopItems: ' . $ref_id);
141                continue;
142            }
143
144            $num_added++;
145            /*
146            ilObjUser::_dropDesktopItem(
147                $user->getId(),
148                $ref_id,
149                ilObject::_lookupType($ref_id,true)
150            );*/
151        }
152        return $num_removed;
153    }
154
155
156    public function getObjIdByImportId($sid, $import_id)
157    {
158        $this->initAuth($sid);
159        $this->initIlias();
160
161        if (!$this->__checkSession($sid)) {
162            return $this->__raiseError($this->__getMessage(), $this->__getMessageCode());
163        }
164        if (!$import_id) {
165            return $this->__raiseError(
166                'No import id given.',
167                'Client'
168            );
169        }
170
171        global $DIC;
172
173        $ilLog = $DIC['ilLog'];
174
175        $obj_id = ilObject::_lookupObjIdByImportId($import_id);
176        $ilLog->write("SOAP getObjIdByImportId(): import_id = " . $import_id . ' obj_id = ' . $obj_id);
177
178        return $obj_id ? $obj_id : "0";
179    }
180
181    public function getRefIdsByImportId($sid, $import_id)
182    {
183        $this->initAuth($sid);
184        $this->initIlias();
185
186        if (!$this->__checkSession($sid)) {
187            return $this->__raiseError($this->__getMessage(), $this->__getMessageCode());
188        }
189        if (!$import_id) {
190            return $this->__raiseError(
191                'No import id given.',
192                'Client'
193            );
194        }
195
196        global $DIC;
197
198        $tree = $DIC['tree'];
199
200        $obj_id = ilObject::_lookupObjIdByImportId($import_id);
201
202
203        $ref_ids = ilObject::_getAllReferences($obj_id);
204
205        foreach ($ref_ids as $ref_id) {
206            // only get non deleted reference ids
207            if ($tree->isInTree($ref_id)) {
208                $new_refs[] = $ref_id;
209            }
210        }
211        return $new_refs ? $new_refs : array();
212    }
213
214    public function getRefIdsByObjId($sid, $obj_id)
215    {
216        $this->initAuth($sid);
217        $this->initIlias();
218
219        if (!$this->__checkSession($sid)) {
220            return $this->__raiseError($this->__getMessage(), $this->__getMessageCode());
221        }
222        if (!$obj_id) {
223            return $this->__raiseError(
224                'No object id given.',
225                'Client'
226            );
227        }
228
229        $ref_ids = ilObject::_getAllReferences($obj_id);
230        foreach ($ref_ids as $ref_id) {
231            $new_refs[] = $ref_id;
232        }
233        return $new_refs ? $new_refs : array();
234    }
235
236    /**
237    *	Returns a array of object ids which match the references id, given by a comma seperated string.
238    *
239    *	@param	string $sid	Session ID
240    *	@param	array of int $ref ids as comma separated list
241    *	@return	array of ref ids, same order as object ids there for there might by duplicates
242    *
243    */
244    public function getObjIdsByRefIds($sid, $ref_ids)
245    {
246        $this->initAuth($sid);
247        $this->initIlias();
248
249        if (!$this->__checkSession($sid)) {
250            return $this->__raiseError($this->__getMessage(), $this->__getMessageCode());
251        }
252
253
254        if (!count($ref_ids) || !is_array($ref_ids)) {
255            return $this->__raiseError('No reference id(s) given.', 'Client');
256        }
257
258        $obj_ids = array();
259        if (count($ref_ids)) {
260            foreach ($ref_ids as $ref_id) {
261                $ref_id = trim($ref_id);
262                if (!is_numeric($ref_id)) {
263                    return $this->__raiseError('Reference ID has to be numeric. Value: ' . $ref_id, 'Client');
264                }
265
266                $obj_id = ilObject::_lookupObjectId($ref_id);
267                if (!$obj_id) {
268                    return $this->__raiseError('No object found for reference ID. Value: ' . $ref_id, 'Client');
269                }
270                if (!ilObject::_hasUntrashedReference($obj_id)) {
271                    return $this->__raiseError('No untrashed reference found for reference ID. Value: ' . $ref_id, 'Client');
272                }
273                $obj_ids[] = $obj_id;
274            }
275        }
276        return $obj_ids;
277    }
278
279
280
281    public function getObjectByReference($sid, $a_ref_id, $user_id)
282    {
283        $this->initAuth($sid);
284        $this->initIlias();
285
286        if (!$this->__checkSession($sid)) {
287            return $this->__raiseError($this->__getMessage(), $this->__getMessageCode());
288        }
289        if (!is_numeric($a_ref_id)) {
290            return $this->__raiseError(
291                'No valid reference id given. Please choose an existing reference id of an ILIAS object',
292                'Client'
293            );
294        }
295
296        if (!$tmp_obj = ilObjectFactory::getInstanceByRefId($a_ref_id, false)) {
297            return $this->__raiseError('Cannot create object instance!', 'Server');
298        }
299
300
301        if (ilObject::_isInTrash($a_ref_id)) {
302            return $this->__raiseError("Object with ID $a_ref_id has been deleted.", 'Client');
303        }
304
305        include_once './webservice/soap/classes/class.ilObjectXMLWriter.php';
306
307        $xml_writer = new ilObjectXMLWriter();
308        $xml_writer->enablePermissionCheck(true);
309        if ($user_id) {
310            $xml_writer->setUserId($user_id);
311            $xml_writer->enableOperations(true);
312        }
313        $xml_writer->setObjects(array($tmp_obj));
314        if ($xml_writer->start()) {
315            return $xml_writer->getXML();
316        }
317
318        return $this->__raiseError('Cannot create object xml !', 'Server');
319    }
320
321    public function getObjectsByTitle($sid, $a_title, $user_id)
322    {
323        $this->initAuth($sid);
324        $this->initIlias();
325
326        if (!$this->__checkSession($sid)) {
327            return $this->__raiseError($this->__getMessage(), $this->__getMessageCode());
328        }
329        if (!strlen($a_title)) {
330            return $this->__raiseError(
331                'No valid query string given.',
332                'Client'
333            );
334        }
335
336        include_once './Services/Search/classes/class.ilQueryParser.php';
337
338        $query_parser = new ilQueryParser($a_title);
339        $query_parser->setMinWordLength(0, true);
340        $query_parser->setCombination(QP_COMBINATION_AND);
341        $query_parser->parse();
342        if (!$query_parser->validate()) {
343            return $this->__raiseError(
344                $query_parser->getMessage(),
345                'Client'
346            );
347        }
348
349        include_once './Services/Search/classes/class.ilObjectSearchFactory.php';
350
351        include_once 'Services/Search/classes/Like/class.ilLikeObjectSearch.php';
352        $object_search = new ilLikeObjectSearch($query_parser);
353
354        #$object_search =& ilObjectSearchFactory::_getObjectSearchInstance($query_parser);
355        $object_search->setFields(array('title'));
356        $object_search->appendToFilter('role');
357        $object_search->appendToFilter('rolt');
358        $res =&$object_search->performSearch();
359        if ($user_id) {
360            $res->setUserId($user_id);
361        }
362
363        $res->filter(ROOT_FOLDER_ID, true);
364
365        $objs = array();
366        foreach ($res->getUniqueResults() as $entry) {
367            if ($entry['type'] == 'role' or $entry['type'] == 'rolt') {
368                if ($tmp = ilObjectFactory::getInstanceByObjId($entry['obj_id'], false)) {
369                    $objs[] = $tmp;
370                }
371                continue;
372            }
373            if ($tmp = ilObjectFactory::getInstanceByRefId($entry['ref_id'], false)) {
374                $objs[] = $tmp;
375            }
376        }
377        if (!count($objs)) {
378            return '';
379        }
380
381        include_once './webservice/soap/classes/class.ilObjectXMLWriter.php';
382
383        $xml_writer = new ilObjectXMLWriter();
384        $xml_writer->enablePermissionCheck(true);
385        if ($user_id) {
386            $xml_writer->setUserId($user_id);
387            $xml_writer->enableOperations(true);
388        }
389        $xml_writer->setObjects($objs);
390        if ($xml_writer->start()) {
391            return $xml_writer->getXML();
392        }
393
394        return $this->__raiseError('Cannot create object xml !', 'Server');
395    }
396
397    public function searchObjects($sid, $types, $key, $combination, $user_id)
398    {
399        $this->initAuth($sid);
400        $this->initIlias();
401
402        if (!$this->__checkSession($sid)) {
403            return $this->__raiseError($this->__getMessage(), $this->__getMessageCode());
404        }
405        if (!is_array($types)) {
406            return $this->__raiseError(
407                'Types must be an array of object types.',
408                'Client'
409            );
410        }
411        if ($combination != 'and' and $combination != 'or') {
412            return $this->__raiseError(
413                'No valid combination given. Must be "and" or "or".',
414                'Client'
415            );
416        }
417
418        // begin-patch fm
419        include_once './Services/Search/classes/class.ilSearchSettings.php';
420        if (ilSearchSettings::getInstance()->enabledLucene()) {
421            ilSearchSettings::getInstance()->setMaxHits(25);
422
423            $typeFilterQuery = '';
424            if (is_array($types)) {
425                foreach ($types as $objectType) {
426                    if (0 === strlen($typeFilterQuery)) {
427                        $typeFilterQuery .= '+( ';
428                    } else {
429                        $typeFilterQuery .= 'OR';
430                    }
431                    $typeFilterQuery .= (' type:' . (string) $objectType . ' ');
432                }
433                $typeFilterQuery .= ') ';
434            }
435
436            include_once './Services/Search/classes/Lucene/class.ilLuceneQueryParser.php';
437            $query_parser = new ilLuceneQueryParser($typeFilterQuery . $key);
438            $query_parser->parse();
439
440            include_once './Services/Search/classes/Lucene/class.ilLuceneSearcher.php';
441            $searcher = ilLuceneSearcher::getInstance($query_parser);
442            $searcher->search();
443
444            include_once './Services/Search/classes/Lucene/class.ilLuceneSearchResultFilter.php';
445            include_once './Services/Search/classes/Lucene/class.ilLucenePathFilter.php';
446            $filter = ilLuceneSearchResultFilter::getInstance($user_id);
447            $filter->setCandidates($searcher->getResult());
448            $filter->filter();
449
450            $result_ids = $filter->getResults();
451            $objs = array();
452            $objs[ROOT_FOLDER_ID] = ilObjectFactory::getInstanceByRefId(ROOT_FOLDER_ID, false);
453            foreach ((array) $result_ids as $ref_id => $obj_id) {
454                $obj = ilObjectFactory::getInstanceByRefId($ref_id, false);
455                if ($obj instanceof ilObject) {
456                    $objs[] = $obj;
457                }
458            }
459            include_once './Services/Search/classes/Lucene/class.ilLuceneHighlighterResultParser.php';
460            $highlighter = new ilLuceneHighlighterResultParser();
461            if ($filter->getResultObjIds()) {
462                $highlighter = $searcher->highlight($filter->getResultObjIds());
463            }
464        } else {
465            include_once './Services/Search/classes/class.ilQueryParser.php';
466
467            $query_parser = new ilQueryParser($key);
468            #$query_parser->setMinWordLength(3);
469            $query_parser->setCombination($combination == 'and' ? QP_COMBINATION_AND : QP_COMBINATION_OR);
470            $query_parser->parse();
471            if (!$query_parser->validate()) {
472                return $this->__raiseError(
473                    $query_parser->getMessage(),
474                    'Client'
475                );
476            }
477
478            #include_once './Services/Search/classes/class.ilObjectSearchFactory.php';
479            #$object_search =& ilObjectSearchFactory::_getObjectSearchInstance($query_parser);
480
481            include_once './Services/Search/classes/Like/class.ilLikeObjectSearch.php';
482            $object_search =  new ilLikeObjectSearch($query_parser);
483
484            $object_search->setFilter($types);
485
486            $res =&$object_search->performSearch();
487            if ($user_id) {
488                $res->setUserId($user_id);
489            }
490            // begin-patch fm
491            $res->setMaxHits(100);
492            // begin-patch fm
493            $res->filter(ROOT_FOLDER_ID, $combination == 'and' ? true : false);
494
495            $counter = 0;
496            $objs = array();
497            foreach ($res->getUniqueResults() as $entry) {
498                $obj = ilObjectFactory::getInstanceByRefId($entry['ref_id'], false);
499                if ($obj instanceof ilObject) {
500                    $objs[] = $obj;
501                }
502            }
503        }
504
505        if (!count($objs)) {
506            return '';
507        }
508
509        include_once './webservice/soap/classes/class.ilObjectXMLWriter.php';
510
511        $xml_writer = new ilObjectXMLWriter();
512
513        // begin-patch fm
514        if (ilSearchSettings::getInstance()->enabledLucene()) {
515            $xml_writer->enableReferences(false);
516            $xml_writer->setMode(ilObjectXmlWriter::MODE_SEARCH_RESULT);
517            $xml_writer->setHighlighter($highlighter);
518        }
519
520        $xml_writer->enablePermissionCheck(true);
521
522        if ($user_id) {
523            $xml_writer->setUserId($user_id);
524            $xml_writer->enableOperations(true);
525        }
526
527        $xml_writer->setObjects($objs);
528        if ($xml_writer->start()) {
529            #$GLOBALS['DIC']['ilLog']->write(__METHOD__.': '.$xml_writer->xmlDumpMem(true));
530            return $xml_writer->getXML();
531        }
532
533        return $this->__raiseError('Cannot create object xml !', 'Server');
534    }
535
536    public function getTreeChilds($sid, $ref_id, $types, $user_id)
537    {
538        $this->initAuth($sid);
539        $this->initIlias();
540
541        if (!$this->__checkSession($sid)) {
542            return $this->__raiseError($this->__getMessage(), $this->__getMessageCode());
543        }
544
545        $all = false;
546
547        global $DIC;
548
549        $tree = $DIC['tree'];
550
551        if (!$target_obj =&ilObjectFactory::getInstanceByRefId($ref_id, false)) {
552            return $this->__raiseError(
553                'No valid reference id given.',
554                'Client'
555            );
556        }
557        if (intval($ref_id) == SYSTEM_FOLDER_ID) {
558            return $this->__raiseError(
559                'No valid reference id given.',
560                'Client'
561            );
562        }
563
564        if (!$types) {
565            $all = true;
566        }
567
568        $objs = array();
569
570        // begin-patch filemanager
571        include_once './Services/WebServices/FileManager/classes/class.ilFMSettings.php';
572        if (in_array('parent', (array) $types)) {
573            $objs[] = $target_obj;
574        }
575        // end-patch filemanager
576
577        foreach ($tree->getChilds($ref_id, 'title') as $child) {
578            if ($all or in_array($child['type'], $types)) {
579                if ($tmp = ilObjectFactory::getInstanceByRefId($child['ref_id'], false)) {
580                    $objs[] = $tmp;
581                }
582            }
583        }
584
585        include_once './webservice/soap/classes/class.ilObjectXMLWriter.php';
586
587        $xml_writer = new ilObjectXMLWriter();
588        // begin-patch filemanager
589        if (ilFMSettings::getInstance()->isEnabled()) {
590            $xml_writer->enableReferences(false);
591        }
592        // end-patch filemanager
593        $xml_writer->enablePermissionCheck(true);
594        $xml_writer->setObjects($objs);
595        $xml_writer->enableOperations(true);
596        if ($user_id) {
597            $xml_writer->setUserId($user_id);
598        }
599
600        if ($xml_writer->start()) {
601            #$GLOBALS['DIC']['ilLog']->write(__METHOD__.': '.$xml_writer->getXML());
602            return $xml_writer->getXML();
603        }
604
605        return $this->__raiseError('Cannot create object xml !', 'Server');
606    }
607
608    public function getXMLTree($sid, $ref_id, $types, $user_id)
609    {
610        $this->initAuth($sid);
611        $this->initIlias();
612
613        if (!$this->__checkSession($sid)) {
614            return $this->__raiseError($this->__getMessage(), $this->__getMessageCode());
615        }
616
617        global $DIC;
618
619        $tree = $DIC['tree'];
620
621        $nodedata = $tree->getNodeData($ref_id);
622        $nodearray = $tree->getSubTree($nodedata);
623
624
625        $filter = (array) $types;
626
627        global $DIC;
628
629        $objDefinition = $DIC['objDefinition'];
630        foreach ($nodearray as $node) {
631            if (!$objDefinition->isAdministrationObject($node['type']) && !$objDefinition->isSystemObject($node['type'])) {
632                if (!in_array($node['type'], $filter)) {
633                    if ($tmp = ilObjectFactory::getInstanceByRefId($node['ref_id'], false)) {
634                        $nodes[] = $tmp;
635                    }
636                }
637            }
638        }
639
640
641        include_once './webservice/soap/classes/class.ilObjectXMLWriter.php';
642
643        $xml_writer = new ilObjectXMLWriter();
644        $xml_writer->enablePermissionCheck(true);
645        $xml_writer->setObjects($nodes);
646        $xml_writer->enableOperations(false);
647
648        if ($user_id) {
649            $xml_writer->setUserId($user_id);
650        }
651
652        if ($xml_writer->start()) {
653            return $xml_writer->getXML();
654        }
655
656        return $this->__raiseError('Cannot create object xml !', 'Server');
657    }
658
659    public function addObject($sid, $a_target_id, $a_xml)
660    {
661        $this->initAuth($sid);
662        $this->initIlias();
663
664        if (!$this->__checkSession($sid)) {
665            return $this->__raiseError($this->__getMessage(), $this->__getMessageCode());
666        }
667        if (!strlen($a_xml)) {
668            return $this->__raiseError(
669                'No valid xml string given.',
670                'Client'
671            );
672        }
673
674        global $DIC;
675
676        $rbacsystem = $DIC['rbacsystem'];
677        $objDefinition = $DIC['objDefinition'];
678        $ilUser = $DIC['ilUser'];
679        $lng = $DIC['lng'];
680        $ilObjDataCache = $DIC['ilObjDataCache'];
681
682        if (!$target_obj =&ilObjectFactory::getInstanceByRefId($a_target_id, false)) {
683            return $this->__raiseError(
684                'No valid target given.',
685                'Client'
686            );
687        }
688
689        if (ilObject::_isInTrash($a_target_id)) {
690            return $this->__raiseError("Parent with ID $a_target_id has been deleted.", 'Client');
691        }
692
693        $allowed_types = array('root','cat','grp','crs','fold');
694        if (!in_array($target_obj->getType(), $allowed_types)) {
695            return $this->__raiseError(
696                'No valid target type. Target must be reference id of "course, group, category or folder"',
697                'Client'
698            );
699        }
700
701        $allowed_subtypes = $target_obj->getPossibleSubObjects();
702
703        foreach ($allowed_subtypes as $row) {
704            if ($row['name'] != 'rolf') {
705                $allowed[] = $row['name'];
706            }
707        }
708
709        include_once './webservice/soap/classes/class.ilObjectXMLParser.php';
710
711        $xml_parser = new ilObjectXMLParser($a_xml, true);
712        try {
713            $xml_parser->startParsing();
714        } catch (ilSaxParserException $se) {
715            return $this->__raiseError($se->getMessage(), 'Client');
716        } catch (ilObjectXMLException $e) {
717            return $this->__raiseError($e->getMessage(), 'Client');
718        }
719
720        foreach ($xml_parser->getObjectData() as $object_data) {
721            $res = $this->validateReferences('create', $object_data, $a_target_id);
722            if ($this->isFault($res)) {
723                return $res;
724            }
725
726            // Check possible subtype
727            if (!in_array($object_data['type'], $allowed)) {
728                return $this->__raiseError(
729                    'Objects of type: ' . $object_data['type'] . ' are not allowed to be subobjects of type ' .
730                                           $target_obj->getType() . '!',
731                    'Client'
732                );
733            }
734            if (!$rbacsystem->checkAccess('create', $a_target_id, $object_data['type'])) {
735                return $this->__raiseError(
736                    'No permission to create objects of type ' . $object_data['type'] . '!',
737                    'Client'
738                );
739            }
740            // begin-patch fm
741            /*
742            if($object_data['type'] == 'crs')
743            {
744                return $this->__raiseError('Cannot create course objects. Use method addCourse() ',
745                                           'Client');
746            }
747            */
748            // end-patch fm
749
750            // It's not possible to add objects with non unique import ids
751            if (strlen($object_data['import_id']) and ilObject::_lookupObjIdByImportId($object_data['import_id'])) {
752                return $this->__raiseError(
753                    'An object with import id ' . $object_data['import_id'] . ' already exists!',
754                    'Server'
755                );
756            }
757
758            // call gui object method
759            $class_name = $objDefinition->getClassName($object_data['type']);
760            $location = $objDefinition->getLocation($object_data['type']);
761
762            $class_constr = "ilObj" . $class_name;
763            require_once($location . "/class.ilObj" . $class_name . ".php");
764
765            $newObj = new $class_constr();
766
767            if (isset($object_data['owner']) && strlen($object_data['owner'])) {
768                if ((int) $object_data['owner']) {
769                    if (ilObject::_exists((int) $object_data['owner']) &&
770                       $ilObjDataCache->lookupType((int) $object_data['owner']) == 'usr') {
771                        $newObj->setOwner((int) $object_data['owner']);
772                    }
773                } else {
774                    $usr_id = ilObjUser::_lookupId(trim($object_data['owner']));
775                    if ((int) $usr_id) {
776                        $newObj->setOwner((int) $usr_id);
777                    }
778                }
779            }
780
781            $newObj->setType($object_data['type']);
782            if (strlen($object_data['import_id'])) {
783                $newObj->setImportId($object_data['import_id']);
784            }
785
786            if ($objDefinition->supportsOfflineHandling($newObj->getType())) {
787                $newObj->setOfflineStatus((bool) $object_data['offline']);
788            }
789            $newObj->setTitle($object_data['title']);
790            $newObj->setDescription($object_data['description']);
791            $newObj->create(); // true for upload
792            $newObj->createReference();
793            $newObj->putInTree($a_target_id);
794            $newObj->setPermissions($a_target_id);
795
796            switch ($object_data['type']) {
797                case 'grp':
798                    // Add member
799                    $newObj->addMember(
800                        $object_data['owner'] ? $object_data['owner'] : $ilUser->getId(),
801                        $newObj->getDefaultAdminRole()
802                    );
803                    break;
804
805                // begin-patch fm
806                case 'crs':
807                    $newObj->getMemberObject()->add($ilUser->getId(), IL_CRS_ADMIN);
808                    break;
809                // end-patch fm
810                case 'lm':
811                    $newObj->createLMTree();
812                    break;
813                case 'cat':
814                    /** @var $newObj ilObjCategory */
815                    $newObj->addTranslation($object_data["title"], $object_data["description"], $lng->getLangKey(), true);
816                    break;
817            }
818
819            $this->addReferences($newObj, $object_data);
820        }
821        $ref_id = $newObj->getRefId();
822        return  $ref_id  ? $ref_id : "0";
823    }
824
825    public function addReference($sid, $a_source_id, $a_target_id)
826    {
827        $this->initAuth($sid);
828        $this->initIlias();
829
830        if (!$this->__checkSession($sid)) {
831            return $this->__raiseError($this->__getMessage(), $this->__getMessageCode());
832        }
833        if (!is_numeric($a_source_id)) {
834            return $this->__raiseError(
835                'No source id given.',
836                'Client'
837            );
838        }
839        if (!is_numeric($a_target_id)) {
840            return $this->__raiseError(
841                'No target id given.',
842                'Client'
843            );
844        }
845
846        global $DIC;
847
848        $objDefinition = $DIC['objDefinition'];
849        $rbacsystem = $DIC['rbacsystem'];
850        $tree = $DIC['tree'];
851
852        if (!$source_obj =&ilObjectFactory::getInstanceByRefId($a_source_id, false)) {
853            return $this->__raiseError(
854                'No valid source id given.',
855                'Client'
856            );
857        }
858        if (!$target_obj =&ilObjectFactory::getInstanceByRefId($a_target_id, false)) {
859            return $this->__raiseError(
860                'No valid target id given.',
861                'Client'
862            );
863        }
864
865        if (!$objDefinition->allowLink($source_obj->getType()) and
866            $source_obj->getType() != 'cat' and
867            $source_obj->getType() != 'crs') {
868            return $this->__raiseError(
869                'Linking of object type: ' . $source_obj->getType() . ' is not allowed',
870                'Client'
871            );
872        }
873
874        $allowed_subtypes = $target_obj->getPossibleSubObjects();
875        foreach ($allowed_subtypes as $row) {
876            if ($row['name'] != 'rolf') {
877                $allowed[] = $row['name'];
878            }
879        }
880        if (!in_array($source_obj->getType(), $allowed)) {
881            return $this->__raiseError(
882                'Objects of type: ' . $source_obj->getType() . ' are not allowed to be subobjects of type ' .
883                                       $target_obj->getType() . '!',
884                'Client'
885            );
886        }
887
888        // Permission checks
889        if (!$rbacsystem->checkAccess('create', $target_obj->getRefId(), $source_obj->getType())) {
890            return $this->__raiseError(
891                'No permission to create objects of type ' . $source_obj->getType() . '!',
892                'Client'
893            );
894        }
895        if (!$rbacsystem->checkAccess('delete', $source_obj->getRefId())) {
896            return $this->__raiseError(
897                'No permission to link object with id: ' . $source_obj->getRefId() . '!',
898                'Client'
899            );
900        }
901
902
903        if ($source_obj->getType() != 'cat' and $source_obj->getType() != 'crs') {
904            // check if object already linked to target
905            $possibleChilds = $tree->getChildsByType($target_obj->getRefId(), $source_obj->getType());
906            foreach ($possibleChilds as $child) {
907                if ($child["obj_id"] == $source_obj->getId()) {
908                    return $this->__raiseError("Object already linked to target.", "Client");
909                }
910            }
911
912            // Finally link it to target position
913
914            $new_ref_id = $source_obj->createReference();
915            $source_obj->putInTree($target_obj->getRefId());
916            $source_obj->setPermissions($target_obj->getRefId());
917
918            return $new_ref_id ? $new_ref_id : "0";
919        } else {
920            switch ($source_obj->getType()) {
921                case 'cat':
922                    include_once('./Modules/CategoryReference/classes/class.ilObjCategoryReference.php');
923                    $new_ref = new ilObjCategoryReference();
924                    break;
925
926                case 'crs':
927                    include_once('./Modules/CourseReference/classes/class.ilObjCourseReference.php');
928                    $new_ref = new ilObjCourseReference();
929                    break;
930                case 'grp':
931                    include_once('./Modules/GroupReference/classes/class.ilObjGroupReference.php');
932                    $new_ref = new ilObjGroupReference();
933                    break;
934            }
935            $new_ref->create();
936            $new_ref_id = $new_ref->createReference();
937
938            $new_ref->putInTree($target_obj->getRefId());
939            $new_ref->setPermissions($target_obj->getRefId());
940
941            $new_ref->setTargetId($source_obj->getId());
942            $new_ref->update();
943
944            return $new_ref_id ? $new_ref_id : 0;
945        }
946    }
947
948    public function deleteObject($sid, $reference_id)
949    {
950        $this->initAuth($sid);
951        $this->initIlias();
952
953        if (!$this->__checkSession($sid)) {
954            return $this->__raiseError($this->__getMessage(), $this->__getMessageCode());
955        }
956        if (!is_numeric($reference_id)) {
957            return $this->__raiseError(
958                'No reference id given.',
959                'Client'
960            );
961        }
962        global $DIC;
963
964        $tree = $DIC->repositoryTree();
965        $rbacsystem = $DIC['rbacsystem'];
966        $rbacadmin = $DIC['rbacadmin'];
967        $user = $DIC->user();
968
969        if (!$del_obj =&ilObjectFactory::getInstanceByRefId($reference_id, false)) {
970            return $this->__raiseError(
971                'No valid reference id given.',
972                'Client'
973            );
974        }
975        if (!$rbacsystem->checkAccess('delete', $del_obj->getRefId())) {
976            return $this->__raiseError(
977                'No permission to delete object with id: ' . $del_obj->getRefId() . '!',
978                'Client'
979            );
980        }
981
982        // Delete tree
983        if ($tree->isDeleted($reference_id)) {
984            return $this->__raiseError('Node already deleted', 'Server');
985        }
986
987        if ($del_obj->getType() == 'rolf') {
988            return $this->__raiseError('Delete is not available for role folders.', 'Client');
989        }
990
991        $subnodes = $tree->getSubtree($tree->getNodeData($reference_id));
992        foreach ($subnodes as $subnode) {
993            $rbacadmin->revokePermission($subnode["child"]);
994        }
995        if (!$tree->moveToTrash($reference_id, true, $user->getId())) {
996            return $this->__raiseError('Node already deleted', 'Client');
997        }
998
999        return true;
1000    }
1001
1002    public function removeFromSystemByImportId($sid, $import_id)
1003    {
1004        $this->initAuth($sid);
1005        $this->initIlias();
1006
1007        if (!$this->__checkSession($sid)) {
1008            return $this->__raiseError($this->__getMessage(), $this->__getMessageCode());
1009        }
1010        if (!strlen($import_id)) {
1011            return $this->__raiseError(
1012                'No import id given. Aborting!',
1013                'Client'
1014            );
1015        }
1016        global $DIC;
1017
1018        $rbacsystem = $DIC['rbacsystem'];
1019        $tree = $DIC['tree'];
1020        $ilLog = $DIC['ilLog'];
1021
1022        // get obj_id
1023        if (!$obj_id = ilObject::_lookupObjIdByImportId($import_id)) {
1024            return $this->__raiseError(
1025                'No object found with import id: ' . $import_id,
1026                'Client'
1027            );
1028        }
1029
1030        // Check access
1031        $permission_ok = false;
1032        foreach ($ref_ids = ilObject::_getAllReferences($obj_id) as $ref_id) {
1033            if ($rbacsystem->checkAccess('delete', $ref_id)) {
1034                $permission_ok = true;
1035                break;
1036            }
1037        }
1038        if (!$permission_ok) {
1039            return $this->__raiseError(
1040                'No permission to delete the object with import id: ' . $import_id,
1041                'Server'
1042            );
1043        }
1044
1045        // Delete all references (delete permssions and entries in object_reference)
1046        foreach ($ref_ids as $ref_id) {
1047            // All subnodes
1048            $node_data = $tree->getNodeData($ref_id);
1049            $subtree_nodes = $tree->getSubtree($node_data);
1050
1051            foreach ($subtree_nodes as $node) {
1052                $ilLog->write('Soap: removeFromSystemByImportId(). Deleting object with title id: ' . $node['title']);
1053                $tmp_obj = ilObjectFactory::getInstanceByRefId($node['ref_id']);
1054                if (!is_object($tmp_obj)) {
1055                    return $this->__raiseError(
1056                        'Cannot create instance of reference id: ' . $node['ref_id'],
1057                        'Server'
1058                    );
1059                }
1060                $tmp_obj->delete();
1061            }
1062            // Finally delete tree
1063            $tree->deleteTree($node_data);
1064        }
1065
1066        return true;
1067    }
1068
1069
1070    public function updateObjects($sid, $a_xml)
1071    {
1072        $this->initAuth($sid);
1073        $this->initIlias();
1074
1075        if (!$this->__checkSession($sid)) {
1076            return $this->__raiseError($this->__getMessage(), $this->__getMessageCode());
1077        }
1078        if (!strlen($a_xml)) {
1079            return $this->__raiseError(
1080                'No valid xml string given.',
1081                'Client'
1082            );
1083        }
1084
1085        global $DIC;
1086
1087        $rbacreview = $DIC['rbacreview'];
1088        $rbacsystem = $DIC['rbacsystem'];
1089        $lng = $DIC['lng'];
1090        $ilAccess = $DIC['ilAccess'];
1091        $objDefinition = $DIC['objDefinition'];
1092
1093        include_once './webservice/soap/classes/class.ilObjectXMLParser.php';
1094        $xml_parser = new ilObjectXMLParser($a_xml, true);
1095        try {
1096            $xml_parser->startParsing();
1097        } catch (ilSaxParserException $se) {
1098            return $this->__raiseError($se->getMessage(), 'Client');
1099        } catch (ilObjectXMLException $e) {
1100            return $this->__raiseError($e->getMessage(), 'Client');
1101        }
1102
1103
1104        // Validate incoming data
1105        $object_datas = $xml_parser->getObjectData();
1106        foreach ($object_datas as &$object_data) {
1107            $res = $this->validateReferences('update', $object_data);
1108            if ($this->isFault($res)) {
1109                return $res;
1110            }
1111
1112
1113            if (!$object_data["obj_id"]) {
1114                return $this->__raiseError('No obj_id in xml found.', 'Client');
1115            } elseif ((int) $object_data["obj_id"] == -1 && count($object_data["references"])>0) {
1116                // object id might be unknown, resolve references instead to determine object id
1117                // all references should point to the same object, so using the first one is ok.
1118                foreach ($object_data["references"] as $refid) {
1119                    if (ilObject::_isInTrash($refid)) {
1120                        continue;
1121                    }
1122                    break;
1123                }
1124
1125                $obj_id_from_refid = ilObject::_lookupObjectId($object_data["references"][0], false);
1126                if (!$obj_id_from_refid) {
1127                    return $this->__raiseError('No obj_id found for reference id ' . $object_data["references"][0], 'CLIENT_OBJECT_NOT_FOUND');
1128                } else {
1129                    $tmp_obj = ilObjectFactory::getInstanceByObjId($object_data['obj_id'], false);
1130                    $object_data["obj_id"] = $obj_id_from_refid;
1131                }
1132            }
1133
1134            $tmp_obj = ilObjectFactory::getInstanceByObjId($object_data['obj_id'], false);
1135            if ($tmp_obj == null) {
1136                return $this->__raiseError('No object for id ' . $object_data['obj_id'] . '!', 'CLIENT_OBJECT_NOT_FOUND');
1137            } else {
1138                $object_data["instance"] = $tmp_obj;
1139            }
1140
1141            if ($object_data['type'] == 'role') {
1142                $rolf_ids = $rbacreview->getFoldersAssignedToRole($object_data['obj_id'], true);
1143                $rolf_id = $rolf_ids[0];
1144
1145                if (!$rbacsystem->checkAccess('write', $rolf_id)) {
1146                    return $this->__raiseError('No write permission for object with id ' . $object_data['obj_id'] . '!', 'Client');
1147                }
1148            } else {
1149                $permission_ok = false;
1150                foreach (ilObject::_getAllReferences($object_data['obj_id']) as $ref_id) {
1151                    if ($ilAccess->checkAccess('write', '', $ref_id)) {
1152                        $permission_ok = true;
1153                        break;
1154                    }
1155                }
1156                if (!$permission_ok) {
1157                    return $this->__raiseError('No write permission for object with id ' . $object_data['obj_id'] . '!', 'Client');
1158                }
1159            }
1160        }
1161        // perform update
1162        if (count($object_datas) > 0) {
1163            foreach ($object_datas as $object_data) {
1164                $this->updateReferences($object_data);
1165                /**
1166                 * @var ilObject
1167                 */
1168                $tmp_obj = $object_data["instance"];
1169                $tmp_obj->setTitle($object_data['title']);
1170                $tmp_obj->setDescription($object_data['description']);
1171
1172                if ($objDefinition->supportsOfflineHandling($tmp_obj->getType())) {
1173                    $tmp_obj->setOfflineStatus($object_data['offline']);
1174                }
1175
1176                $tmp_obj->update();
1177                if (strlen($object_data['owner']) && is_numeric($object_data['owner'])) {
1178                    $tmp_obj->setOwner($object_data['owner']);
1179                    $tmp_obj->updateOwner();
1180                }
1181            }
1182            return true;
1183        }
1184        return false;
1185    }
1186
1187    public function moveObject($sid, $ref_id, $target_id)
1188    {
1189        $this->initAuth($sid);
1190        $this->initIlias();
1191
1192        if (!$this->__checkSession($sid)) {
1193            return $this->__raiseError($this->__getMessage(), $this->__getMessageCode());
1194        }
1195
1196        include_once './webservice/soap/classes/class.ilSoapUtils.php';
1197        global $DIC;
1198
1199        $rbacreview = $DIC['rbacreview'];
1200        $rbacadmin = $DIC['rbacadmin'];
1201        $objDefinition = $DIC['objDefinition'];
1202        $rbacsystem = $DIC['rbacsystem'];
1203        $lng = $DIC['lng'];
1204        $ilUser = $DIC['ilUser'];
1205        $tree = $DIC['tree'];
1206
1207        // does source object exist
1208        if (!$source_object_type = ilObjectFactory::getTypeByRefId($ref_id, false)) {
1209            return $this->__raiseError('No valid source given.', 'Client');
1210        }
1211
1212        // does target object exist
1213        if (!$target_object_type = ilObjectFactory::getTypeByRefId($target_id, false)) {
1214            return $this->__raiseError('No valid target given.', 'Client');
1215        }
1216
1217        // check for trash
1218        if (ilObject::_isInTrash($ref_id)) {
1219            return $this->__raiseError('Object is trashed.', 'Client');
1220        }
1221
1222        if (ilObject::_isInTrash($target_id)) {
1223            return $this->__raiseError('Object is trashed.', 'Client');
1224        }
1225
1226        $canAddType = $this->canAddType($source_object_type, $target_object_type, $target_id);
1227        if ($this->isFault($canAddType)) {
1228            return $canAddType;
1229        }
1230
1231        // check if object already linked to target
1232        $possibleChilds = $tree->getChildsByType($target_id, $ref_id);
1233        foreach ($possibleChilds as $child) {
1234            if ($child["obj_id"] == $ref_id) {
1235                return $this->__raiseError("Object already exists in target.", "Client");
1236            }
1237        }
1238
1239        // CHECK IF PASTE OBJECT SHALL BE CHILD OF ITSELF
1240        if ($tree->isGrandChild($ref_id, $target_id)) {
1241            return $this->__raiseError("Cannot move object into itself.", "Client");
1242        }
1243
1244        $old_parent = $tree->getParentId($ref_id);
1245        $tree->moveTree($ref_id, $target_id);
1246        $rbacadmin->adjustMovedObjectPermissions($ref_id, $old_parent);
1247
1248        include_once('./Services/Conditions/classes/class.ilConditionHandler.php');
1249        ilConditionHandler::_adjustMovedObjectConditions($ref_id);
1250        return true;
1251    }
1252
1253    /**
1254     * copy object in repository
1255     * $sid	session id
1256     * $settings_xml contains copy wizard settings following ilias_copy_wizard_settings.dtd
1257     */
1258    public function copyObject($sid, $copy_settings_xml)
1259    {
1260        $this->initAuth($sid);
1261        $this->initIlias();
1262
1263        if (!$this->__checkSession($sid)) {
1264            return $this->__raiseError($this->__getMessage(), $this->__getMessageCode());
1265        }
1266
1267
1268        include_once './webservice/soap/classes/class.ilSoapUtils.php';
1269        global $DIC;
1270
1271        $rbacreview = $DIC['rbacreview'];
1272        $objDefinition = $DIC['objDefinition'];
1273        $rbacsystem = $DIC['rbacsystem'];
1274        $lng = $DIC['lng'];
1275        $ilUser = $DIC['ilUser'];
1276
1277        include_once './webservice/soap/classes/class.ilCopyWizardSettingsXMLParser.php';
1278        $xml_parser = new ilCopyWizardSettingsXMLParser($copy_settings_xml);
1279        try {
1280            $xml_parser->startParsing();
1281        } catch (ilSaxParserException $se) {
1282            return $this->__raiseError($se->getMessage(), "Client");
1283        }
1284
1285        // checking copy permissions, objects and create permissions
1286        if (!$rbacsystem->checkAccess('copy', $xml_parser->getSourceId())) {
1287            return $this->__raiseError("Missing copy permissions for object with reference id " . $xml_parser->getSourceId(), 'Client');
1288        }
1289
1290        // checking copy permissions, objects and create permissions
1291        $source_id = $xml_parser->getSourceId();
1292        $target_id = $xml_parser->getTargetId();
1293
1294
1295        // does source object exist
1296        if (!$source_object_type = ilObjectFactory::getTypeByRefId($source_id, false)) {
1297            return $this->__raiseError('No valid source given.', 'Client');
1298        }
1299
1300        // does target object exist
1301        if (!$target_object_type = ilObjectFactory::getTypeByRefId($xml_parser->getTargetId(), false)) {
1302            return $this->__raiseError('No valid target given.', 'Client');
1303        }
1304
1305
1306        $canAddType = $this->canAddType($source_object_type, $target_object_type, $target_id);
1307        if ($this->isFault($canAddType)) {
1308            return $canAddType;
1309        }
1310
1311        // if is container object than clone with sub items
1312        $options = $xml_parser->getOptions();
1313        //		print_r($options);
1314        $source_object = ilObjectFactory::getInstanceByRefId($source_id);
1315        if ($source_object instanceof ilContainer) {
1316            // get client id from sid
1317            $clientid = substr($sid, strpos($sid, "::") + 2);
1318            $sessionid = str_replace("::" . $clientid, "", $sid);
1319            // call container clone
1320            $ret = $source_object->cloneAllObject(
1321                $sessionid,
1322                $clientid,
1323                $source_object_type,
1324                $target_id,
1325                $source_id,
1326                $options,
1327                true
1328            );
1329
1330            return $ret['ref_id'];
1331        } else {
1332            // create copy wizard settings
1333            $copy_id = ilCopyWizardOptions::_allocateCopyId();
1334            $wizard_options = ilCopyWizardOptions::_getInstance($copy_id);
1335            $wizard_options->saveOwner($ilUser->getId());
1336            $wizard_options->saveRoot($source_id);
1337
1338            foreach ($options as $source_id => $option) {
1339                $wizard_options->addEntry($source_id, $option);
1340            }
1341            $wizard_options->read();
1342
1343            // call object clone
1344            $newObject = $source_object->cloneObject($xml_parser->getTargetId(), $copy_id);
1345            return is_object($newObject) ? $newObject->getRefId() : -1;
1346        }
1347    }
1348
1349    public function getPathForRefId($sid, $ref_id)
1350    {
1351        $this->initAuth($sid);
1352        $this->initIlias();
1353
1354        if (!$this->__checkSession($sid)) {
1355            return $this->__raiseError($this->__getMessage(), $this->__getMessageCode());
1356        }
1357
1358        global $DIC;
1359
1360        $ilAccess = $DIC['ilAccess'];
1361        $objDefinition = $DIC['objDefinition'];
1362        $rbacsystem = $DIC['rbacsystem'];
1363        $lng = $DIC['lng'];
1364        $ilUser = $DIC['ilUser'];
1365
1366        if (!$rbacsystem->checkAccess('read', $ref_id)) {
1367            return $this->__raiseError("Missing read permissions for object with reference id " . $ref_id, 'Client');
1368        }
1369
1370        if (ilObject::_isInTrash($ref_id)) {
1371            return $this->__raiseError("Object is in Trash", 'Client');
1372        }
1373        global $DIC;
1374
1375        $tree = $DIC['tree'];
1376        $lng = $DIC['lng'];
1377        $items = $tree->getPathFull($ref_id);
1378
1379        include_once 'webservice/soap/classes/class.ilXMLResultSet.php';
1380        include_once 'webservice/soap/classes/class.ilXMLResultSetWriter.php';
1381        include_once 'Modules/Course/classes/class.ilCourseXMLWriter.php';
1382
1383        $xmlResultSet = new ilXMLResultSet();
1384        $xmlResultSet->addColumn("ref_id");
1385        $xmlResultSet->addColumn("type");
1386        $xmlResultSet->addColumn("title");
1387
1388        $writer = new ilXMLResultSetWriter($xmlResultSet);
1389        foreach ($items as $item) {
1390            if ($item["ref_id"] == $ref_id) {
1391                continue;
1392            }
1393            if ($item["title"] == "ILIAS" && $item["type"] == "root") {
1394                $item["title"] = $lng->txt("repository");
1395            }
1396
1397            $row = new ilXMLResultSetRow();
1398            $xmlResultSet->addRow($row);
1399            $row->setValue("ref_id", $item["ref_id"]);
1400            $row->setValue("type", $item["type"]);
1401            $row->setValue("title", $item["title"]);
1402        }
1403        $writer->start();
1404        return $writer->getXML();
1405    }
1406
1407
1408    private function canAddType($type, $target_type, $target_id)
1409    {
1410        // checking for target subtypes. Can we add source to target
1411        global $DIC;
1412
1413        $objDefinition = $DIC['objDefinition'];
1414        $rbacsystem = $DIC['rbacsystem'];
1415
1416        $allowed_types = array('root','cat','grp','crs','fold');
1417        if (!in_array($target_type, $allowed_types)) {
1418            return $this->__raiseError('No valid target type. Target must be reference id of "course, group, category or folder"', 'Client');
1419        }
1420
1421        $allowed_subtypes = $objDefinition->getSubObjects($target_type);
1422        $allowed = array();
1423
1424        foreach ($allowed_subtypes as $row) {
1425            if ($row['name'] != 'rolf') {
1426                $allowed[] = $row['name'];
1427            }
1428        }
1429
1430        if (!in_array($type, $allowed)) {
1431            return $this->__raiseError('Objects of type: ' . $type . ' are not allowed to be subobjects of type ' . $target_type . '!', 'Client');
1432        }
1433        if (!$rbacsystem->checkAccess('create', $target_id, $type)) {
1434            return $this->__raiseError('No permission to create objects of type ' . $type . '!', 'Client');
1435        }
1436
1437        return true;
1438    }
1439
1440    private function validateReferences($a_action, $a_object_data, $a_target_id = 0)
1441    {
1442        global $DIC;
1443
1444        $ilAccess = $DIC['ilAccess'];
1445
1446        if (!isset($a_object_data['references']) or !count($a_object_data['references'])) {
1447            return true;
1448        }
1449        if ($a_action == 'create') {
1450            if (count($a_object_data['references']) > 1) {
1451                if (in_array($a_object_data['type'], array('cat','crs','grp','fold'))) {
1452                    return $this->__raiseError(
1453                        "Cannot create references for type " . $a_object_data['type'],
1454                        'Client'
1455                    );
1456                }
1457            }
1458            if (count($a_object_data['references']) == 1) {
1459                if ($a_target_id != $a_object_data['references'][0]['parent_id']) {
1460                    return $this->__raiseError(
1461                        "Cannot create references for type " . $a_object_data['type'],
1462                        'Client'
1463                    );
1464                }
1465            }
1466
1467            foreach ($a_object_data['references'] as $ref_data) {
1468                if (!$ref_data['parent_id']) {
1469                    return $this->__raiseError('Element References: No parent Id given!', 'Client');
1470                }
1471
1472                $target_type = ilObject::_lookupType(ilObject::_lookupObjId($ref_data['parent_id']));
1473                $can_add_type = $this->canAddType($a_object_data['type'], $target_type, $ref_data['parent_id']);
1474                if ($this->isFault($can_add_type)) {
1475                    return $can_add_type;
1476                }
1477            }
1478            return true;
1479        }
1480
1481        if ($a_action == 'update') {
1482            foreach ($a_object_data['references'] as $ref_data) {
1483                if (!$ref_data['ref_id']) {
1484                    return $this->__raiseError('Element References: No reference id given!', 'Client');
1485                }
1486                // check permissions
1487                if (!$ilAccess->checkAccess('write', '', $ref_data['ref_id'])) {
1488                    return $this->__raiseError('No write permission for object with reference id ' . $ref_data['ref_id'] . '!', 'Client');
1489                }
1490                // TODO: check if all references belong to the same object
1491            }
1492            return true;
1493        }
1494    }
1495
1496    private function updateReferences($a_object_data)
1497    {
1498        global $DIC;
1499
1500        $tree = $DIC['tree'];
1501        $ilLog = $DIC['ilLog'];
1502
1503        if (!isset($a_object_data['references']) or !count($a_object_data['references'])) {
1504            return true;
1505        }
1506
1507        foreach ($a_object_data['references'] as $ref_data) {
1508            if (isset($ref_data['time_target']) /* and ($crs_ref_id = $tree->checkForParentType($ref_data['ref_id'],'crs')) */) {
1509                include_once('./webservice/soap/classes/class.ilObjectXMLWriter.php');
1510                include_once('./Services/Object/classes/class.ilObjectActivation.php');
1511                $old = ilObjectActivation::getItem($ref_data['ref_id']);
1512
1513                $items = new ilObjectActivation();
1514                $items->toggleChangeable(isset($ref_data['time_target']['changeable']) ? $ref_data['time_target']['changeable'] : $old['changeable']);
1515                $items->setTimingStart(isset($ref_data['time_target']['starting_time']) ? $ref_data['time_target']['starting_time'] : $old['timing_start']);
1516                $items->setTimingEnd(isset($ref_data['time_target']['ending_time']) ? $ref_data['time_target']['ending_time'] : $old['timing_end']);
1517                $items->toggleVisible(isset($ref_data['time_target']['timing_visibility']) ? $ref_data['time_target']['timing_visibility'] : $old['visible']);
1518                $items->setSuggestionStart(isset($ref_data['time_target']['suggestion_start']) ? $ref_data['time_target']['suggestion_start'] : $old['suggestion_start']);
1519                $items->setSuggestionEnd(isset($ref_data['time_target']['suggestion_end']) ? $ref_data['time_target']['suggestion_end'] : $old['suggestion_end']);
1520
1521                switch ($ref_data['time_target']['timing_type']) {
1522                    case ilObjectXMLWriter::TIMING_DEACTIVATED:
1523                        $ilLog->write(__METHOD__ . ilObjectActivation::TIMINGS_DEACTIVATED . ' ' . $ref_data['time_target']['timing_type']);
1524                        $items->setTimingType(ilObjectActivation::TIMINGS_DEACTIVATED);
1525                        break;
1526
1527                    case ilObjectXMLWriter::TIMING_TEMPORARILY_AVAILABLE:
1528                        $ilLog->write(__METHOD__ . ilObjectActivation::TIMINGS_ACTIVATION . ' ' . $ref_data['time_target']['timing_type']);
1529                        $items->setTimingType(ilObjectActivation::TIMINGS_ACTIVATION);
1530                        break;
1531
1532                    case ilObjectXMLWriter::TIMING_PRESETTING:
1533                        $ilLog->write(__METHOD__ . ilObjectActivation::TIMINGS_PRESETTING . ' ' . $ref_data['time_target']['timing_type']);
1534                        $items->setTimingType(ilObjectActivation::TIMINGS_PRESETTING);
1535                        break;
1536                }
1537                $items->update($ref_data['ref_id']);
1538            }
1539        }
1540        return true;
1541    }
1542
1543
1544    private function addReferences($source, $a_object_data)
1545    {
1546        global $DIC;
1547
1548        $tree = $DIC['tree'];
1549        $ilLog = $DIC['ilLog'];
1550
1551        if (!isset($a_object_data['references']) or !count($a_object_data['references'])) {
1552            return true;
1553        }
1554
1555        $original_id = $source->getRefId();
1556
1557        foreach ($a_object_data['references'] as $ref_data) {
1558            $new_ref_id = $ref_id = $original_id;
1559            if ($tree->getParentId($original_id) != $ref_data['parent_id']) {
1560                // New reference requested => create it
1561                $new_ref_id = $source->createReference();
1562                $source->putInTree($ref_data['parent_id']);
1563                $source->setPermissions($ref_data['parent_id']);
1564            }
1565            if (isset($ref_data['time_target']) /* and ($crs_ref_id = $tree->checkForParentType($new_ref_id,'crs')) */) {
1566                include_once('./webservice/soap/classes/class.ilObjectXMLWriter.php');
1567                include_once('./Services/Object/classes/class.ilObjectActivation.php');
1568
1569                if (!isset($ref_data['time_target']['starting_time'])) {
1570                    $ref_data['time_target']['starting_time'] = time();
1571                }
1572                if (!isset($ref_data['time_target']['ending_time'])) {
1573                    $ref_data['time_target']['ending_time'] = time();
1574                }
1575
1576                $items = new ilObjectActivation();
1577                $items->toggleChangeable($ref_data['time_target']['changeable']);
1578                $items->setTimingStart($ref_data['time_target']['starting_time']);
1579                $items->setTimingEnd($ref_data['time_target']['ending_time']);
1580                $items->toggleVisible($ref_data['time_target']['timing_visibility']);
1581                $items->setSuggestionStart($ref_data['time_target']['suggestion_start']);
1582                $items->setSuggestionEnd($ref_data['time_target']['suggestion_end']);
1583
1584                switch ($ref_data['time_target']['timing_type']) {
1585                    case ilObjectXMLWriter::TIMING_DEACTIVATED:
1586                        $ilLog->write(__METHOD__ . ilObjectActivation::TIMINGS_DEACTIVATED . ' ' . $ref_data['time_target']['timing_type']);
1587                        $items->setTimingType(ilObjectActivation::TIMINGS_DEACTIVATED);
1588                        break;
1589
1590                    case ilObjectXMLWriter::TIMING_TEMPORARILY_AVAILABLE:
1591                        $ilLog->write(__METHOD__ . ilObjectActivation::TIMINGS_ACTIVATION . ' ' . $ref_data['time_target']['timing_type']);
1592                        $items->setTimingType(ilObjectActivation::TIMINGS_ACTIVATION);
1593                        break;
1594
1595                    case ilObjectXMLWriter::TIMING_PRESETTING:
1596                        $ilLog->write(__METHOD__ . ilObjectActivation::TIMINGS_PRESETTING . ' ' . $ref_data['time_target']['timing_type']);
1597                        $items->setTimingType(ilObjectActivation::TIMINGS_PRESETTING);
1598                        break;
1599                }
1600                $items->update($new_ref_id);
1601            }
1602        }
1603    }
1604}
1605