ILIAS  release_5-3 Revision v5.3.23-19-g915713cf615
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['ilDB'];
17  $this->task = $task;
18  }
19 
20 
26  public static function findDeepestDuplicate()
27  {
28  global $ilDB;
29 
30  $query = 'SELECT child FROM tree first ' .
31  'WHERE EXISTS ( ' .
32  'SELECT child FROM tree second WHERE first.child = second.child ' .
33  'GROUP BY child HAVING COUNT(child) > 1 ) ' .
34  'ORDER BY depth DESC';
35 
36  $GLOBALS['ilLog']->write($query);
37 
38  $res = $ilDB->query($query);
39  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
40  return $row->child;
41  }
42  return 0;
43  }
44 
45  public static function repairPK()
46  {
47  #$GLOBALS['ilDB']->dropPrimaryKey('tree');
48  $GLOBALS['ilDB']->addPrimaryKey('tree', array('child'));
49  }
50 
51  public static function getNodeInfo($a_tree_id, $a_child)
52  {
53  global $ilDB;
54 
55  $query = 'SELECT * FROM tree WHERE child = ' . $ilDB->quote($a_child, 'integer') . ' AND tree = ' . $ilDB->quote($a_tree_id, 'integer');
56  $res = $ilDB->query($query);
57 
58  $node = array();
59  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
60  $node['child'] = $row->child;
61  $node['tree'] = $row->tree;
62  $node['depth'] = $row->depth;
63 
64  // read obj_id
65  $query = 'SELECT obj_id FROM object_reference WHERE ref_id = ' . $ilDB->quote($a_child, 'integer');
66  $ref_res = $ilDB->query($query);
67  while ($ref_row = $ref_res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
68  $node['obj_id'] = $ref_row->obj_id;
69 
70  // read object info
71  $query = 'SELECT title, description, type FROM object_data ' .
72  'WHERE obj_id = ' . $ilDB->quote($ref_row->obj_id);
73  $obj_res = $ilDB->query($query);
74  while ($obj_row = $obj_res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
75  $node['title'] = $obj_row->title;
76  $node['description'] = $obj_row->description;
77  $node['type'] = $obj_row->type;
78  }
79  }
80  }
81  return $node;
82  }
83 
84  public static function getChilds($a_tree_id, $a_childs)
85  {
86  global $ilDB;
87 
88  $query = 'SELECT * FROM tree WHERE tree = ' . $ilDB->quote($a_tree_id, 'integer') . ' ' . 'AND child = ' . $ilDB->quote($a_childs, 'integer');
89  $res = $ilDB->query($query);
90 
91  $childs = array();
92  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
93  $childs[] = $row->child;
94  }
95  return $childs;
96  }
97 
103  public static function findDuplicates($a_duplicate_id)
104  {
105  global $ilDB;
106 
107  $query = 'SELECT * FROM tree first ' .
108  'WHERE EXISTS ( ' .
109  'SELECT child FROM tree second WHERE first.child = second.child ' .
110  'GROUP BY child HAVING COUNT(child) > 1 ) ' .
111  'AND child = ' . $ilDB->quote($a_duplicate_id, 'integer') . ' ' .
112  'ORDER BY depth DESC';
113  $res = $ilDB->query($query);
114 
115  $GLOBALS['ilLog']->write($query);
116 
117  $nodes = array();
118  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
119  $node = array();
120  $node['tree'] = $row->tree;
121  $node['child'] = $row->child;
122  $node['depth'] = $row->depth;
123 
124  $nodes[] = $node;
125  }
126 
127  return $nodes;
128  }
129 
130  public static function hasDuplicate($a_child)
131  {
132  global $ilDB;
133 
134  return count(self::findDuplicates($a_child));
135  }
136 
137  public static function deleteDuplicateFromTree($a_duplicate_id, $a_delete_trash)
138  {
139  $dups = self::findDuplicates($a_duplicate_id);
140  foreach ($dups as $dup) {
141  if ($a_delete_trash and $dup['tree'] < 1) {
142  self::deleteDuplicate($dup['tree'], $dup['child']);
143  }
144  if (!$a_delete_trash and $dup['tree'] == 1) {
145  self::deleteDuplicate($dup['tree'], $dup['child']);
146  }
147  }
148  return true;
149  }
150 
151  protected static function deleteDuplicate($tree_id, $dup_id)
152  {
153  global $ilDB;
154 
155  $query = 'SELECT child FROM tree ' .
156  'WHERE parent = ' . $ilDB->quote($dup_id, 'integer') . ' ' .
157  'AND tree = ' . $ilDB->quote($tree_id, 'integer');
158  $res = $ilDB->query($query);
159  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
160  // start recursion
161  self::deleteDuplicate($tree_id, $row->child);
162  }
163  // now delete node
164  if (self::hasDuplicate($dup_id)) {
165  $query = 'DELETE FROM tree ' .
166  'WHERE child = ' . $ilDB->quote($dup_id, 'integer') . ' ' .
167  'AND tree = ' . $ilDB->quote($tree_id, 'integer');
168  $ilDB->manipulate($query);
169  }
170  }
171 
172 
176  public function getDB()
177  {
178  return $this->db;
179  }
180 
185  public function getTask()
186  {
187  return $this->task;
188  }
189 
190 
191 
196  public function validateStructure()
197  {
198  $failures = $this->checkStructure();
199 
200  if (count($failures)) {
201  $this->getTask()->setStatus(ilSCTask::STATUS_FAILED);
202  } else {
203  $this->getTask()->setStatus(ilSCTask::STATUS_COMPLETED);
204  }
205  $this->getTask()->setLastUpdate(new ilDateTime(time(), IL_CAL_UNIX));
206  $this->getTask()->update();
207  return count($failures);
208  }
209 
210 
211  public function checkStructure()
212  {
213  return $GLOBALS['tree']->validateParentRelations();
214  global $ilDB;
215 
216  $query = 'select child from tree child where not exists ' .
217  '( ' .
218  'select child from tree parent where child.parent = parent.child and (parent.lft < child.lft) and (parent.rgt > child.rgt) ' .
219  ')' .
220  'and tree = 1 and child <> 1';
221  $res = $ilDB->query($query);
222 
223  $failures = array();
224  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
225  $failures[] = $row->child;
226  }
227  return $failures;
228  }
229 
230 
231 
235  public function validateDuplicates()
236  {
237  $failures = $this->checkDuplicates();
238 
239  if (count($failures)) {
240  $this->getTask()->setStatus(ilSCTask::STATUS_FAILED);
241  } else {
242  $this->getTask()->setStatus(ilSCTask::STATUS_COMPLETED);
243  }
244  $this->getTask()->setLastUpdate(new ilDateTime(time(), IL_CAL_UNIX));
245  $this->getTask()->update();
246  return count($failures);
247  }
248 
252  public function checkDuplicates()
253  {
254  $query = 'SELECT child, count(child) num FROM tree ' .
255  'GROUP BY child ' .
256  'HAVING count(child) > 1';
257  $res = $this->getDB()->query($query);
258 
259  $GLOBALS['ilLog']->write($query);
260 
261  $failures = array();
262  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
263  $failures[] = $row->child;
264  }
265  return $failures;
266  }
267 
268  public function findMissingTreeEntries()
269  {
270  global $ilDB;
271 
272  $failures = $this->readMissingTreeEntries();
273 
274  if (count($failures)) {
275  $this->getTask()->setStatus(ilSCTask::STATUS_FAILED);
276  } else {
277  $this->getTask()->setStatus(ilSCTask::STATUS_COMPLETED);
278  }
279 
280  $this->getTask()->setLastUpdate(new ilDateTime(time(), IL_CAL_UNIX));
281  $this->getTask()->update();
282  return count($failures);
283  }
284 
285 
289  public function findMissing()
290  {
291  global $ilDB;
292 
293  $failures = $this->readMissing();
294 
295  if (count($failures)) {
296  $this->getTask()->setStatus(ilSCTask::STATUS_FAILED);
297  } else {
298  $this->getTask()->setStatus(ilSCTask::STATUS_COMPLETED);
299  }
300 
301  $this->getTask()->setLastUpdate(new ilDateTime(time(), IL_CAL_UNIX));
302  $this->getTask()->update();
303  return count($failures);
304  }
305 
309  public function repairMissing()
310  {
311  $failures = $this->readMissing();
312  $recf_ref_id = $this->createRecoveryContainer();
313  foreach ($failures as $ref_id) {
314  $this->repairMissingObject($recf_ref_id, $ref_id);
315  }
316  }
317 
322  protected function repairMissingObject($a_parent_ref, $a_ref_id)
323  {
324  global $ilDB;
325 
326  // check if object entry exist
327  $query = 'SELECT obj_id FROM object_reference ' .
328  'WHERE ref_id = ' . $ilDB->quote($a_ref_id, 'integer');
329 
330  $res = $ilDB->query($query);
331  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
332  $query = 'SELECT type, title FROM object_data ' .
333  'WHERE obj_id = ' . $ilDB->quote($row->obj_id, 'integer');
334  $ores = $ilDB->query($query);
335 
336  $done = false;
337  while ($orow = $ores->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
338  $GLOBALS['ilLog']->write(__METHOD__ . ': Moving to recovery folder: ' . $orow->type . ': ' . $orow->title);
339  $done = true;
340 
341  include_once './Services/Object/classes/class.ilObjectFactory.php';
342  $factory = new ilObjectFactory();
343  $ref_obj = $factory->getInstanceByRefId($a_ref_id, false);
344 
345  if ($ref_obj instanceof ilObjRoleFolder) {
346  $ref_obj->delete();
347  } elseif ($ref_obj instanceof ilObject) {
348  $ref_obj->putInTree($a_parent_ref);
349  $ref_obj->setPermissions($a_parent_ref);
350  $GLOBALS['ilLog']->write(__METHOD__ . ': Moving finished');
351  break;
352  }
353  }
354  if (!$done) {
355  // delete reference value
356  $query = 'DELETE FROM object_reference WHERE ref_id = ' . $ilDB->quote($a_ref_id, 'integer');
357  $ilDB->manipulate($query);
358  $GLOBALS['ilLog']->write(__METHOD__ . ': Delete reference for "object" without tree and object_data entry: ref_id= ' . $a_ref_id);
359  }
360  }
361  }
362 
369  protected function readMissing()
370  {
371  global $ilDB;
372 
373  $query = 'SELECT ref_id FROM object_reference ' .
374  'LEFT JOIN tree ON ref_id = child ' .
375  'WHERE child IS NULL';
376  $res = $ilDB->query($query);
377 
378  $failures = array();
379  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
380  $failures[] = $row->ref_id;
381  }
382  return $failures;
383  }
384 
389  public function repairMissingTreeEntries()
390  {
391  global $ilDB;
392 
393  $missing = $this->readMissingTreeEntries();
394  $GLOBALS['ilLog']->write(__METHOD__ . ': ' . print_r($missing, true));
395 
396  foreach ($missing as $ref_id) {
397  // check for duplicates
398  $query = 'SELECT tree, child FROM tree ' .
399  'WHERE child = ' . $ilDB->quote($ref_id);
400  $res = $ilDB->query($query);
401  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
402  $GLOBALS['ilLog']->write(__METHOD__ . ': ' . $row->tree . ': ' . $ref_id);
403 
404  $this->deleteMissingTreeEntry($row->tree, $ref_id);
405  }
406  }
407  }
408 
412  protected function deleteMissingTreeEntry($a_tree_id, $a_ref_id)
413  {
414  global $ilDB;
415 
416  $query = 'SELECT child FROM tree ' .
417  'WHERE parent = ' . $ilDB->quote($a_ref_id, 'integer') . ' ' .
418  'AND tree = ' . $ilDB->quote($a_tree_id, 'integer');
419 
420  $res = $ilDB->query($query);
421  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
422  // check for duplicates
423  $query = 'SELECT tree, child FROM tree ' .
424  'WHERE child = ' . $ilDB->quote($row->child);
425  $resd = $ilDB->query($query);
426  while ($rowd = $resd->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
427  $this->deleteMissingTreeEntry($rowd->tree, $rowd->child);
428  }
429  }
430 
431  // finally delete
432  include_once './Services/Object/classes/class.ilObjectFactory.php';
433  $factory = new ilObjectFactory();
434  $ref_obj = $factory->getInstanceByRefId($a_ref_id, false);
435 
436  if (($ref_obj instanceof ilObject) and $ref_obj->getType()) {
437  $ref_obj->delete();
438  }
439 
440  $query = 'DELETE from tree ' .
441  'WHERE tree = ' . $ilDB->quote($a_tree_id) . ' ' .
442  'AND child = ' . $ilDB->quote($a_ref_id);
443  $ilDB->manipulate($query);
444  }
445 
446 
453  protected function readMissingTreeEntries()
454  {
455  global $ilDB;
456 
457  $query = 'SELECT child FROM tree ' .
458  'LEFT JOIN object_reference ON child = ref_id ' .
459  'WHERE ref_id IS NULL';
460 
461  $res = $ilDB->query($query);
462 
463  $failures = array();
464  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
465  $failures[] = $row->child;
466  }
467  return $failures;
468  }
469 
470 
474  protected function createRecoveryContainer()
475  {
476  $now = new ilDateTime(time(), IL_CAL_UNIX);
477 
478  include_once './Modules/Folder/classes/class.ilObjFolder.php';
479  $folder = new ilObjFolder();
480  $folder->setTitle('__System check recovery: ' . $now->get(IL_CAL_DATETIME));
481  $folder->create();
482  $folder->createReference();
483  $folder->putInTree(RECOVERY_FOLDER_ID);
484 
485  return $folder->getRefId();
486  }
487 }
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...
static deleteDuplicate($tree_id, $dup_id)
const STATUS_FAILED
static findDeepestDuplicate()
find duplicates type $ilDB
$GLOBALS['loaded']
Global hash that tracks already loaded includes.
$factory
Definition: metadata.php:47
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
Create styles array
The data for the language used.
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
Add data(end) time
Method that wraps PHPs time in order to allow simulations with the workflow.
checkDuplicates()
Check for duplicates.
validateStructure()
validate tree structure base on parent relation
static getNodeInfo($a_tree_id, $a_child)