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