ILIAS  release_9 Revision v9.13-25-g2c18ec4c24f
class.ilSoapUtils.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
25 include_once './webservice/soap/classes/class.ilSoapAdministration.php';
26 
28 {
29  public function ignoreUserAbort(): int
30  {
31  return ignore_user_abort(true);
32  }
33 
34  public function disableSOAPCheck(): void
35  {
36  $this->soap_check = false;
37  }
38 
42  public function saveTempFileAsMediaObject(string $sid, string $name, string $tmp_name)
43  {
44  $this->initAuth($sid);
45  $this->initIlias();
46 
47  if (!$this->checkSession($sid)) {
48  return $this->raiseError($this->getMessage(), $this->getMessageCode());
49  }
50 
51  include_once "./Services/MediaObjects/classes/class.ilObjMediaObject.php";
52  return ilObjMediaObject::_saveTempFileAsMediaObject($name, $tmp_name);
53  }
54 
58  public function getMobsOfObject(string $sid, string $a_type, int $a_id)
59  {
60  $this->initAuth($sid);
61  $this->initIlias();
62 
63  if (!$this->checkSession($sid)) {
64  return $this->raiseError($this->getMessage(), $this->getMessageCode());
65  }
66 
67  include_once "./Services/MediaObjects/classes/class.ilObjMediaObject.php";
68  return ilObjMediaObject::_getMobsOfObject($a_type, $a_id);
69  }
70 
74  public function ilCloneDependencies(string $sid, int $copy_identifier, bool $is_initialized = false)
75  {
76  if (!$is_initialized) {
77  $this->initAuth($sid);
78  $this->initIlias();
79 
80  if (!$this->checkSession($sid)) {
81  return $this->raiseError($this->getMessage(), $this->getMessageCode());
82  }
83  }
84 
85  global $DIC;
86 
87  $ilLog = $DIC['ilLog'];
88  $ilUser = $DIC['ilUser'];
89 
90  include_once('Services/CopyWizard/classes/class.ilCopyWizardOptions.php');
91  $cp_options = ilCopyWizardOptions::_getInstance($copy_identifier);
92 
93  // Check owner of copy procedure
94  if (!$cp_options->checkOwner($ilUser->getId())) {
95  ilLoggerFactory::getLogger('obj')->error('Permission check failed for user id: ' . $ilUser->getId() . ', copy id: ' . $copy_identifier);
96  return false;
97  }
98 
99  // Fetch first node
100  if (($node = $cp_options->fetchFirstDependenciesNode()) === null) {
101  $cp_options->deleteAll();
102  ilLoggerFactory::getLogger('obj')->info('Finished copy step 2. Copy completed');
103  return true;
104  }
105 
106  // Check options of this node
107  $options = $cp_options->getOptions((int) $node['child']);
108  $new_ref_id = 0;
109  switch ($options['type']) {
111  ilLoggerFactory::getLogger('obj')->debug(': Omitting node: ' . $node['obj_id'] . ', ' . $node['title'] . ', ' . $node['type']);
112  $this->callNextDependency($sid, $cp_options);
113  break;
114 
116  ilLoggerFactory::getLogger('obj')->debug(': Start cloning dependencies for node: ' . $node['obj_id'] . ', ' . $node['title'] . ', ' . $node['type']);
117  $this->cloneDependencies($node, $cp_options);
118  $this->callNextDependency($sid, $cp_options);
119  break;
120 
122  ilLoggerFactory::getLogger('obj')->debug(': Start cloning dependencies: ' . $node['obj_id'] . ', ' . $node['title'] . ', ' . $node['type']);
123  $this->cloneDependencies($node, $cp_options);
124  $this->callNextDependency($sid, $cp_options);
125  break;
126 
127  default:
128  ilLoggerFactory::getLogger('obj')->warning('No valid action type given for node: ' . $node['obj_id'] . ', ' . $node['title'] . ', ' . $node['type']);
129  $this->callNextDependency($sid, $cp_options);
130  break;
131  }
132  return true;
133  }
134 
138  public function ilClone(string $sid, int $copy_identifier)
139  {
140  $this->initAuth($sid);
141  $this->initIlias();
142 
143  if (!$this->checkSession($sid)) {
144  ilLoggerFactory::getLogger('obj')->error('Object cloning failed. Invalid session given: ' . $this->getMessage());
145  }
146 
147  global $DIC;
148 
149  $ilUser = $DIC->user();
150 
151  include_once('Services/CopyWizard/classes/class.ilCopyWizardOptions.php');
152  $cp_options = ilCopyWizardOptions::_getInstance($copy_identifier);
153 
154  // Check owner of copy procedure
155  if (!$cp_options->checkOwner($ilUser->getId())) {
156  ilLoggerFactory::getLogger('obj')->error('Permission check failed for user id: ' . $ilUser->getId() . ', copy id: ' . $copy_identifier);
157  return false;
158  }
159 
160  // Fetch first node
161  if (($node = $cp_options->fetchFirstNode()) === null) {
162  ilLoggerFactory::getLogger('obj')->info('Finished copy step 1. Starting copying of object dependencies...');
163  return $this->ilCloneDependencies($sid, $copy_identifier, true);
164  }
165  // Check options of this node
166  $options = $cp_options->getOptions((int) $node['child']);
167 
168  $action = $this->rewriteActionForNode($cp_options, $node, $options);
169 
170  $new_ref_id = 0;
171  switch ($action) {
173  ilLoggerFactory::getLogger('obj')->debug(': Omitting node: ' . $node['obj_id'] . ', ' . $node['title'] . ', ' . $node['type']);
174  // set mapping to zero
175  $cp_options->appendMapping($node['child'], 0);
176  $this->callNextNode($sid, $cp_options);
177  break;
178 
180 
181  ilLoggerFactory::getLogger('obj')->debug('Start cloning node: ' . $node['obj_id'] . ', ' . $node['title'] . ', ' . $node['type']);
182  $new_ref_id = $this->cloneNode($node, $cp_options);
183  $this->callNextNode($sid, $cp_options);
184  break;
185 
187  ilLoggerFactory::getLogger('obj')->debug('Start linking node: ' . $node['obj_id'] . ', ' . $node['title'] . ', ' . $node['type']);
188  $new_ref_id = $this->linkNode($node, $cp_options);
189  $this->callNextNode($sid, $cp_options);
190  break;
191 
192  case \ilCopyWizardOptions::COPY_WIZARD_LINK_TO_TARGET:
193  ilLoggerFactory::getLogger('obj')->debug('Start creating internal link for: ' . $node['obj_id'] . ', ' . $node['title'] . ', ' . $node['type']);
194  $new_ref_id = $this->internalLinkNode($node, $cp_options);
195  $this->callNextNode($sid, $cp_options);
196  break;
197 
198  default:
199  ilLoggerFactory::getLogger('obj')->warning('No valid action type given for: ' . $node['obj_id'] . ', ' . $node['title'] . ', ' . $node['type']);
200  $this->callNextNode($sid, $cp_options);
201  break;
202  }
203  return $new_ref_id;
204  }
205 
206  protected function rewriteActionForNode(ilCopyWizardOptions $cpo, array $node, array $options): int
207  {
209  if (array_key_exists('type', $options)) {
210  $default_mode = (int) $options['type'];
211  }
212  if (
213  array_key_exists('child', $node) &&
214  $cpo->isRootNode((int) $node['child'])
215  ) {
216  return $default_mode;
217  }
218 
219  if ($this->findMappedReferenceForNode($cpo, $node) && $default_mode == \ilCopyWizardOptions::COPY_WIZARD_COPY) {
220  return \ilCopyWizardOptions::COPY_WIZARD_LINK_TO_TARGET;
221  }
222  return $default_mode;
223  }
224 
225  protected function findMappedReferenceForNode(\ilCopyWizardOptions $cpo, array $node): ?int
226  {
227  global $DIC;
228 
229  $logger = $DIC->logger()->obj();
230  $tree = $DIC->repositoryTree();
231  $root = $cpo->getRootNode();
232  $obj_id = (int) $node['obj_id'];
233 
234  $mappings = $cpo->getMappings();
235  foreach (\ilObject::_getAllReferences($obj_id) as $ref_id => $also_ref_id) {
236  $logger->debug('Validating node: ' . $ref_id . ' and root ' . $root);
237  $logger->dump($DIC->repositoryTree()->getRelation($ref_id, $root));
238 
239  if ($DIC->repositoryTree()->getRelation($ref_id, $root) !== \ilTree::RELATION_CHILD) {
240  $logger->debug('Ignoring non child relation');
241  continue;
242  }
243  // check if mapping is already available
244  $logger->dump($mappings);
245  if (array_key_exists($ref_id, $mappings)) {
246  $logger->debug('Found existing mapping for linked node.');
247  return $mappings[$ref_id];
248  }
249  }
250  $logger->info('Nothing found');
251  return null;
252  }
253 
254  private function callNextNode(string $sid, ilCopyWizardOptions $cp_options): void
255  {
256  global $DIC;
257 
258  $ilLog = $DIC->logger()->obj();
259 
260  $cp_options->dropFirstNode();
261  if ($cp_options->isSOAPEnabled()) {
262  // Start next soap call
263  include_once 'Services/WebServices/SOAP/classes/class.ilSoapClient.php';
264  $soap_client = new ilSoapClient();
265  $soap_client->setResponseTimeout(1);
266  $soap_client->enableWSDL(true);
267  $soap_client->init();
268  $soap_client->call('ilClone', array($sid, $cp_options->getCopyId()));
269  } else {
270  ilLoggerFactory::getLogger('obj')->warning('SOAP clone call failed. Calling clone method manually');
271  $cp_options->read();
272  include_once('./webservice/soap/include/inc.soap_functions.php');
273  $res = ilSoapFunctions::ilClone($sid, $cp_options->getCopyId());
274  }
275  }
276 
277  private function callNextDependency(string $sid, ilCopyWizardOptions $cp_options): void
278  {
279  $cp_options->dropFirstDependenciesNode();
280 
281  if ($cp_options->isSOAPEnabled()) {
282  // Start next soap call
283  include_once 'Services/WebServices/SOAP/classes/class.ilSoapClient.php';
284  $soap_client = new ilSoapClient();
285  $soap_client->setResponseTimeout(1);
286  $soap_client->enableWSDL(true);
287  $soap_client->init();
288  $soap_client->call('ilCloneDependencies', array($sid, $cp_options->getCopyId()));
289  } else {
290  ilLoggerFactory::getLogger('obj')->warning('SOAP clone call failed. Calling clone method manually');
291  $cp_options->read();
292  include_once('./webservice/soap/include/inc.soap_functions.php');
293  $res = ilSoapFunctions::ilCloneDependencies($sid, $cp_options->getCopyId());
294  }
295  }
296 
297  private function cloneNode(array $node, ilCopyWizardOptions $cp_options): int
298  {
299  global $DIC;
300 
301  $ilLog = $DIC['ilLog'];
302  $tree = $DIC['tree'];
303  $ilAccess = $DIC['ilAccess'];
304  $rbacreview = $DIC['rbacreview'];
305  $source_id = (int) $node['child'];
306  $parent_id = (int) $node['parent'];
307  $options = $cp_options->getOptions((int) $node['child']);
308  $mappings = $cp_options->getMappings();
309 
310  if (!$ilAccess->checkAccess('copy', '', (int) $node['child'])) {
311  ilLoggerFactory::getLogger('obj')->error('No copy permission granted: ' . $source_id . ', ' . $node['title'] . ', ' . $node['type']);
312  return 0;
313  }
314  if (!isset($mappings[$parent_id])) {
315  ilLoggerFactory::getLogger('obj')->info('Omitting node ' . $source_id . ', ' . $node['title'] . ', ' . $node['type'] . '. No target found.');
316  return 0;
317  }
318  $target_id = $mappings[$parent_id];
319 
320  if (!$tree->isInTree($target_id)) {
321  ilLoggerFactory::getLogger('obj')->notice('Omitting node ' . $source_id . ', ' . $node['title'] . ', ' . $node['type'] . '. Object has been deleted.');
322  return 0;
323  }
324 
325  $orig = ilObjectFactory::getInstanceByRefId($source_id);
326  $new_obj = $orig->cloneObject((int) $target_id, $cp_options->getCopyId());
327 
328  if (!is_object($new_obj)) {
329  ilLoggerFactory::getLogger('obj')->error('Error copying ' . $source_id . ', ' . $node['title'] . ', ' . $node['type'] . '. No target found.');
330  return 0;
331  }
332 
333  // rbac log
334  include_once "Services/AccessControl/classes/class.ilRbacLog.php";
335  $rbac_log_roles = $rbacreview->getParentRoleIds($new_obj->getRefId(), false);
336  $rbac_log = ilRbacLog::gatherFaPa($new_obj->getRefId(), array_keys($rbac_log_roles), true);
337  ilRbacLog::add(ilRbacLog::COPY_OBJECT, $new_obj->getRefId(), $rbac_log, true);
338 
339  // Finally add new mapping entry
340  $cp_options->appendMapping($source_id, $new_obj->getRefId());
341  return $new_obj->getRefId();
342  }
343 
344  private function cloneDependencies(array $node, ilCopyWizardOptions $cp_options): void
345  {
346  global $DIC;
347 
348  $ilLog = $DIC['ilLog'];
349 
350  $source_id = (int) $node['child'];
351  $mappings = $cp_options->getMappings();
352 
353  if (!isset($mappings[$source_id])) {
354  ilLoggerFactory::getLogger('obj')->debug('Omitting node ' . $source_id . ', ' . $node['title'] . ', ' . $node['type'] . '. No mapping found.');
355  return;
356  }
357  $target_id = $mappings[$source_id];
358 
359  $orig = ilObjectFactory::getInstanceByRefId($source_id);
360  $orig->cloneDependencies($target_id, $cp_options->getCopyId());
361  }
362 
363  private function internalLinkNode(array $node, ilCopyWizardOptions $cp_options): int
364  {
365  global $DIC;
366 
367  $ilAccess = $DIC->access();
368  $logger = $DIC->logger()->obj();
369  $rbacreview = $DIC->rbac()->review();
370  $tree = $DIC->repositoryTree();
371  $mappings = $cp_options->getMappings();
372 
373  $source_id = $this->findMappedReferenceForNode($cp_options, $node);
374  try {
375  $orig = ilObjectFactory::getInstanceByRefId((int) $source_id);
376  if (!$orig instanceof \ilObject) {
377  $logger->error('Cannot create object instance.');
378  return 0;
379  }
380  } catch (\ilObjectNotFoundException $e) {
381  $logger->error('Cannot create object instance for ref_id: ' . $source_id);
382  $logger->error($e->getMessage());
383  return 0;
384  }
385 
386  // target (parent id) is the mapped parent id of the current node
387  $node_parent = $node['parent'];
388  if (!array_key_exists($node_parent, $mappings)) {
389  $logger->error('Cannot new parent id for node: ' . $node['parent']);
390  return 0;
391  }
392  $parent_id = $mappings[$node_parent];
393 
394  $new_ref_id = $orig->createReference();
395  $orig->putInTree($parent_id);
396  $orig->setPermissions($parent_id);
397 
398  if (!($new_ref_id)) {
399  $logger->warning('Creating internal link failed.');
400  return 0;
401  }
402 
403  // rbac log
404  $rbac_log_roles = $rbacreview->getParentRoleIds($new_ref_id, false);
405  $rbac_log = ilRbacLog::gatherFaPa($new_ref_id, array_keys($rbac_log_roles), true);
406  ilRbacLog::add(ilRbacLog::LINK_OBJECT, $new_ref_id, $rbac_log, true);
407 
408  // Finally add new mapping entry
409  $cp_options->appendMapping($node['child'], $new_ref_id);
410 
411  $logger->notice('Added mapping for ' . $node['child'] . ' ' . $new_ref_id);
412  return $new_ref_id;
413  }
414 
415  private function linkNode(array $node, ilCopyWizardOptions $cp_options): int
416  {
417  global $DIC;
418 
419  $ilLog = $DIC['ilLog'];
420  $ilAccess = $DIC['ilAccess'];
421  $rbacreview = $DIC['rbacreview'];
422 
423  $source_id = (int) $node['child'];
424  $parent_id = (int) $node['parent'];
425  $options = $cp_options->getOptions((int) $node['child']);
426  $mappings = $cp_options->getMappings();
427 
428  if (!$ilAccess->checkAccess('delete', '', (int) $node['child'])) {
429  ilLoggerFactory::getLogger('obj')->warning('No delete permission granted: ' . $source_id . ', ' . $node['title'] . ', ' . $node['type']);
430  return 0;
431  }
432  if (!isset($mappings[$parent_id])) {
433  ilLoggerFactory::getLogger('obj')->warning('Omitting node ' . $source_id . ', ' . $node['title'] . ', ' . $node['type'] . '. No target found.');
434  return 0;
435  }
436  $target_id = $mappings[$parent_id];
437 
438  $orig = ilObjectFactory::getInstanceByRefId($source_id);
439  $new_ref_id = $orig->createReference();
440  $orig->putInTree($target_id);
441  $orig->setPermissions($target_id);
442 
443  if (!($new_ref_id)) {
444  ilLoggerFactory::getLogger('obj')->error('Error linking ' . $source_id . ', ' . $node['title'] . ', ' . $node['type'] . '. No target found.');
445  return 0;
446  }
447 
448  // rbac log
449  include_once "Services/AccessControl/classes/class.ilRbacLog.php";
450  $rbac_log_roles = $rbacreview->getParentRoleIds($new_ref_id, false);
451  $rbac_log = ilRbacLog::gatherFaPa($new_ref_id, array_keys($rbac_log_roles), true);
452  ilRbacLog::add(ilRbacLog::LINK_OBJECT, $new_ref_id, $rbac_log, true);
453 
454  // Finally add new mapping entry
455  $cp_options->appendMapping($source_id, $new_ref_id);
456  return $new_ref_id;
457  }
458 
463  public function deleteExpiredDualOptInUserObjects(string $sid, int $usr_id): bool
464  {
465  $this->initAuth($sid);
466  $this->initIlias();
467 
468  // Session check not possible -> anonymous user is the trigger
469 
470  global $DIC;
471 
472  $ilDB = $DIC->database();
473  $ilLog = $DIC->logger()->user();
474 
475  $ilLog->debug('Started deletion of inactive user objects with expired confirmation hash values (dual opt in) ...');
476  require_once 'Services/Registration/classes/class.ilRegistrationSettings.php';
477  $oRegSettigs = new ilRegistrationSettings();
478  $query = '';
479 
480  /*
481  * Fetch the current actuator user object first, because this user will try to perform very probably
482  * a new registration with the same login name in a few seconds ;-)
483  *
484  */
485  if ($usr_id > 0) {
486  $query .= 'SELECT usr_id, create_date, reg_hash FROM usr_data '
487  . 'WHERE active = 0 '
488  . 'AND reg_hash IS NOT NULL '
489  . 'AND usr_id = ' . $ilDB->quote($usr_id, 'integer') . ' ';
490  $query .= 'UNION ';
491  }
492 
493  $query .= 'SELECT usr_id, create_date, reg_hash FROM usr_data '
494  . 'WHERE active = 0 '
495  . 'AND reg_hash IS NOT NULL '
496  . 'AND usr_id != ' . $ilDB->quote($usr_id, 'integer') . ' ';
497 
498  $res = $ilDB->query($query);
499 
500  $ilLog->debug($ilDB->numRows($res) . ' inactive user objects with confirmation hash values (dual opt in) found ...');
501 
502  /*
503  * mjansen: 15.12.2010:
504  * I perform the expiration check in php because of multi database support (mysql, postgresql).
505  * I did not find an oracle equivalent for mysql: UNIX_TIMESTAMP()
506  */
507 
508  $num_deleted_users = 0;
509  while ($row = $ilDB->fetchAssoc($res)) {
510  if ((int) $row['usr_id'] === ANONYMOUS_USER_ID || (int) $row['usr_id'] === SYSTEM_USER_ID) {
511  continue;
512  }
513 
514  if (($row['reg_hash'] ?? '') === '') {
515  continue;
516  }
517 
518  if (($row['create_date'] ?? '') !== '' &&
519  $oRegSettigs->getRegistrationHashLifetime() > 0 &&
520  time() - $oRegSettigs->getRegistrationHashLifetime() > strtotime($row['create_date'])) {
521  $user = ilObjectFactory::getInstanceByObjId($row['usr_id'], false);
522  if ($user instanceof ilObjUser) {
523  $ilLog->info('User ' . $user->getLogin() . ' (obj_id: ' . $user->getId() . ') will be deleted due to an expired registration hash ...');
524  $user->delete();
525  ++$num_deleted_users;
526  }
527  }
528  }
529 
530  $ilLog->info($num_deleted_users . ' inactive user objects with expired confirmation hash values (dual opt in) deleted ...');
531  $ilLog->info('Finished deletion of inactive user objects with expired confirmation hash values (dual opt in) ...');
532 
533  return true;
534  }
535 }
static gatherFaPa(int $a_ref_id, array $a_role_ids, bool $a_add_action=false)
$res
Definition: ltiservices.php:69
const ANONYMOUS_USER_ID
Definition: constants.php:27
static getLogger(string $a_component_id)
Get component logger.
static ilClone(string $sid, int $copy_identifier)
saveTempFileAsMediaObject(string $sid, string $name, string $tmp_name)
deleteExpiredDualOptInUserObjects(string $sid, int $usr_id)
Method for soap webservice: deleteExpiredDualOptInUserObjects This service will run in background...
const SYSTEM_USER_ID
This file contains constants for PHPStan analyis, see: https://phpstan.org/config-reference#constants...
Definition: constants.php:26
static _getAllReferences(int $id)
get all reference ids for object ID
ilClone(string $sid, int $copy_identifier)
ilCloneDependencies(string $sid, int $copy_identifier, bool $is_initialized=false)
linkNode(array $node, ilCopyWizardOptions $cp_options)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
cloneNode(array $node, ilCopyWizardOptions $cp_options)
raiseError(string $a_message, $a_code)
rewriteActionForNode(ilCopyWizardOptions $cpo, array $node, array $options)
cloneDependencies(array $node, ilCopyWizardOptions $cp_options)
internalLinkNode(array $node, ilCopyWizardOptions $cp_options)
getOptions(int $a_source_id)
Get entry by source public.
global $DIC
Definition: feed.php:28
isSOAPEnabled()
Check if SOAP calls are disabled.
$ref_id
Definition: ltiauth.php:67
appendMapping($a_source_id, $a_target_id)
Add mapping of source -> target.
static ilCloneDependencies(string $sid, int $copy_identifier)
static add(int $a_action, int $a_ref_id, array $a_diff, bool $a_source_ref_id=false)
callNextNode(string $sid, ilCopyWizardOptions $cp_options)
getMobsOfObject(string $sid, string $a_type, int $a_id)
findMappedReferenceForNode(\ilCopyWizardOptions $cpo, array $node)
static getInstanceByRefId(int $ref_id, bool $stop_on_error=true)
get an instance of an Ilias object by reference id
const COPY_OBJECT
const LINK_OBJECT
const RELATION_CHILD
static _getMobsOfObject(string $a_type, int $a_id, int $a_usage_hist_nr=0, string $a_lang="-")
dropFirstDependenciesNode()
Drop first node (for cloneDependencies())
static getInstanceByObjId(?int $obj_id, bool $stop_on_error=true)
get an instance of an Ilias object by object id
static _saveTempFileAsMediaObject(string $name, string $tmp_name, bool $upload=true)
Create new media object and update page in db and return new media object.
Class ilObjAuthSettingsGUI.
callNextDependency(string $sid, ilCopyWizardOptions $cp_options)
isRootNode(int $a_root)
Is root node public.
static _getInstance(int $a_copy_id)
dropFirstNode()
Drop first node (for cloneObject())