ILIAS  Release_4_0_x_branch Revision 61816
 All Data Structures Namespaces Files Functions Variables Groups Pages
class.ilDBUpdate.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (c) 1998-2009 ILIAS open source, Extended GPL, see docs/LICENSE */
3 
13 {
18 
24 
30 
34  function ilDBUpdate($a_db_handler = 0,$tmp_flag = false)
35  {
36  // workaround to allow setup migration
37  if ($a_db_handler)
38  {
39  $this->db =& $a_db_handler;
40 
41  if ($tmp_flag)
42  {
43  $this->PATH = "./";
44  }
45  else
46  {
47  $this->PATH = "./";
48  //$this->PATH = "../";
49  }
50  }
51  else
52  {
53  global $mySetup;
54  $this->db = $mySetup->db;
55  $this->PATH = "./";
56  }
57 
58  $this->getCurrentVersion();
59 
60  // get update file for current version
61  $updatefile = $this->getFileForStep($this->currentVersion + 1);
62 
63  $this->current_file = $updatefile;
64  $this->DB_UPDATE_FILE = $this->PATH."setup/sql/".$updatefile;
65 
66  //
67  // NOTE: IF YOU SET THIS TO THE NEWEST FILE, CHANGE ALSO getFileForStep()
68  //
69  $this->LAST_UPDATE_FILE = $this->PATH."setup/sql/dbupdate_02.php";
70 
71  $this->readDBUpdateFile();
72  $this->readLastUpdateFile();
73  $this->readFileVersion();
74  }
75 
79  function getFileForStep($a_version)
80  {
81  //
82  // NOTE: IF YOU ADD A NEW FILE HERE, CHANGE ALSO THE CONSTRUCTOR
83  //
84  if ((int)$a_version > 864) // last number in previous file
85  {
86  return "dbupdate_02.php";
87  }
88  else
89  {
90  return "dbupdate.php";
91  }
92  }
93 
97  function initStep($i)
98  {
99  //
100  }
101 
107  function _DBUpdate()
108  {
109  $this->db->disconnect();
110  }
111 
112  function readDBUpdateFile()
113  {
114  if (!file_exists($this->DB_UPDATE_FILE))
115  {
116  $this->error = "no_db_update_file";
117  $this->filecontent = array();
118  return false;
119  }
120 
121  $this->filecontent = @file($this->DB_UPDATE_FILE);
122  return true;
123  }
124 
126  {
127  if (!file_exists($this->LAST_UPDATE_FILE))
128  {
129  $this->error = "no_last_update_file";
130  $this->lastfilecontent = array();
131  return false;
132  }
133 
134  $this->lastfilecontent = @file($this->LAST_UPDATE_FILE);
135  return true;
136  }
137 
138  function getCurrentVersion()
139  {
140  $GLOBALS["ilDB"] = $this->db;
141  include_once './Services/Administration/classes/class.ilSetting.php';
142  $set = new ilSetting();
143  $this->currentVersion = (integer) $set->get("db_version");
144 
145  return $this->currentVersion;
146  }
147 
148  function setCurrentVersion ($a_version)
149  {
150  include_once './Services/Administration/classes/class.ilSetting.php';
151  $set = new ilSetting();
152  $set->set("db_version", $a_version);
153  $this->currentVersion = $a_version;
154 
155  return true;
156  }
157 
163  function setRunningStatus($a_nr)
164  {
165  include_once './Services/Administration/classes/class.ilSetting.php';
166  $set = new ilSetting();
167  $set->set("db_update_running", $a_nr);
168  $this->db_update_running = $a_nr;
169  }
170 
176  function getRunningStatus()
177  {
178  include_once './Services/Administration/classes/class.ilSetting.php';
179  $set = new ilSetting();
180  $this->db_update_running = (integer) $set->get("db_update_running");
181 
182  return $this->db_update_running;
183  }
184 
189  {
190  include_once './Services/Administration/classes/class.ilSetting.php';
191  $set = new ilSetting();
192  $set->set("db_update_running", 0);
193  $this->db_update_running = 0;
194  }
195 
196  function readFileVersion()
197  {
198  //go through filecontent and search for last occurence of <#x>
199  reset($this->lastfilecontent);
200  $regs = array();
201  foreach ($this->lastfilecontent as $row)
202  {
203  if (ereg("^<#([0-9]+)>", $row, $regs))
204  {
205  $version = $regs[1];
206  }
207  }
208 
209  $this->fileVersion = (integer) $version;
210  return $this->fileVersion;
211  }
212 
216  function getFileVersion()
217  {
218  return $this->fileVersion;
219  }
220 
227  function execQuery($db,$str)
228  {
229  $sql = explode("\n",trim($str));
230  for ($i=0; $i<count($sql); $i++)
231  {
232  $sql[$i] = trim($sql[$i]);
233  if ($sql[$i] != "" && substr($sql[$i],0,1)!="#")
234  {
235  //take line per line, until last char is ";"
236  if (substr($sql[$i],-1)==";")
237  {
238  //query is complete
239  $q .= " ".substr($sql[$i],0,-1);
240  $check = $this->checkQuery($q);
241  if ($check === true)
242  {
243  $r = $db->query($q);
244  if (MDB2::isError($r))
245  {
246  $this->error = $r->getMessage();
247  return false;
248  }
249  }
250  else
251  {
252  $this->error = $check;
253  return false;
254  }
255  unset($q);
256  } //if
257  else
258  {
259  $q .= " ".$sql[$i];
260  } //else
261  } //if
262  } //for
263  if ($q != "")
264  {
265  echo "incomplete_statement: ".$q."<br>";
266  return false;
267  }
268  return true;
269  }
270 
274  function checkQuery($q)
275  {
276  return true;
277  }
278 
282  function applyUpdate($a_break = 0)
283  {
284  global $ilCtrlStructureReader, $ilMySQLAbstraction;
285 
286  include_once './Services/Database/classes/class.ilMySQLAbstraction.php';
287 
288  $ilMySQLAbstraction = new ilMySQLAbstraction();
289  $GLOBALS['ilMySQLAbstraction'] = $ilMySQLAbstraction;
290 
293 
294  if ($a_break > $this->currentVersion &&
295  $a_break < $this->fileVersion)
296  {
297  $f = $a_break;
298  }
299 
300  if ($c < $f)
301  {
302  $msg = array();
303  for ($i=($c+1); $i<=$f; $i++)
304  {
305  // check wether next update file must be loaded
306  if ($this->current_file != $this->getFileForStep($i))
307  {
308  $this->DB_UPDATE_FILE = $this->PATH."setup/sql/".$this->getFileForStep($i);
309  $this->readDBUpdateFile();
310  }
311 
312  $this->initStep($i);
313 
314  if ($this->applyUpdateNr($i) == false)
315  {
316  $msg[] = array(
317  "msg" => "update_error: ".$this->error,
318  "nr" => $i
319  );
320  $this->updateMsg = $msg;
321  return false;
322  }
323  else
324  {
325  $msg[] = array(
326  "msg" => "update_applied",
327  "nr" => $i
328  );
329  }
330  }
331 
332  $this->updateMsg = $msg;
333  }
334  else
335  {
336  $this->updateMsg = "no_changes";
337  }
338 
339  if ($f < $this->fileVersion)
340  {
341  return true;
342  }
343  else
344  {
345  return $this->loadXMLInfo();
346  }
347  }
348 
349  function loadXMLInfo()
350  {
351  global $ilCtrlStructureReader;
352 
353  // read module and service information into db
354  require_once "./setup/classes/class.ilModuleReader.php";
355  require_once "./setup/classes/class.ilServiceReader.php";
356  require_once "./setup/classes/class.ilCtrlStructureReader.php";
357 
358  require_once "./Services/Component/classes/class.ilModule.php";
359  require_once "./Services/Component/classes/class.ilService.php";
362 
364  foreach($modules as $module)
365  {
366  $mr = new ilModuleReader(ILIAS_ABSOLUTE_PATH."/Modules/".$module["subdir"]."/module.xml",
367  $module["subdir"], "Modules");
368  $mr->getModules();
369  unset($mr);
370  }
371 
373  foreach($services as $service)
374  {
375  $sr = new ilServiceReader(ILIAS_ABSOLUTE_PATH."/Services/".$service["subdir"]."/service.xml",
376  $service["subdir"], "Services");
377  $sr->getServices();
378  unset($sr);
379  }
380 
381  $ilCtrlStructureReader->readStructure();
382 
383  return true;
384  }
385 
392  function applyUpdateNr($nr, $hotfix = false)
393  {
394  global $ilDB,$ilErr,$ilUser,$ilCtrlStructureReader,$ilModuleReader,$ilMySQLAbstraction;
395 
396  //search for desired $nr
397  reset($this->filecontent);
398 
399  if (!$hotfix)
400  {
401  $this->setRunningStatus($nr);
402  }
403 
404  //init
405  $i = 0;
406 
407  //go through filecontent
408  while (!ereg("^<#".$nr.">", $this->filecontent[$i]) && $i<count($this->filecontent))
409  {
410  $i++;
411  }
412 
413  //update not found
414  if ($i == count($this->filecontent))
415  {
416  $this->error = "update_not_found";
417  return false;
418  }
419 
420  $i++;
421 
422  //update found, now extract this update to a new array
423  $update = array();
424  while ($i<count($this->filecontent) && !ereg("^<#".($nr+1).">", $this->filecontent[$i]))
425  {
426  $update[] = trim($this->filecontent[$i]);
427  $i++;
428  }
429 
430  //now you have the update, now process it
431  $sql = array();
432  $php = array();
433  $mode = "sql";
434 
435  foreach ($update as $row)
436  {
437  if (ereg("<\?php", $row))
438  {
439  if (count($sql)>0)
440  {
441  if ($this->execQuery($this->db, implode("\n", $sql)) == false)
442  {
443  $this->error = $this->error;
444  return false;
445  }
446  $sql = array();
447  }
448  $mode = "php";
449  }
450  elseif (ereg("\?>", $row))
451  {
452  if (count($php)>0)
453  {
454  $code = implode("\n", $php);
455  eval($code);
456  $php = array();
457  }
458  $mode = "sql";
459 
460  }
461  else
462  {
463  if ($mode == "sql")
464  {
465  $sql[] = $row;
466  }
467 
468  if ($mode == "php")
469  {
470  $php[] = $row;
471  }
472  } //else
473  } //foreach
474 
475  if ($mode == "sql" && count($sql) > 0)
476  {
477  if ($this->execQuery($this->db, implode("\n", $sql)) == false)
478  {
479  $this->error = "dump_error: ".$this->error;
480  return false;
481  }
482  }
483 
484  //increase db_Version number
485  if (!$hotfix)
486  {
487  $this->setCurrentVersion($nr);
488  }
489  else
490  {
491  $this->setHotfixCurrentVersion($nr);
492  }
493 
494  if (!$hotfix)
495  {
496  $this->clearRunningStatus();
497  }
498  //$this->currentVersion = $ilias->getSetting("db_version");
499 
500  return true;
501 
502  }
503 
505  {
506  if ($this->fileVersion > $this->currentVersion)
507  return false;
508  else
509  return true;
510  }
511 
512  function getTables()
513  {
514  $a = array();
515 
516  $query = "SHOW TABLES";
517  $res = $this->db->query($query);
518  while ($row = $res->fetchRow())
519  {
520  $status = $this->getTableStatus($row[0]);
521  $a[] = array(
522  "name" => $status["Table"],
523  "table" => $row[0],
524  "status" => $status["Msg_text"]
525  );
526  }
527  return $a;
528  }
529 
530  function getTableStatus($table)
531  {
532  $a = array();
533 
534  $query = "ANALYZE TABLE ".$table;
535  $res = $this->db->query($query);
536  $row = $res->fetchRow(DB_FETCHMODE_ASSOC);
537  return $row;
538  }
539 
540  function optimizeTables($tables)
541  {
542  $msg = array();
543  foreach ($_POST["tables"] as $key => $value)
544  {
545  $query = "OPTIMIZE TABLE ".$key;
546  $res = $this->db->query($query);
547  $msg[] = "table $key: ok";
548  }
549  return $msg;
550  }
551 
555 
556 
561  {
562  $this->readHotfixInfo();
563  return $this->hotfix_current_version;
564  }
565 
569  function setHotfixCurrentVersion($a_version)
570  {
571  $this->readHotfixInfo();
572  $this->hotfix_setting->set("db_hotfixes_".
573  $this->hotfix_version[0]."_".$this->hotfix_version[1], $a_version);
574  $this->hotfix_current_version = $a_version;
575  return true;
576  }
577 
582  {
583  $this->readHotfixInfo();
584  return $this->hotfix_file_version;
585  }
586 
590  function readHotfixFileVersion($a_file_content)
591  {
592  //go through filecontent and search for last occurence of <#x>
593  reset($a_file_content);
594  $regs = array();
595  foreach ($a_file_content as $row)
596  {
597  if (ereg("^<#([0-9]+)>", $row, $regs))
598  {
599  $version = $regs[1];
600  }
601  }
602 
603  return (integer) $version;
604  }
605 
609  function readHotfixInfo($a_force = false)
610  {
611  if ($this->hotfix_info_read && !$a_force)
612  {
613  return;
614  }
615  include_once './Services/Administration/classes/class.ilSetting.php';
616  $GLOBALS["ilDB"] = $this->db;
617  $this->hotfix_setting = new ilSetting();
618  $ilias_version = ILIAS_VERSION_NUMERIC;
619  $version_array = explode(".", $ilias_version);
620  $this->hotfix_version[0] = $version_array[0];
621  $this->hotfix_version[1] = $version_array[1];
622  $hotfix_file = $this->PATH."setup/sql/".$this->hotfix_version[0]."_".$this->hotfix_version[1]."_hotfixes.php";
623  if (is_file($hotfix_file))
624  {
625  $this->hotfix_content = @file($hotfix_file);
626  $this->hotfix_current_version = (int) $this->hotfix_setting->get("db_hotfixes_".
627  $this->hotfix_version[0]."_".$this->hotfix_version[1]);
628  $this->hotfix_file_version = $this->readHotfixFileVersion($this->hotfix_content);
629  }
630  $this->hotfix_info_read = true;
631  }
632 
636  function hotfixAvailable()
637  {
638  $this->readHotfixInfo();
639  if ($this->hotfix_file_version > $this->hotfix_current_version)
640  {
641  return true;
642  }
643  return false;
644  }
645 
649  function applyHotfix()
650  {
651  global $ilCtrlStructureReader, $ilMySQLAbstraction;
652 
653  include_once './Services/Database/classes/class.ilMySQLAbstraction.php';
654 
655  $ilMySQLAbstraction = new ilMySQLAbstraction();
656  $GLOBALS['ilMySQLAbstraction'] = $ilMySQLAbstraction;
657 
658  $this->readHotfixInfo(true);
659 
660  $f = $this->getHotfixFileVersion();
661  $c = $this->getHotfixCurrentVersion();
662 
663  if ($c < $f)
664  {
665  $msg = array();
666  for ($i=($c+1); $i<=$f; $i++)
667  {
668 // $this->initStep($i); // nothings happens here
669 
670  $this->filecontent = $this->hotfix_content;
671 
672  if ($this->applyUpdateNr($i, true) == false)
673  {
674  $msg[] = array(
675  "msg" => "update_error: ".$this->error,
676  "nr" => $i
677  );
678  $this->updateMsg = $msg;
679  return false;
680  }
681  else
682  {
683  $msg[] = array(
684  "msg" => "hotfix_applied",
685  "nr" => $i
686  );
687  }
688  }
689 
690  $this->updateMsg = $msg;
691  }
692  else
693  {
694  $this->updateMsg = "no_changes";
695  }
696 
697  return $this->loadXMLInfo();
698  }
699 
700 
701 } // END class.DBUdate
702 ?>