ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
class.ilSCTreeTasks.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (c) 1998-2009 ILIAS open source, Extended GPL, see docs/LICENSE */
3 
10 {
11  private $db = null;
12  private $task = null;
13 
14  public function __construct(ilSCTask $task)
15  {
16  $this->db = $GLOBALS['DIC']['ilDB'];
17  $this->task = $task;
18  }
19 
20 
26  public static function findDeepestDuplicate()
27  {
28  global $DIC;
29 
30  $ilDB = $DIC['ilDB'];
31 
32  $query = 'SELECT child FROM tree first ' .
33  'WHERE EXISTS ( ' .
34  'SELECT child FROM tree second WHERE first.child = second.child ' .
35  'GROUP BY child HAVING COUNT(child) > 1 ) ' .
36  'ORDER BY depth DESC';
37 
38  $GLOBALS['DIC']['ilLog']->write($query);
39 
40  $res = $ilDB->query($query);
41  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
42  return $row->child;
43  }
44  return 0;
45  }
46 
47  public static function repairPK()
48  {
49  #$GLOBALS['DIC']['ilDB']->dropPrimaryKey('tree');
50  $GLOBALS['DIC']['ilDB']->addPrimaryKey('tree', array('child'));
51  }
52 
53  public static function getNodeInfo($a_tree_id, $a_child)
54  {
55  global $DIC;
56 
57  $ilDB = $DIC['ilDB'];
58 
59  $query = 'SELECT * FROM tree WHERE child = ' . $ilDB->quote($a_child, 'integer') . ' AND tree = ' . $ilDB->quote($a_tree_id, 'integer');
60  $res = $ilDB->query($query);
61 
62  $node = array();
63  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
64  $node['child'] = $row->child;
65  $node['tree'] = $row->tree;
66  $node['depth'] = $row->depth;
67 
68  // read obj_id
69  $query = 'SELECT obj_id FROM object_reference WHERE ref_id = ' . $ilDB->quote($a_child, 'integer');
70  $ref_res = $ilDB->query($query);
71  while ($ref_row = $ref_res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
72  $node['obj_id'] = $ref_row->obj_id;
73 
74  // read object info
75  $query = 'SELECT title, description, type FROM object_data ' .
76  'WHERE obj_id = ' . $ilDB->quote($ref_row->obj_id);
77  $obj_res = $ilDB->query($query);
78  while ($obj_row = $obj_res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
79  $node['title'] = $obj_row->title;
80  $node['description'] = $obj_row->description;
81  $node['type'] = $obj_row->type;
82  }
83  }
84  }
85  return $node;
86  }
87 
88  public static function getChilds($a_tree_id, $a_childs)
89  {
90  global $DIC;
91 
92  $ilDB = $DIC['ilDB'];
93 
94  $query = 'SELECT * FROM tree WHERE tree = ' . $ilDB->quote($a_tree_id, 'integer') . ' ' . 'AND child = ' . $ilDB->quote($a_childs, 'integer');
95  $res = $ilDB->query($query);
96 
97  $childs = array();
98  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
99  $childs[] = $row->child;
100  }
101  return $childs;
102  }
103 
109  public static function findDuplicates($a_duplicate_id)
110  {
111  global $DIC;
112 
113  $ilDB = $DIC['ilDB'];
114 
115  $query = 'SELECT * FROM tree first ' .
116  'WHERE EXISTS ( ' .
117  'SELECT child FROM tree second WHERE first.child = second.child ' .
118  'GROUP BY child HAVING COUNT(child) > 1 ) ' .
119  'AND child = ' . $ilDB->quote($a_duplicate_id, 'integer') . ' ' .
120  'ORDER BY depth DESC';
121  $res = $ilDB->query($query);
122 
123  $GLOBALS['DIC']['ilLog']->write($query);
124 
125  $nodes = array();
126  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
127  $node = array();
128  $node['tree'] = $row->tree;
129  $node['child'] = $row->child;
130  $node['depth'] = $row->depth;
131 
132  $nodes[] = $node;
133  }
134 
135  return $nodes;
136  }
137 
138  public static function hasDuplicate($a_child)
139  {
140  global $DIC;
141 
142  $ilDB = $DIC['ilDB'];
143 
144  return count(self::findDuplicates($a_child));
145  }
146 
147  public static function deleteDuplicateFromTree($a_duplicate_id, $a_delete_trash)
148  {
149  $dups = self::findDuplicates($a_duplicate_id);
150  foreach ($dups as $dup) {
151  if ($a_delete_trash and $dup['tree'] < 1) {
152  self::deleteDuplicate($dup['tree'], $dup['child']);
153  }
154  if (!$a_delete_trash and $dup['tree'] == 1) {
155  self::deleteDuplicate($dup['tree'], $dup['child']);
156  }
157  }
158  return true;
159  }
160 
161  protected static function deleteDuplicate($tree_id, $dup_id)
162  {
163  global $DIC;
164 
165  $ilDB = $DIC['ilDB'];
166 
167  $query = 'SELECT child FROM tree ' .
168  'WHERE parent = ' . $ilDB->quote($dup_id, 'integer') . ' ' .
169  'AND tree = ' . $ilDB->quote($tree_id, 'integer');
170  $res = $ilDB->query($query);
171  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
172  // start recursion
173  self::deleteDuplicate($tree_id, $row->child);
174  }
175  // now delete node
176  if (self::hasDuplicate($dup_id)) {
177  $query = 'DELETE FROM tree ' .
178  'WHERE child = ' . $ilDB->quote($dup_id, 'integer') . ' ' .
179  'AND tree = ' . $ilDB->quote($tree_id, 'integer');
180  $ilDB->manipulate($query);
181  }
182  }
183 
184 
188  public function getDB()
189  {
190  return $this->db;
191  }
192 
197  public function getTask()
198  {
199  return $this->task;
200  }
201 
202 
203 
208  public function validateStructure()
209  {
210  $failures = $this->checkStructure();
211 
212  if (count($failures)) {
213  $this->getTask()->setStatus(ilSCTask::STATUS_FAILED);
214  } else {
215  $this->getTask()->setStatus(ilSCTask::STATUS_COMPLETED);
216  }
217  $this->getTask()->setLastUpdate(new ilDateTime(time(), IL_CAL_UNIX));
218  $this->getTask()->update();
219  return count($failures);
220  }
221 
222 
223  public function checkStructure()
224  {
225  return $GLOBALS['DIC']['tree']->validateParentRelations();
226  global $DIC;
227 
228  $ilDB = $DIC['ilDB'];
229 
230  $query = 'select child from tree child where not exists ' .
231  '( ' .
232  'select child from tree parent where child.parent = parent.child and (parent.lft < child.lft) and (parent.rgt > child.rgt) ' .
233  ')' .
234  'and tree = 1 and child <> 1';
235  $res = $ilDB->query($query);
236 
237  $failures = array();
238  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
239  $failures[] = $row->child;
240  }
241  return $failures;
242  }
243 
244 
245 
249  public function validateDuplicates()
250  {
251  $failures = $this->checkDuplicates();
252 
253  if (count($failures)) {
254  $this->getTask()->setStatus(ilSCTask::STATUS_FAILED);
255  } else {
256  $this->getTask()->setStatus(ilSCTask::STATUS_COMPLETED);
257  }
258  $this->getTask()->setLastUpdate(new ilDateTime(time(), IL_CAL_UNIX));
259  $this->getTask()->update();
260  return count($failures);
261  }
262 
266  public function checkDuplicates()
267  {
268  $query = 'SELECT child, count(child) num FROM tree ' .
269  'GROUP BY child ' .
270  'HAVING count(child) > 1';
271  $res = $this->getDB()->query($query);
272 
273  $GLOBALS['DIC']['ilLog']->write($query);
274 
275  $failures = array();
276  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
277  $failures[] = $row->child;
278  }
279  return $failures;
280  }
281 
282  public function findMissingTreeEntries()
283  {
284  global $DIC;
285 
286  $ilDB = $DIC['ilDB'];
287 
288  $failures = $this->readMissingTreeEntries();
289 
290  if (count($failures)) {
291  $this->getTask()->setStatus(ilSCTask::STATUS_FAILED);
292  } else {
293  $this->getTask()->setStatus(ilSCTask::STATUS_COMPLETED);
294  }
295 
296  $this->getTask()->setLastUpdate(new ilDateTime(time(), IL_CAL_UNIX));
297  $this->getTask()->update();
298  return count($failures);
299  }
300 
301 
305  public function findMissing()
306  {
307  global $DIC;
308 
309  $ilDB = $DIC['ilDB'];
310 
311  $failures = $this->readMissing();
312 
313  if (count($failures)) {
314  $this->getTask()->setStatus(ilSCTask::STATUS_FAILED);
315  } else {
316  $this->getTask()->setStatus(ilSCTask::STATUS_COMPLETED);
317  }
318 
319  $this->getTask()->setLastUpdate(new ilDateTime(time(), IL_CAL_UNIX));
320  $this->getTask()->update();
321  return count($failures);
322  }
323 
327  public function repairMissing()
328  {
329  $failures = $this->readMissing();
330  $recf_ref_id = $this->createRecoveryContainer();
331  foreach ($failures as $ref_id) {
332  $this->repairMissingObject($recf_ref_id, $ref_id);
333  }
334  }
335 
340  protected function repairMissingObject($a_parent_ref, $a_ref_id)
341  {
342  global $DIC;
343 
344  $ilDB = $DIC['ilDB'];
345 
346  // check if object entry exist
347  $query = 'SELECT obj_id FROM object_reference ' .
348  'WHERE ref_id = ' . $ilDB->quote($a_ref_id, 'integer');
349 
350  $res = $ilDB->query($query);
351  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
352  $query = 'SELECT type, title FROM object_data ' .
353  'WHERE obj_id = ' . $ilDB->quote($row->obj_id, 'integer');
354  $ores = $ilDB->query($query);
355 
356  $done = false;
357  while ($orow = $ores->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
358  $GLOBALS['DIC']['ilLog']->write(__METHOD__ . ': Moving to recovery folder: ' . $orow->type . ': ' . $orow->title);
359  $done = true;
360 
361  include_once './Services/Object/classes/class.ilObjectFactory.php';
362  $factory = new ilObjectFactory();
363  $ref_obj = $factory->getInstanceByRefId($a_ref_id, false);
364 
365  if ($ref_obj instanceof ilObjRoleFolder) {
366  $ref_obj->delete();
367  } elseif ($ref_obj instanceof ilObject) {
368  $ref_obj->putInTree($a_parent_ref);
369  $ref_obj->setPermissions($a_parent_ref);
370  $GLOBALS['DIC']['ilLog']->write(__METHOD__ . ': Moving finished');
371  break;
372  }
373  }
374  if (!$done) {
375  // delete reference value
376  $query = 'DELETE FROM object_reference WHERE ref_id = ' . $ilDB->quote($a_ref_id, 'integer');
377  $ilDB->manipulate($query);
378  $GLOBALS['DIC']['ilLog']->write(__METHOD__ . ': Delete reference for "object" without tree and object_data entry: ref_id= ' . $a_ref_id);
379  }
380  }
381  }
382 
389  protected function readMissing()
390  {
391  global $DIC;
392 
393  $ilDB = $DIC['ilDB'];
394 
395  $query = 'SELECT ref_id FROM object_reference ' .
396  'LEFT JOIN tree ON ref_id = child ' .
397  'WHERE child IS NULL';
398  $res = $ilDB->query($query);
399 
400  $failures = array();
401  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
402  $failures[] = $row->ref_id;
403  }
404  return $failures;
405  }
406 
411  public function repairMissingTreeEntries()
412  {
413  global $DIC;
414 
415  $ilDB = $DIC['ilDB'];
416 
417  $missing = $this->readMissingTreeEntries();
418  $GLOBALS['DIC']['ilLog']->write(__METHOD__ . ': ' . print_r($missing, true));
419 
420  foreach ($missing as $ref_id) {
421  // check for duplicates
422  $query = 'SELECT tree, child FROM tree ' .
423  'WHERE child = ' . $ilDB->quote($ref_id);
424  $res = $ilDB->query($query);
425  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
426  $GLOBALS['DIC']['ilLog']->write(__METHOD__ . ': ' . $row->tree . ': ' . $ref_id);
427 
428  $this->deleteMissingTreeEntry($row->tree, $ref_id);
429  }
430  }
431  }
432 
436  protected function deleteMissingTreeEntry($a_tree_id, $a_ref_id)
437  {
438  global $DIC;
439 
440  $ilDB = $DIC['ilDB'];
441 
442  $query = 'SELECT child FROM tree ' .
443  'WHERE parent = ' . $ilDB->quote($a_ref_id, 'integer') . ' ' .
444  'AND tree = ' . $ilDB->quote($a_tree_id, 'integer');
445 
446  $res = $ilDB->query($query);
447  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
448  // check for duplicates
449  $query = 'SELECT tree, child FROM tree ' .
450  'WHERE child = ' . $ilDB->quote($row->child);
451  $resd = $ilDB->query($query);
452  while ($rowd = $resd->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
453  $this->deleteMissingTreeEntry($rowd->tree, $rowd->child);
454  }
455  }
456 
457  // finally delete
458  include_once './Services/Object/classes/class.ilObjectFactory.php';
459  $factory = new ilObjectFactory();
460  $ref_obj = $factory->getInstanceByRefId($a_ref_id, false);
461 
462  if (($ref_obj instanceof ilObject) and $ref_obj->getType()) {
463  $ref_obj->delete();
464  }
465 
466  $query = 'DELETE from tree ' .
467  'WHERE tree = ' . $ilDB->quote($a_tree_id) . ' ' .
468  'AND child = ' . $ilDB->quote($a_ref_id);
469  $ilDB->manipulate($query);
470  }
471 
472 
479  protected function readMissingTreeEntries()
480  {
481  global $DIC;
482 
483  $ilDB = $DIC['ilDB'];
484 
485  $query = 'SELECT child FROM tree ' .
486  'LEFT JOIN object_reference ON child = ref_id ' .
487  'WHERE ref_id IS NULL';
488 
489  $res = $ilDB->query($query);
490 
491  $failures = array();
492  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
493  $failures[] = $row->child;
494  }
495  return $failures;
496  }
497 
498 
502  protected function createRecoveryContainer()
503  {
504  $now = new ilDateTime(time(), IL_CAL_UNIX);
505 
506  include_once './Modules/Folder/classes/class.ilObjFolder.php';
507  $folder = new ilObjFolder();
508  $folder->setTitle('__System check recovery: ' . $now->get(IL_CAL_DATETIME));
509  $folder->create();
510  $folder->createReference();
511  $folder->putInTree(RECOVERY_FOLDER_ID);
512 
513  return $folder->getRefId();
514  }
515 }
Class ilObjRoleFolder.
Defines a system check task.
findMissing()
Find missing objects.
Class ilObjFolder.
Class ilObjectFactory.
const IL_CAL_DATETIME
static findDuplicates($a_duplicate_id)
find duplicates type $ilDB
__construct(ilSCTask $task)
readMissingTreeEntries()
Read missing tree entries for referenced objects Entry in tree but no entry in object reference type...
global $DIC
Definition: saml.php:7
static deleteDuplicate($tree_id, $dup_id)
const STATUS_FAILED
static findDeepestDuplicate()
find duplicates type $ilDB
$factory
Definition: metadata.php:43
repairMissingTreeEntries()
repair missing tree entries type $ilDB
static getChilds($a_tree_id, $a_childs)
const IL_CAL_UNIX
repairMissingObject($a_parent_ref, $a_ref_id)
Repair missing object.
static hasDuplicate($a_child)
foreach($_POST as $key=> $value) $res
static deleteDuplicateFromTree($a_duplicate_id, $a_delete_trash)
deleteMissingTreeEntry($a_tree_id, $a_ref_id)
Delete missing tree entries from tree table.
Date and time handling
$query
$row
repairMissing()
Repair missing objects.
const STATUS_COMPLETED
Defines a system check task.
createRecoveryContainer()
Create a reccovery folder.
readMissing()
Read missing objects in tree Entry in oject_reference but no entry in tree type $ilDB.
global $ilDB
$GLOBALS['JPEG_Segment_Names']
Global Variable: XMP_tag_captions.
checkDuplicates()
Check for duplicates.
validateStructure()
validate tree structure base on parent relation
static getNodeInfo($a_tree_id, $a_child)