ILIAS  release_5-2 Revision v5.2.25-18-g3f80b828510
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  {
41  return $row->child;
42  }
43  return 0;
44  }
45 
46  public static function repairPK()
47  {
48  #$GLOBALS['ilDB']->dropPrimaryKey('tree');
49  $GLOBALS['ilDB']->addPrimaryKey('tree', array('child'));
50  }
51 
52  public static function getNodeInfo($a_tree_id, $a_child)
53  {
54  global $ilDB;
55 
56  $query = 'SELECT * FROM tree WHERE child = '.$ilDB->quote($a_child,'integer').' AND tree = '. $ilDB->quote($a_tree_id,'integer');
57  $res = $ilDB->query($query);
58 
59  $node = array();
60  while($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT))
61  {
62  $node['child'] = $row->child;
63  $node['tree'] = $row->tree;
64  $node['depth'] = $row->depth;
65 
66  // read obj_id
67  $query = 'SELECT obj_id FROM object_reference WHERE ref_id = '.$ilDB->quote($a_child,'integer');
68  $ref_res = $ilDB->query($query);
69  while($ref_row = $ref_res->fetchRow(ilDBConstants::FETCHMODE_OBJECT))
70  {
71  $node['obj_id'] = $ref_row->obj_id;
72 
73  // read object info
74  $query = 'SELECT title, description, type FROM object_data '.
75  'WHERE obj_id = '.$ilDB->quote($ref_row->obj_id);
76  $obj_res = $ilDB->query($query);
77  while($obj_row = $obj_res->fetchRow(ilDBConstants::FETCHMODE_OBJECT))
78  {
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 $ilDB;
91 
92  $query = 'SELECT * FROM tree WHERE tree = '.$ilDB->quote($a_tree_id,'integer').' '.'AND child = '.$ilDB->quote($a_childs,'integer');
93  $res = $ilDB->query($query);
94 
95  $childs = array();
96  while($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT))
97  {
98  $childs[] = $row->child;
99  }
100  return $childs;
101  }
102 
108  public static function findDuplicates($a_duplicate_id)
109  {
110  global $ilDB;
111 
112  $query = 'SELECT * FROM tree first '.
113  'WHERE EXISTS ( '.
114  'SELECT child FROM tree second WHERE first.child = second.child '.
115  'GROUP BY child HAVING COUNT(child) > 1 ) '.
116  'AND child = '.$ilDB->quote($a_duplicate_id,'integer').' '.
117  'ORDER BY depth DESC';
118  $res = $ilDB->query($query);
119 
120  $GLOBALS['ilLog']->write($query);
121 
122  $nodes = array();
123  while($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT))
124  {
125  $node = array();
126  $node['tree'] = $row->tree;
127  $node['child'] = $row->child;
128  $node['depth'] = $row->depth;
129 
130  $nodes[] = $node;
131  }
132 
133  return $nodes;
134  }
135 
136  public static function hasDuplicate($a_child)
137  {
138  global $ilDB;
139 
140  return count(self::findDuplicates($a_child));
141  }
142 
143  public static function deleteDuplicateFromTree($a_duplicate_id, $a_delete_trash)
144  {
145  $dups = self::findDuplicates($a_duplicate_id);
146  foreach($dups as $dup)
147  {
148  if($a_delete_trash and $dup['tree'] < 1)
149  {
150  self::deleteDuplicate($dup['tree'],$dup['child']);
151  }
152  if(!$a_delete_trash and $dup['tree'] == 1)
153  {
154  self::deleteDuplicate($dup['tree'],$dup['child']);
155  }
156  }
157  return TRUE;
158  }
159 
160  protected static function deleteDuplicate($tree_id, $dup_id)
161  {
162  global $ilDB;
163 
164  $query = 'SELECT child FROM tree '.
165  'WHERE parent = '.$ilDB->quote($dup_id,'integer').' '.
166  'AND tree = '.$ilDB->quote($tree_id,'integer');
167  $res = $ilDB->query($query);
168  while($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT))
169  {
170  // start recursion
171  self::deleteDuplicate($tree_id, $row->child);
172  }
173  // now delete node
174  if(self::hasDuplicate($dup_id))
175  {
176  $query = 'DELETE FROM tree '.
177  'WHERE child = '.$ilDB->quote($dup_id,'integer').' '.
178  'AND tree = '.$ilDB->quote($tree_id,'integer');
179  $ilDB->manipulate($query);
180  }
181  }
182 
183 
187  public function getDB()
188  {
189  return $this->db;
190  }
191 
196  public function getTask()
197  {
198  return $this->task;
199  }
200 
201 
202 
207  public function validateStructure()
208  {
209  $failures = $this->checkStructure();
210 
211  if(count($failures))
212  {
213  $this->getTask()->setStatus(ilSCTask::STATUS_FAILED);
214  }
215  else
216  {
217  $this->getTask()->setStatus(ilSCTask::STATUS_COMPLETED);
218  }
219  $this->getTask()->setLastUpdate(new ilDateTime(time(),IL_CAL_UNIX));
220  $this->getTask()->update();
221  return count($failures);
222  }
223 
224 
225  public function checkStructure()
226  {
227  return $GLOBALS['tree']->validateParentRelations();
228  global $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  {
240  $failures[] = $row->child;
241  }
242  return $failures;
243  }
244 
245 
246 
250  public function validateDuplicates()
251  {
252  $failures = $this->checkDuplicates();
253 
254  if(count($failures))
255  {
256  $this->getTask()->setStatus(ilSCTask::STATUS_FAILED);
257  }
258  else
259  {
260  $this->getTask()->setStatus(ilSCTask::STATUS_COMPLETED);
261  }
262  $this->getTask()->setLastUpdate(new ilDateTime(time(),IL_CAL_UNIX));
263  $this->getTask()->update();
264  return count($failures);
265  }
266 
270  public function checkDuplicates()
271  {
272  $query = 'SELECT child, count(child) num FROM tree '.
273  'GROUP BY child '.
274  'HAVING count(child) > 1';
275  $res = $this->getDB()->query($query);
276 
277  $GLOBALS['ilLog']->write($query);
278 
279  $failures = array();
280  while($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT))
281  {
282  $failures[] = $row->child;
283  }
284  return $failures;
285  }
286 
287  public function findMissingTreeEntries()
288  {
289  global $ilDB;
290 
291  $failures = $this->readMissingTreeEntries();
292 
293  if(count($failures))
294  {
295  $this->getTask()->setStatus(ilSCTask::STATUS_FAILED);
296  }
297  else
298  {
299  $this->getTask()->setStatus(ilSCTask::STATUS_COMPLETED);
300  }
301 
302  $this->getTask()->setLastUpdate(new ilDateTime(time(),IL_CAL_UNIX));
303  $this->getTask()->update();
304  return count($failures);
305  }
306 
307 
311  public function findMissing()
312  {
313  global $ilDB;
314 
315  $failures = $this->readMissing();
316 
317  if(count($failures))
318  {
319  $this->getTask()->setStatus(ilSCTask::STATUS_FAILED);
320  }
321  else
322  {
323  $this->getTask()->setStatus(ilSCTask::STATUS_COMPLETED);
324  }
325 
326  $this->getTask()->setLastUpdate(new ilDateTime(time(),IL_CAL_UNIX));
327  $this->getTask()->update();
328  return count($failures);
329 
330  }
331 
335  public function repairMissing()
336  {
337  $failures = $this->readMissing();
338  $recf_ref_id = $this->createRecoveryContainer();
339  foreach($failures as $ref_id)
340  {
341  $this->repairMissingObject($recf_ref_id,$ref_id);
342  }
343 
344  }
345 
350  protected function repairMissingObject($a_parent_ref, $a_ref_id)
351  {
352  global $ilDB;
353 
354  // check if object entry exist
355  $query = 'SELECT obj_id FROM object_reference '.
356  'WHERE ref_id = '.$ilDB->quote($a_ref_id,'integer');
357 
358  $res = $ilDB->query($query);
359  while($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT))
360  {
361  $query = 'SELECT type, title FROM object_data '.
362  'WHERE obj_id = '.$ilDB->quote($row->obj_id,'integer');
363  $ores = $ilDB->query($query);
364 
365  $done = FALSE;
366  while($orow = $ores->fetchRow(ilDBConstants::FETCHMODE_OBJECT))
367  {
368  $GLOBALS['ilLog']->write(__METHOD__.': Moving to recovery folder: '.$orow->type.': '.$orow->title);
369  $done = TRUE;
370 
371  include_once './Services/Object/classes/class.ilObjectFactory.php';
372  $factory = new ilObjectFactory();
373  $ref_obj = $factory->getInstanceByRefId($a_ref_id,FALSE);
374 
375  if($ref_obj instanceof ilObjRoleFolder)
376  {
377  $ref_obj->delete();
378  }
379  elseif($ref_obj instanceof ilObject)
380  {
381  $ref_obj->putInTree($a_parent_ref);
382  $ref_obj->setPermissions($a_parent_ref);
383  $GLOBALS['ilLog']->write(__METHOD__.': Moving finished');
384  break;
385  }
386  }
387  if(!$done)
388  {
389  // delete reference value
390  $query = 'DELETE FROM object_reference WHERE ref_id = '.$ilDB->quote($a_ref_id,'integer');
391  $ilDB->manipulate($query);
392  $GLOBALS['ilLog']->write(__METHOD__.': Delete reference for "object" without tree and object_data entry: ref_id= '.$a_ref_id );
393  }
394  }
395 
396  }
397 
404  protected function readMissing()
405  {
406  global $ilDB;
407 
408  $query = 'SELECT ref_id FROM object_reference '.
409  'LEFT JOIN tree ON ref_id = child '.
410  'WHERE child IS NULL';
411  $res = $ilDB->query($query);
412 
413  $failures = array();
414  while($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT))
415  {
416  $failures[] = $row->ref_id;
417  }
418  return $failures;
419  }
420 
425  public function repairMissingTreeEntries()
426  {
427  global $ilDB;
428 
429  $missing = $this->readMissingTreeEntries();
430  $GLOBALS['ilLog']->write(__METHOD__.': '.print_r($missing,TRUE));
431 
432  foreach($missing as $ref_id)
433  {
434  // check for duplicates
435  $query = 'SELECT tree, child FROM tree '.
436  'WHERE child = '.$ilDB->quote($ref_id);
437  $res = $ilDB->query($query);
438  while($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT))
439  {
440  $GLOBALS['ilLog']->write(__METHOD__.': '.$row->tree.': '.$ref_id);
441 
442  $this->deleteMissingTreeEntry($row->tree,$ref_id);
443  }
444  }
445  }
446 
450  protected function deleteMissingTreeEntry($a_tree_id,$a_ref_id)
451  {
452  global $ilDB;
453 
454  $query = 'SELECT child FROM tree '.
455  'WHERE parent = '.$ilDB->quote($a_ref_id,'integer').' '.
456  'AND tree = '.$ilDB->quote($a_tree_id,'integer');
457 
458  $res = $ilDB->query($query);
459  while($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT))
460  {
461  // check for duplicates
462  $query = 'SELECT tree, child FROM tree '.
463  'WHERE child = '.$ilDB->quote($row->child);
464  $resd = $ilDB->query($query);
465  while($rowd = $resd->fetchRow(ilDBConstants::FETCHMODE_OBJECT))
466  {
467  $this->deleteMissingTreeEntry($rowd->tree,$rowd->child);
468  }
469  }
470 
471  // finally delete
472  include_once './Services/Object/classes/class.ilObjectFactory.php';
473  $factory = new ilObjectFactory();
474  $ref_obj = $factory->getInstanceByRefId($a_ref_id,FALSE);
475 
476  if(($ref_obj instanceof ilObject) and $ref_obj->getType())
477  {
478  $ref_obj->delete();
479  }
480 
481  $query = 'DELETE from tree '.
482  'WHERE tree = '.$ilDB->quote($a_tree_id).' '.
483  'AND child = '.$ilDB->quote($a_ref_id);
484  $ilDB->manipulate($query);
485  }
486 
487 
494  protected function readMissingTreeEntries()
495  {
496  global $ilDB;
497 
498  $query = 'SELECT child FROM tree '.
499  'LEFT JOIN object_reference ON child = ref_id '.
500  'WHERE ref_id IS NULL';
501 
502  $res = $ilDB->query($query);
503 
504  $failures = array();
505  while($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT))
506  {
507  $failures[] = $row->child;
508  }
509  return $failures;
510  }
511 
512 
516  protected function createRecoveryContainer()
517  {
518  $now = new ilDateTime(time(),IL_CAL_UNIX);
519 
520  include_once './Modules/Folder/classes/class.ilObjFolder.php';
521  $folder = new ilObjFolder();
522  $folder->setTitle('__System check recovery: '.$now->get(IL_CAL_DATETIME));
523  $folder->create();
524  $folder->createReference();
525  $folder->putInTree(RECOVERY_FOLDER_ID);
526 
527  return $folder->getRefId();
528  }
529 
530 
531 
532 
533 }
534 ?>
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
Class ilObject Basic functions for all objects.
$GLOBALS['loaded']
Global hash that tracks already loaded includes.
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)
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
Create styles array
The data for the language used.
repairMissing()
Repair missing objects.
const STATUS_COMPLETED
$ref_id
Definition: sahs_server.php:39
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)