ILIAS  release_5-2 Revision v5.2.25-18-g3f80b828510
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 __construct($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_04.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 > 4182) // last number in previous file
85 {
86 return "dbupdate_04.php";
87 }
88 else if ((int)$a_version > 2948) // last number in previous file
89 {
90 return "dbupdate_03.php";
91 }
92 else if ((int)$a_version > 864) // last number in previous file
93 {
94 return "dbupdate_02.php";
95 }
96 else
97 {
98 return "dbupdate.php";
99 }
100 }
101
105 function initStep($i)
106 {
107 //
108 }
109
110
112 {
113 if (!file_exists($this->DB_UPDATE_FILE))
114 {
115 $this->error = "no_db_update_file";
116 $this->filecontent = array();
117 return false;
118 }
119
120 $this->filecontent = @file($this->DB_UPDATE_FILE);
121 return true;
122 }
123
125 {
126 if (!file_exists($this->LAST_UPDATE_FILE))
127 {
128 $this->error = "no_last_update_file";
129 $this->lastfilecontent = array();
130 return false;
131 }
132
133 $this->lastfilecontent = @file($this->LAST_UPDATE_FILE);
134 return true;
135 }
136
138 {
139 include_once './Services/Administration/classes/class.ilSetting.php';
140 $set = new ilSetting("common", true);
141 $this->currentVersion = (integer) $set->get("db_version");
143 }
144
145 function setCurrentVersion ($a_version)
146 {
147 include_once './Services/Administration/classes/class.ilSetting.php';
148 $set = new ilSetting("common", true);
149 $set->set("db_version", $a_version);
150 $this->currentVersion = $a_version;
151
152 return true;
153 }
154
160 function setRunningStatus($a_nr)
161 {
162 include_once './Services/Administration/classes/class.ilSetting.php';
163 $set = new ilSetting("common", true);
164 $set->set("db_update_running", $a_nr);
165 $this->db_update_running = $a_nr;
166 }
167
174 {
175 include_once './Services/Administration/classes/class.ilSetting.php';
176 $set = new ilSetting("common", true);
177 $this->db_update_running = (integer) $set->get("db_update_running");
178
179 return $this->db_update_running;
180 }
181
186 {
187 include_once './Services/Administration/classes/class.ilSetting.php';
188 $set = new ilSetting("common", true);
189 $set->set("db_update_running", 0);
190 $this->db_update_running = 0;
191 }
192
194 {
195 //go through filecontent and search for last occurence of <#x>
196 reset($this->lastfilecontent);
197 $regs = array();
198 foreach ($this->lastfilecontent as $row)
199 {
200 if (preg_match('/^<\#([0-9]+)>/', $row, $regs))
201 {
202 $version = $regs[1];
203 }
204 }
205
206 $this->fileVersion = (integer) $version;
207 return $this->fileVersion;
208 }
209
213 function getFileVersion()
214 {
215 return $this->fileVersion;
216 }
217
224 function execQuery($db,$str)
225 {
226 $sql = explode("\n",trim($str));
227 for ($i=0; $i<count($sql); $i++)
228 {
229 $sql[$i] = trim($sql[$i]);
230 if ($sql[$i] != "" && substr($sql[$i],0,1)!="#")
231 {
232 //take line per line, until last char is ";"
233 if (substr($sql[$i],-1)==";")
234 {
235 //query is complete
236 $q .= " ".substr($sql[$i],0,-1);
237 $check = $this->checkQuery($q);
238 if ($check === true)
239 {
240 try {
241 $r = $db->query($q);
242 } catch (ilDatabaseException $e) {
243 var_dump($e); // FSX
244 exit;
245 $this->error = $e->getMessage();
246
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 {
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
363 $mr = new ilModuleReader("", "", "");
364 $mr->clearTables();
365 foreach($modules as $module)
366 {
367 $mr = new ilModuleReader(ILIAS_ABSOLUTE_PATH."/Modules/".$module["subdir"]."/module.xml",
368 $module["subdir"], "Modules");
369 $mr->getModules();
370 unset($mr);
371 }
372
373 $sr = new ilServiceReader("", "", "");
374 $sr->clearTables();
375 foreach($services as $service)
376 {
377 $sr = new ilServiceReader(ILIAS_ABSOLUTE_PATH."/Services/".$service["subdir"]."/service.xml",
378 $service["subdir"], "Services");
379 $sr->getServices();
380 unset($sr);
381 }
382
383 $ilCtrlStructureReader->readStructure();
384
385 return true;
386 }
387
394 function applyUpdateNr($nr, $hotfix = false, $custom_update = false)
395 {
396 global $ilDB,$ilErr,$ilUser,$ilCtrlStructureReader,$ilModuleReader,$ilMySQLAbstraction;
397
398 //search for desired $nr
399 reset($this->filecontent);
400
401 if (!$hotfix && !$custom_update)
402 {
403 $this->setRunningStatus($nr);
404 }
405
406 //init
407 $i = 0;
408
409 //go through filecontent
410 while (!preg_match("/^<\#".$nr.">/", $this->filecontent[$i]) && $i<count($this->filecontent))
411 {
412 $i++;
413 }
414
415 //update not found
416 if ($i == count($this->filecontent))
417 {
418 $this->error = "update_not_found";
419 return false;
420 }
421
422 $i++;
423
424 //update found, now extract this update to a new array
425 $update = array();
426 while ($i<count($this->filecontent) && !preg_match("/^<#".($nr+1).">/", $this->filecontent[$i]))
427 {
428 $update[] = trim($this->filecontent[$i]);
429 $i++;
430 }
431
432 //now you have the update, now process it
433 $sql = array();
434 $php = array();
435 $mode = "sql";
436
437 foreach ($update as $row)
438 {
439 if (preg_match("/<\?php/", $row))
440 {
441 if (count($sql)>0)
442 {
443 if ($this->execQuery($this->db, implode("\n", $sql)) == false)
444 {
445 $this->error = $this->error;
446 return false;
447 }
448 $sql = array();
449 }
450 $mode = "php";
451 }
452 elseif (preg_match("/\?>/", $row))
453 {
454 if (count($php)>0)
455 {
456 $code = implode("\n", $php);
457 if (eval($code) === false)
458 {
459 $this->error = "Parse error: ".$code;
460 return false;
461 }
462 $php = array();
463 }
464 $mode = "sql";
465
466 }
467 else
468 {
469 if ($mode == "sql")
470 {
471 $sql[] = $row;
472 }
473
474 if ($mode == "php")
475 {
476 $php[] = $row;
477 }
478 } //else
479 } //foreach
480
481 if ($mode == "sql" && count($sql) > 0)
482 {
483 if ($this->execQuery($this->db, implode("\n", $sql)) == false)
484 {
485 $this->error = "dump_error: ".$this->error;
486 return false;
487 }
488 }
489
490 //increase db_Version number
491 if (!$hotfix && !$custom_update)
492 {
493 $this->setCurrentVersion($nr);
494 }
495 elseif($hotfix)
496 {
497 $this->setHotfixCurrentVersion($nr);
498 }
499 elseif($custom_update)
500 {
502 }
503
504 if (!$hotfix && !$custom_update)
505 {
506 $this->clearRunningStatus();
507 }
508 //$this->currentVersion = $ilias->getSetting("db_version");
509
510 return true;
511
512 }
513
515 {
516 if ($this->fileVersion > $this->currentVersion)
517 return false;
518 else
519 return true;
520 }
521
522 function getTables()
523 {
524 $a = array();
525
526 $query = "SHOW TABLES";
527 $res = $this->db->query($query);
528 while ($row = $res->fetchRow())
529 {
530 $status = $this->getTableStatus($row[0]);
531 $a[] = array(
532 "name" => $status["Table"],
533 "table" => $row[0],
534 "status" => $status["Msg_text"]
535 );
536 }
537 return $a;
538 }
539
540 function getTableStatus($table)
541 {
542 $a = array();
543
544 $query = "ANALYZE TABLE ".$table;
545 $res = $this->db->query($query);
547 return $row;
548 }
549
550
554
555
560 {
561 $this->readHotfixInfo();
562 return $this->hotfix_current_version;
563 }
564
568 function setHotfixCurrentVersion($a_version)
569 {
570 $this->readHotfixInfo();
571 $this->hotfix_setting->set("db_hotfixes_".
572 $this->hotfix_version[0]."_".$this->hotfix_version[1], $a_version);
573 $this->hotfix_current_version = $a_version;
574 return true;
575 }
576
581 {
582 $this->readHotfixInfo();
583 return $this->hotfix_file_version;
584 }
585
589 function readHotfixFileVersion($a_file_content)
590 {
591 //go through filecontent and search for last occurence of <#x>
592 reset($a_file_content);
593 $regs = array();
594 foreach ($a_file_content as $row)
595 {
596 if (preg_match("/^<#([0-9]+)>/", $row, $regs))
597 {
598 $version = $regs[1];
599 }
600 }
601
602 return (integer) $version;
603 }
604
608 function readHotfixInfo($a_force = false)
609 {
610 if ($this->hotfix_info_read && !$a_force)
611 {
612 return;
613 }
614 include_once './Services/Administration/classes/class.ilSetting.php';
615 $this->hotfix_setting = new ilSetting("common", true);
616 $ilias_version = ILIAS_VERSION_NUMERIC;
617 $version_array = explode(".", $ilias_version);
618 $this->hotfix_version[0] = $version_array[0];
619 $this->hotfix_version[1] = $version_array[1];
620 $hotfix_file = $this->PATH."setup/sql/".$this->hotfix_version[0]."_".$this->hotfix_version[1]."_hotfixes.php";
621 if (is_file($hotfix_file))
622 {
623 $this->hotfix_content = @file($hotfix_file);
624 $this->hotfix_current_version = (int) $this->hotfix_setting->get("db_hotfixes_".
625 $this->hotfix_version[0]."_".$this->hotfix_version[1]);
626 $this->hotfix_file_version = $this->readHotfixFileVersion($this->hotfix_content);
627 }
628 $this->hotfix_info_read = true;
629 }
630
635 {
636 $this->readHotfixInfo();
637 if ($this->hotfix_file_version > $this->hotfix_current_version)
638 {
639 return true;
640 }
641 return false;
642 }
643
647 function applyHotfix()
648 {
649 global $ilCtrlStructureReader, $ilMySQLAbstraction;
650
651 include_once './Services/Database/classes/class.ilMySQLAbstraction.php';
652
653 $ilMySQLAbstraction = new ilMySQLAbstraction();
654 $GLOBALS['ilMySQLAbstraction'] = $ilMySQLAbstraction;
655
656 $this->readHotfixInfo(true);
657
658 $f = $this->getHotfixFileVersion();
659 $c = $this->getHotfixCurrentVersion();
660
661 if ($c < $f)
662 {
663 $msg = array();
664 for ($i=($c+1); $i<=$f; $i++)
665 {
666// $this->initStep($i); // nothings happens here
667
668 $this->filecontent = $this->hotfix_content;
669
670 if ($this->applyUpdateNr($i, true) == false)
671 {
672 $msg[] = array(
673 "msg" => "update_error: ".$this->error,
674 "nr" => $i
675 );
676 $this->updateMsg = $msg;
677 return false;
678 }
679 else
680 {
681 $msg[] = array(
682 "msg" => "hotfix_applied",
683 "nr" => $i
684 );
685 }
686 }
687
688 $this->updateMsg = $msg;
689 }
690 else
691 {
692 $this->updateMsg = "no_changes";
693 }
694
695 return $this->loadXMLInfo();
696 }
697
699 {
700 $this->readCustomUpdatesInfo();
701 return $this->custom_updates_current_version;
702 }
703
704 public function setCustomUpdatesCurrentVersion($a_version)
705 {
706 $this->readCustomUpdatesInfo();
707 $this->custom_updates_setting->set('db_version_custom', $a_version);
708 $this->custom_updates_current_version = $a_version;
709 return true;
710 }
711
713 {
714 $this->readCustomUpdatesInfo();
715 return $this->custom_updates_file_version;
716 }
717
718 public function readCustomUpdatesFileVersion($a_file_content)
719 {
720 //go through filecontent and search for last occurence of <#x>
721 reset($a_file_content);
722 $regs = array();
723 foreach ($a_file_content as $row)
724 {
725 if (preg_match("/^<#([0-9]+)>/", $row, $regs))
726 {
727 $version = $regs[1];
728 }
729 }
730
731 return (integer) $version;
732 }
733
734 public function readCustomUpdatesInfo($a_force = false)
735 {
736 if ($this->custom_updates_info_read && !$a_force)
737 {
738 return;
739 }
740 include_once './Services/Administration/classes/class.ilSetting.php';
741
742 $this->custom_updates_setting = new ilSetting();
743 $custom_updates_file = $this->PATH."setup/sql/dbupdate_custom.php";
744 if (is_file($custom_updates_file))
745 {
746 $this->custom_updates_content = @file($custom_updates_file);
747 $this->custom_updates_current_version = (int) $this->custom_updates_setting->get('db_version_custom', 0);
748 $this->custom_updates_file_version = $this->readCustomUpdatesFileVersion($this->custom_updates_content);
749 }
750 $this->custom_updates_info_read = true;
751 }
752
753 public function customUpdatesAvailable()
754 {
755 // trunk does not support custom updates
756// return false;
757
758 $this->readCustomUpdatesInfo();
759 if ($this->custom_updates_file_version > $this->custom_updates_current_version)
760 {
761 return true;
762 }
763 return false;
764 }
765
766 public function applyCustomUpdates()
767 {
768 global $ilCtrlStructureReader, $ilMySQLAbstraction;
769
770 include_once './Services/Database/classes/class.ilMySQLAbstraction.php';
771
772 $ilMySQLAbstraction = new ilMySQLAbstraction();
773 $GLOBALS['ilMySQLAbstraction'] = $ilMySQLAbstraction;
774
775 $this->readCustomUpdatesInfo(true);
776
777 $f = $this->getCustomUpdatesFileVersion();
778 $c = $this->getCustomUpdatesCurrentVersion();
779
780 if ($c < $f)
781 {
782 $msg = array();
783 for ($i=($c+1); $i<=$f; $i++)
784 {
785// $this->initStep($i); // nothings happens here
786
787 $this->filecontent = $this->custom_updates_content;
788
789 if ($this->applyUpdateNr($i, false, true) == false)
790 {
791 $msg[] = array(
792 "msg" => "update_error: ".$this->error,
793 "nr" => $i
794 );
795 $this->updateMsg = $msg;
796 return false;
797 }
798 else
799 {
800 $msg[] = array(
801 "msg" => "custom_update_applied",
802 "nr" => $i
803 );
804 }
805 }
806
807 $this->updateMsg = $msg;
808 }
809 else
810 {
811 $this->updateMsg = "no_changes";
812 }
813
814 return $this->loadXMLInfo();
815 }
816
822 function getUpdateSteps($a_break = 0)
823 {
824 global $ilCtrlStructureReader, $ilMySQLAbstraction;
825
826 $str = "";
827
830
831 if ($a_break > $this->currentVersion &&
832 $a_break < $this->fileVersion)
833 {
834 $f = $a_break;
835 }
836
837 if ($c < $f)
838 {
839 $msg = array();
840 for ($i=($c+1); $i<=$f; $i++)
841 {
842 // check wether next update file must be loaded
843 if ($this->current_file != $this->getFileForStep($i))
844 {
845 $this->DB_UPDATE_FILE = $this->PATH."setup/sql/".$this->getFileForStep($i);
846 $this->readDBUpdateFile();
847 }
848
849 $str.= $this->getUpdateStepNr($i);
850 }
851
852 }
853 return $str;
854 }
855
861 function getHotfixSteps()
862 {
863 $this->readHotfixInfo(true);
864
865 $str = "";
866
867 $f = $this->getHotfixFileVersion();
868 $c = $this->getHotfixCurrentVersion();
869
870 if ($c < $f)
871 {
872 $msg = array();
873 for ($i=($c+1); $i<=$f; $i++)
874 {
875 $this->filecontent = $this->hotfix_content;
876
877 $str.= $this->getUpdateStepNr($i, true);
878 }
879 }
880
881 return $str;
882 }
883
884
888 function getUpdateStepNr($nr, $hotfix = false, $custom_update = false)
889 {
890 global $ilDB,$ilErr,$ilUser,$ilCtrlStructureReader,$ilModuleReader,$ilMySQLAbstraction;
891
892 $str = "";
893
894 //search for desired $nr
895 reset($this->filecontent);
896
897 //init
898 $i = 0;
899
900 //go through filecontent
901 while (!preg_match("/^<#".$nr.">/", $this->filecontent[$i]) && $i<count($this->filecontent))
902 {
903 $i++;
904 }
905
906 //update not found
907 if ($i == count($this->filecontent))
908 {
909 return false;
910 }
911
912 $i++;
913
914 //update found, now extract this update to a new array
915 $update = array();
916 while ($i<count($this->filecontent) && !preg_match("/^<#".($nr+1).">/", $this->filecontent[$i]))
917 {
918 $str.= $this->filecontent[$i];
919 $i++;
920 }
921
922 return "<pre><b><#".$nr."></b>\n".htmlentities($str)."</pre>";
923 }
924
925} // END class.DBUdate
926?>
$error
Definition: Error.php:17
An exception for terminatinating execution or to throw for unit testing.
error($a_errmsg)
set error message @access public
Database Update class.
getUpdateStepNr($nr, $hotfix=false, $custom_update=false)
Get single update step for presentation.
getFileVersion()
Get Version of file.
applyUpdate($a_break=0)
Apply update.
readCustomUpdatesInfo($a_force=false)
$DB_UPDATE_FILE
db update file
getHotfixSteps()
Get hotfix steps.
setCurrentVersion($a_version)
getFileForStep($a_version)
Get db update file name for db step.
getUpdateSteps($a_break=0)
Get update steps as string (for presentation)
setRunningStatus($a_nr)
Set running status for a step.
getCustomUpdatesCurrentVersion()
setHotfixCurrentVersion($a_version)
Set current hotfix version.
execQuery($db, $str)
execute a query
checkQuery($q)
check query
getHotfixCurrentVersion()
Get current hotfix version.
getHotfixFileVersion()
Get current hotfix version.
readHotfixInfo($a_force=false)
Get status of hotfix file.
__construct($a_db_handler=0, $tmp_flag=false)
constructor
readCustomUpdatesFileVersion($a_file_content)
hotfixAvailable()
Get status of hotfix file.
setCustomUpdatesCurrentVersion($a_version)
getTableStatus($table)
applyUpdateNr($nr, $hotfix=false, $custom_update=false)
apply an update
clearRunningStatus()
Clear running status.
initStep($i)
Init Step.
applyHotfix()
Apply hotfix.
getRunningStatus()
Get running status.
readHotfixFileVersion($a_file_content)
Set current hotfix version.
Class ilDatabaseException.
Class ilModuleReader.
static getAvailableCoreModules()
Get all available core modules.
This class includes methods that help to abstract ILIAS 3.10.x MySQL tables for the use with MDB2 abs...
Class ilServiceReader.
static getAvailableCoreServices()
Get all available core services.
ILIAS Setting Class.
$r
Definition: example_031.php:79
$code
Definition: example_050.php:99
$php
Definition: flush.php:22
$GLOBALS['loaded']
Global hash that tracks already loaded includes.
const ILIAS_VERSION_NUMERIC
$ilCtrlStructureReader
global $ilErr
Definition: raiseError.php:16
global $ilDB
$ilUser
Definition: imgupload.php:18