ILIAS  release_5-1 Revision 5.0.0-5477-g43f3e3fab5f
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_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
115 function _DBUpdate()
116 {
117 $this->db->disconnect();
118 }
119
121 {
122 if (!file_exists($this->DB_UPDATE_FILE))
123 {
124 $this->error = "no_db_update_file";
125 $this->filecontent = array();
126 return false;
127 }
128
129 $this->filecontent = @file($this->DB_UPDATE_FILE);
130 return true;
131 }
132
134 {
135 if (!file_exists($this->LAST_UPDATE_FILE))
136 {
137 $this->error = "no_last_update_file";
138 $this->lastfilecontent = array();
139 return false;
140 }
141
142 $this->lastfilecontent = @file($this->LAST_UPDATE_FILE);
143 return true;
144 }
145
147 {
148 $GLOBALS["ilDB"] = $this->db;
149 include_once './Services/Administration/classes/class.ilSetting.php';
150 $set = new ilSetting("common", true);
151 $this->currentVersion = (integer) $set->get("db_version");
153 }
154
155 function setCurrentVersion ($a_version)
156 {
157 include_once './Services/Administration/classes/class.ilSetting.php';
158 $set = new ilSetting("common", true);
159 $set->set("db_version", $a_version);
160 $this->currentVersion = $a_version;
161
162 return true;
163 }
164
170 function setRunningStatus($a_nr)
171 {
172 include_once './Services/Administration/classes/class.ilSetting.php';
173 $set = new ilSetting("common", true);
174 $set->set("db_update_running", $a_nr);
175 $this->db_update_running = $a_nr;
176 }
177
184 {
185 include_once './Services/Administration/classes/class.ilSetting.php';
186 $set = new ilSetting("common", true);
187 $this->db_update_running = (integer) $set->get("db_update_running");
188
189 return $this->db_update_running;
190 }
191
196 {
197 include_once './Services/Administration/classes/class.ilSetting.php';
198 $set = new ilSetting("common", true);
199 $set->set("db_update_running", 0);
200 $this->db_update_running = 0;
201 }
202
204 {
205 //go through filecontent and search for last occurence of <#x>
206 reset($this->lastfilecontent);
207 $regs = array();
208 foreach ($this->lastfilecontent as $row)
209 {
210 if (ereg("^<#([0-9]+)>", $row, $regs))
211 {
212 $version = $regs[1];
213 }
214 }
215
216 $this->fileVersion = (integer) $version;
217 return $this->fileVersion;
218 }
219
223 function getFileVersion()
224 {
225 return $this->fileVersion;
226 }
227
234 function execQuery($db,$str)
235 {
236 $sql = explode("\n",trim($str));
237 for ($i=0; $i<count($sql); $i++)
238 {
239 $sql[$i] = trim($sql[$i]);
240 if ($sql[$i] != "" && substr($sql[$i],0,1)!="#")
241 {
242 //take line per line, until last char is ";"
243 if (substr($sql[$i],-1)==";")
244 {
245 //query is complete
246 $q .= " ".substr($sql[$i],0,-1);
247 $check = $this->checkQuery($q);
248 if ($check === true)
249 {
250 $r = $db->query($q);
251 if (MDB2::isError($r))
252 {
253 $this->error = $r->getMessage();
254 return false;
255 }
256 }
257 else
258 {
259 $this->error = $check;
260 return false;
261 }
262 unset($q);
263 } //if
264 else
265 {
266 $q .= " ".$sql[$i];
267 } //else
268 } //if
269 } //for
270 if ($q != "")
271 {
272 echo "incomplete_statement: ".$q."<br>";
273 return false;
274 }
275 return true;
276 }
277
281 function checkQuery($q)
282 {
283 return true;
284 }
285
289 function applyUpdate($a_break = 0)
290 {
291 global $ilCtrlStructureReader, $ilMySQLAbstraction;
292
293 include_once './Services/Database/classes/class.ilMySQLAbstraction.php';
294
295 $ilMySQLAbstraction = new ilMySQLAbstraction();
296 $GLOBALS['ilMySQLAbstraction'] = $ilMySQLAbstraction;
297
300
301 if ($a_break > $this->currentVersion &&
302 $a_break < $this->fileVersion)
303 {
304 $f = $a_break;
305 }
306
307 if ($c < $f)
308 {
309 $msg = array();
310 for ($i=($c+1); $i<=$f; $i++)
311 {
312 // check wether next update file must be loaded
313 if ($this->current_file != $this->getFileForStep($i))
314 {
315 $this->DB_UPDATE_FILE = $this->PATH."setup/sql/".$this->getFileForStep($i);
316 $this->readDBUpdateFile();
317 }
318
319 $this->initStep($i);
320
321 if ($this->applyUpdateNr($i) == false)
322 {
323 $msg[] = array(
324 "msg" => "update_error: ".$this->error,
325 "nr" => $i
326 );
327 $this->updateMsg = $msg;
328 return false;
329 }
330 else
331 {
332 $msg[] = array(
333 "msg" => "update_applied",
334 "nr" => $i
335 );
336 }
337 }
338
339 $this->updateMsg = $msg;
340 }
341 else
342 {
343 $this->updateMsg = "no_changes";
344 }
345
346 if ($f < $this->fileVersion)
347 {
348 return true;
349 }
350 else
351 {
352 return $this->loadXMLInfo();
353 }
354 }
355
356 function loadXMLInfo()
357 {
359
360 // read module and service information into db
361 require_once "./setup/classes/class.ilModuleReader.php";
362 require_once "./setup/classes/class.ilServiceReader.php";
363 require_once "./setup/classes/class.ilCtrlStructureReader.php";
364
365 require_once "./Services/Component/classes/class.ilModule.php";
366 require_once "./Services/Component/classes/class.ilService.php";
369
370 $mr = new ilModuleReader("", "", "");
371 $mr->clearTables();
372 foreach($modules as $module)
373 {
374 $mr = new ilModuleReader(ILIAS_ABSOLUTE_PATH."/Modules/".$module["subdir"]."/module.xml",
375 $module["subdir"], "Modules");
376 $mr->getModules();
377 unset($mr);
378 }
379
380 $sr = new ilServiceReader("", "", "");
381 $sr->clearTables();
382 foreach($services as $service)
383 {
384 $sr = new ilServiceReader(ILIAS_ABSOLUTE_PATH."/Services/".$service["subdir"]."/service.xml",
385 $service["subdir"], "Services");
386 $sr->getServices();
387 unset($sr);
388 }
389
390 $ilCtrlStructureReader->readStructure();
391
392 return true;
393 }
394
401 function applyUpdateNr($nr, $hotfix = false, $custom_update = false)
402 {
403 global $ilDB,$ilErr,$ilUser,$ilCtrlStructureReader,$ilModuleReader,$ilMySQLAbstraction;
404
405 //search for desired $nr
406 reset($this->filecontent);
407
408 if (!$hotfix && !$custom_update)
409 {
410 $this->setRunningStatus($nr);
411 }
412
413 //init
414 $i = 0;
415
416 //go through filecontent
417 while (!ereg("^<#".$nr.">", $this->filecontent[$i]) && $i<count($this->filecontent))
418 {
419 $i++;
420 }
421
422 //update not found
423 if ($i == count($this->filecontent))
424 {
425 $this->error = "update_not_found";
426 return false;
427 }
428
429 $i++;
430
431 //update found, now extract this update to a new array
432 $update = array();
433 while ($i<count($this->filecontent) && !ereg("^<#".($nr+1).">", $this->filecontent[$i]))
434 {
435 $update[] = trim($this->filecontent[$i]);
436 $i++;
437 }
438
439 //now you have the update, now process it
440 $sql = array();
441 $php = array();
442 $mode = "sql";
443
444 foreach ($update as $row)
445 {
446 if (ereg("<\?php", $row))
447 {
448 if (count($sql)>0)
449 {
450 if ($this->execQuery($this->db, implode("\n", $sql)) == false)
451 {
452 $this->error = $this->error;
453 return false;
454 }
455 $sql = array();
456 }
457 $mode = "php";
458 }
459 elseif (ereg("\?>", $row))
460 {
461 if (count($php)>0)
462 {
463 $code = implode("\n", $php);
464 if (eval($code) === false)
465 {
466 $this->error = "Parse error: ".$code;
467 return false;
468 }
469 $php = array();
470 }
471 $mode = "sql";
472
473 }
474 else
475 {
476 if ($mode == "sql")
477 {
478 $sql[] = $row;
479 }
480
481 if ($mode == "php")
482 {
483 $php[] = $row;
484 }
485 } //else
486 } //foreach
487
488 if ($mode == "sql" && count($sql) > 0)
489 {
490 if ($this->execQuery($this->db, implode("\n", $sql)) == false)
491 {
492 $this->error = "dump_error: ".$this->error;
493 return false;
494 }
495 }
496
497 //increase db_Version number
498 if (!$hotfix && !$custom_update)
499 {
500 $this->setCurrentVersion($nr);
501 }
502 elseif($hotfix)
503 {
504 $this->setHotfixCurrentVersion($nr);
505 }
506 elseif($custom_update)
507 {
509 }
510
511 if (!$hotfix && !$custom_update)
512 {
513 $this->clearRunningStatus();
514 }
515 //$this->currentVersion = $ilias->getSetting("db_version");
516
517 return true;
518
519 }
520
522 {
523 if ($this->fileVersion > $this->currentVersion)
524 return false;
525 else
526 return true;
527 }
528
529 function getTables()
530 {
531 $a = array();
532
533 $query = "SHOW TABLES";
534 $res = $this->db->query($query);
535 while ($row = $res->fetchRow())
536 {
537 $status = $this->getTableStatus($row[0]);
538 $a[] = array(
539 "name" => $status["Table"],
540 "table" => $row[0],
541 "status" => $status["Msg_text"]
542 );
543 }
544 return $a;
545 }
546
547 function getTableStatus($table)
548 {
549 $a = array();
550
551 $query = "ANALYZE TABLE ".$table;
552 $res = $this->db->query($query);
553 $row = $res->fetchRow(DB_FETCHMODE_ASSOC);
554 return $row;
555 }
556
557 function optimizeTables($tables)
558 {
559 $msg = array();
560 foreach ($_POST["tables"] as $key => $value)
561 {
562 $query = "OPTIMIZE TABLE ".$key;
563 $res = $this->db->query($query);
564 $msg[] = "table $key: ok";
565 }
566 return $msg;
567 }
568
572
573
578 {
579 $this->readHotfixInfo();
580 return $this->hotfix_current_version;
581 }
582
586 function setHotfixCurrentVersion($a_version)
587 {
588 $this->readHotfixInfo();
589 $this->hotfix_setting->set("db_hotfixes_".
590 $this->hotfix_version[0]."_".$this->hotfix_version[1], $a_version);
591 $this->hotfix_current_version = $a_version;
592 return true;
593 }
594
599 {
600 $this->readHotfixInfo();
601 return $this->hotfix_file_version;
602 }
603
607 function readHotfixFileVersion($a_file_content)
608 {
609 //go through filecontent and search for last occurence of <#x>
610 reset($a_file_content);
611 $regs = array();
612 foreach ($a_file_content as $row)
613 {
614 if (ereg("^<#([0-9]+)>", $row, $regs))
615 {
616 $version = $regs[1];
617 }
618 }
619
620 return (integer) $version;
621 }
622
626 function readHotfixInfo($a_force = false)
627 {
628 if ($this->hotfix_info_read && !$a_force)
629 {
630 return;
631 }
632 include_once './Services/Administration/classes/class.ilSetting.php';
633 $GLOBALS["ilDB"] = $this->db;
634 $this->hotfix_setting = new ilSetting("common", true);
635 $ilias_version = ILIAS_VERSION_NUMERIC;
636 $version_array = explode(".", $ilias_version);
637 $this->hotfix_version[0] = $version_array[0];
638 $this->hotfix_version[1] = $version_array[1];
639 $hotfix_file = $this->PATH."setup/sql/".$this->hotfix_version[0]."_".$this->hotfix_version[1]."_hotfixes.php";
640 if (is_file($hotfix_file))
641 {
642 $this->hotfix_content = @file($hotfix_file);
643 $this->hotfix_current_version = (int) $this->hotfix_setting->get("db_hotfixes_".
644 $this->hotfix_version[0]."_".$this->hotfix_version[1]);
645 $this->hotfix_file_version = $this->readHotfixFileVersion($this->hotfix_content);
646 }
647 $this->hotfix_info_read = true;
648 }
649
654 {
655 $this->readHotfixInfo();
656 if ($this->hotfix_file_version > $this->hotfix_current_version)
657 {
658 return true;
659 }
660 return false;
661 }
662
666 function applyHotfix()
667 {
668 global $ilCtrlStructureReader, $ilMySQLAbstraction;
669
670 include_once './Services/Database/classes/class.ilMySQLAbstraction.php';
671
672 $ilMySQLAbstraction = new ilMySQLAbstraction();
673 $GLOBALS['ilMySQLAbstraction'] = $ilMySQLAbstraction;
674
675 $this->readHotfixInfo(true);
676
677 $f = $this->getHotfixFileVersion();
678 $c = $this->getHotfixCurrentVersion();
679
680 if ($c < $f)
681 {
682 $msg = array();
683 for ($i=($c+1); $i<=$f; $i++)
684 {
685// $this->initStep($i); // nothings happens here
686
687 $this->filecontent = $this->hotfix_content;
688
689 if ($this->applyUpdateNr($i, true) == false)
690 {
691 $msg[] = array(
692 "msg" => "update_error: ".$this->error,
693 "nr" => $i
694 );
695 $this->updateMsg = $msg;
696 return false;
697 }
698 else
699 {
700 $msg[] = array(
701 "msg" => "hotfix_applied",
702 "nr" => $i
703 );
704 }
705 }
706
707 $this->updateMsg = $msg;
708 }
709 else
710 {
711 $this->updateMsg = "no_changes";
712 }
713
714 return $this->loadXMLInfo();
715 }
716
718 {
719 $this->readCustomUpdatesInfo();
720 return $this->custom_updates_current_version;
721 }
722
723 public function setCustomUpdatesCurrentVersion($a_version)
724 {
725 $this->readCustomUpdatesInfo();
726 $this->custom_updates_setting->set('db_version_custom', $a_version);
727 $this->custom_updates_current_version = $a_version;
728 return true;
729 }
730
732 {
733 $this->readCustomUpdatesInfo();
734 return $this->custom_updates_file_version;
735 }
736
737 public function readCustomUpdatesFileVersion($a_file_content)
738 {
739 //go through filecontent and search for last occurence of <#x>
740 reset($a_file_content);
741 $regs = array();
742 foreach ($a_file_content as $row)
743 {
744 if (ereg("^<#([0-9]+)>", $row, $regs))
745 {
746 $version = $regs[1];
747 }
748 }
749
750 return (integer) $version;
751 }
752
753 public function readCustomUpdatesInfo($a_force = false)
754 {
755 if ($this->custom_updates_info_read && !$a_force)
756 {
757 return;
758 }
759 include_once './Services/Administration/classes/class.ilSetting.php';
760 $GLOBALS["ilDB"] = $this->db;
761 $this->custom_updates_setting = new ilSetting();
762 $custom_updates_file = $this->PATH."setup/sql/dbupdate_custom.php";
763 if (is_file($custom_updates_file))
764 {
765 $this->custom_updates_content = @file($custom_updates_file);
766 $this->custom_updates_current_version = (int) $this->custom_updates_setting->get('db_version_custom', 0);
767 $this->custom_updates_file_version = $this->readCustomUpdatesFileVersion($this->custom_updates_content);
768 }
769 $this->custom_updates_info_read = true;
770 }
771
772 public function customUpdatesAvailable()
773 {
774 // trunk does not support custom updates
775// return false;
776
777 $this->readCustomUpdatesInfo();
778 if ($this->custom_updates_file_version > $this->custom_updates_current_version)
779 {
780 return true;
781 }
782 return false;
783 }
784
785 public function applyCustomUpdates()
786 {
787 global $ilCtrlStructureReader, $ilMySQLAbstraction;
788
789 include_once './Services/Database/classes/class.ilMySQLAbstraction.php';
790
791 $ilMySQLAbstraction = new ilMySQLAbstraction();
792 $GLOBALS['ilMySQLAbstraction'] = $ilMySQLAbstraction;
793
794 $this->readCustomUpdatesInfo(true);
795
796 $f = $this->getCustomUpdatesFileVersion();
797 $c = $this->getCustomUpdatesCurrentVersion();
798
799 if ($c < $f)
800 {
801 $msg = array();
802 for ($i=($c+1); $i<=$f; $i++)
803 {
804// $this->initStep($i); // nothings happens here
805
806 $this->filecontent = $this->custom_updates_content;
807
808 if ($this->applyUpdateNr($i, false, true) == false)
809 {
810 $msg[] = array(
811 "msg" => "update_error: ".$this->error,
812 "nr" => $i
813 );
814 $this->updateMsg = $msg;
815 return false;
816 }
817 else
818 {
819 $msg[] = array(
820 "msg" => "custom_update_applied",
821 "nr" => $i
822 );
823 }
824 }
825
826 $this->updateMsg = $msg;
827 }
828 else
829 {
830 $this->updateMsg = "no_changes";
831 }
832
833 return $this->loadXMLInfo();
834 }
835
841 function getUpdateSteps($a_break = 0)
842 {
843 global $ilCtrlStructureReader, $ilMySQLAbstraction;
844
845 $str = "";
846
849
850 if ($a_break > $this->currentVersion &&
851 $a_break < $this->fileVersion)
852 {
853 $f = $a_break;
854 }
855
856 if ($c < $f)
857 {
858 $msg = array();
859 for ($i=($c+1); $i<=$f; $i++)
860 {
861 // check wether next update file must be loaded
862 if ($this->current_file != $this->getFileForStep($i))
863 {
864 $this->DB_UPDATE_FILE = $this->PATH."setup/sql/".$this->getFileForStep($i);
865 $this->readDBUpdateFile();
866 }
867
868 $str.= $this->getUpdateStepNr($i);
869 }
870
871 }
872 return $str;
873 }
874
880 function getHotfixSteps()
881 {
882 $this->readHotfixInfo(true);
883
884 $str = "";
885
886 $f = $this->getHotfixFileVersion();
887 $c = $this->getHotfixCurrentVersion();
888
889 if ($c < $f)
890 {
891 $msg = array();
892 for ($i=($c+1); $i<=$f; $i++)
893 {
894 $this->filecontent = $this->hotfix_content;
895
896 $str.= $this->getUpdateStepNr($i, true);
897 }
898 }
899
900 return $str;
901 }
902
903
907 function getUpdateStepNr($nr, $hotfix = false, $custom_update = false)
908 {
909 global $ilDB,$ilErr,$ilUser,$ilCtrlStructureReader,$ilModuleReader,$ilMySQLAbstraction;
910
911 $str = "";
912
913 //search for desired $nr
914 reset($this->filecontent);
915
916 //init
917 $i = 0;
918
919 //go through filecontent
920 while (!ereg("^<#".$nr.">", $this->filecontent[$i]) && $i<count($this->filecontent))
921 {
922 $i++;
923 }
924
925 //update not found
926 if ($i == count($this->filecontent))
927 {
928 return false;
929 }
930
931 $i++;
932
933 //update found, now extract this update to a new array
934 $update = array();
935 while ($i<count($this->filecontent) && !ereg("^<#".($nr+1).">", $this->filecontent[$i]))
936 {
937 $str.= $this->filecontent[$i];
938 $i++;
939 }
940
941 return "<pre><b><#".$nr."></b>\n".htmlentities($str)."</pre>";
942 }
943
944} // END class.DBUdate
945?>
isError($data, $code=null)
Tell whether a value is a MDB2 error.
Definition: MDB2.php:594
const DB_FETCHMODE_ASSOC
Definition: class.ilDB.php:10
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()
optimizeTables($tables)
setHotfixCurrentVersion($a_version)
Set current hotfix version.
execQuery($db, $str)
execute a query
checkQuery($q)
check query
getHotfixCurrentVersion()
Get current hotfix version.
_DBUpdate()
destructor
getHotfixFileVersion()
Get current hotfix version.
readHotfixInfo($a_force=false)
Get status of hotfix file.
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.
ilDBUpdate($a_db_handler=0, $tmp_flag=false)
constructor
initStep($i)
Init Step.
applyHotfix()
Apply hotfix.
getRunningStatus()
Get running status.
readHotfixFileVersion($a_file_content)
Set current hotfix version.
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.
$_POST['username']
Definition: cron.php:12
$r
Definition: example_031.php:79
$code
Definition: example_050.php:99
$GLOBALS['PHPCAS_CLIENT']
This global variable is used by the interface class phpCAS.
Definition: CAS.php:276
const ILIAS_VERSION_NUMERIC
$ilCtrlStructureReader
global $ilDB
global $ilUser
Definition: imgupload.php:15
const ILIAS_ABSOLUTE_PATH