ILIAS  release_5-3 Revision v5.3.23-19-g915713cf615
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 public function __construct($a_db_handler = 0, $tmp_flag = false)
35 {
36 // workaround to allow setup migration
37 if ($a_db_handler) {
38 $this->db =&$a_db_handler;
39
40 if ($tmp_flag) {
41 $this->PATH = "./";
42 } else {
43 $this->PATH = "./";
44 //$this->PATH = "../";
45 }
46 } else {
47 global $mySetup;
48 $this->db = $mySetup->db;
49 $this->PATH = "./";
50 }
51
52 $this->getCurrentVersion();
53
54 // get update file for current version
55 $updatefile = $this->getFileForStep($this->currentVersion + 1);
56
57 $this->current_file = $updatefile;
58 $this->DB_UPDATE_FILE = $this->PATH . "setup/sql/" . $updatefile;
59
60 //
61 // NOTE: IF YOU SET THIS TO THE NEWEST FILE, CHANGE ALSO getFileForStep()
62 //
63 $this->LAST_UPDATE_FILE = $this->PATH . "setup/sql/dbupdate_04.php";
64
65 $this->readDBUpdateFile();
66 $this->readLastUpdateFile();
67 $this->readFileVersion();
68 }
69
73 public function getFileForStep($a_version)
74 {
75 //
76 // NOTE: IF YOU ADD A NEW FILE HERE, CHANGE ALSO THE CONSTRUCTOR
77 //
78 if ((int) $a_version > 4182) { // last number in previous file
79 return "dbupdate_04.php";
80 } elseif ((int) $a_version > 2948) { // last number in previous file
81 return "dbupdate_03.php";
82 } elseif ((int) $a_version > 864) { // last number in previous file
83 return "dbupdate_02.php";
84 } else {
85 return "dbupdate.php";
86 }
87 }
88
92 public function initStep($i)
93 {
94 //
95 }
96
97
98 public function readDBUpdateFile()
99 {
100 if (!file_exists($this->DB_UPDATE_FILE)) {
101 $this->error = "no_db_update_file";
102 $this->filecontent = array();
103 return false;
104 }
105
106 $this->filecontent = @file($this->DB_UPDATE_FILE);
107 return true;
108 }
109
110 public function readLastUpdateFile()
111 {
112 if (!file_exists($this->LAST_UPDATE_FILE)) {
113 $this->error = "no_last_update_file";
114 $this->lastfilecontent = array();
115 return false;
116 }
117
118 $this->lastfilecontent = @file($this->LAST_UPDATE_FILE);
119 return true;
120 }
121
122 public function getCurrentVersion()
123 {
124 include_once './Services/Administration/classes/class.ilSetting.php';
125 $set = new ilSetting("common", true);
126 $this->currentVersion = (integer) $set->get("db_version");
128 }
129
130 public function setCurrentVersion($a_version)
131 {
132 include_once './Services/Administration/classes/class.ilSetting.php';
133 $set = new ilSetting("common", true);
134 $set->set("db_version", $a_version);
135 $this->currentVersion = $a_version;
136
137 return true;
138 }
139
145 public function setRunningStatus($a_nr)
146 {
147 include_once './Services/Administration/classes/class.ilSetting.php';
148 $set = new ilSetting("common", true);
149 $set->set("db_update_running", $a_nr);
150 $this->db_update_running = $a_nr;
151 }
152
158 public function getRunningStatus()
159 {
160 include_once './Services/Administration/classes/class.ilSetting.php';
161 $set = new ilSetting("common", true);
162 $this->db_update_running = (integer) $set->get("db_update_running");
163
164 return $this->db_update_running;
165 }
166
170 public function clearRunningStatus()
171 {
172 include_once './Services/Administration/classes/class.ilSetting.php';
173 $set = new ilSetting("common", true);
174 $set->set("db_update_running", 0);
175 $this->db_update_running = 0;
176 }
177
178 public function readFileVersion()
179 {
180 //go through filecontent and search for last occurence of <#x>
181 reset($this->lastfilecontent);
182 $regs = array();
183 foreach ($this->lastfilecontent as $row) {
184 if (preg_match('/^<\#([0-9]+)>/', $row, $regs)) {
185 $version = $regs[1];
186 }
187 }
188
189 $this->fileVersion = (integer) $version;
190 return $this->fileVersion;
191 }
192
196 public function getFileVersion()
197 {
198 return $this->fileVersion;
199 }
200
207 public function execQuery($db, $str)
208 {
209 $sql = explode("\n", trim($str));
210 for ($i=0; $i<count($sql); $i++) {
211 $sql[$i] = trim($sql[$i]);
212 if ($sql[$i] != "" && substr($sql[$i], 0, 1)!="#") {
213 //take line per line, until last char is ";"
214 if (substr($sql[$i], -1)==";") {
215 //query is complete
216 $q .= " " . substr($sql[$i], 0, -1);
217 $check = $this->checkQuery($q);
218 if ($check === true) {
219 try {
220 $r = $db->query($q);
221 } catch (ilDatabaseException $e) {
222 var_dump($e); // FSX
223 exit;
224 $this->error = $e->getMessage();
225
226 return false;
227 }
228 } else {
229 $this->error = $check;
230 return false;
231 }
232 unset($q);
233 } //if
234 else {
235 $q .= " " . $sql[$i];
236 } //else
237 } //if
238 } //for
239 if ($q != "") {
240 echo "incomplete_statement: " . $q . "<br>";
241 return false;
242 }
243 return true;
244 }
245
249 public function checkQuery($q)
250 {
251 return true;
252 }
253
257 public function applyUpdate($a_break = 0)
258 {
259 global $ilCtrlStructureReader, $ilMySQLAbstraction;
260
261 include_once './Services/Database/classes/class.ilMySQLAbstraction.php';
262
263 $ilMySQLAbstraction = new ilMySQLAbstraction();
264 $GLOBALS['ilMySQLAbstraction'] = $ilMySQLAbstraction;
265
268
269 if ($a_break > $this->currentVersion &&
270 $a_break < $this->fileVersion) {
271 $f = $a_break;
272 }
273
274 if ($c < $f) {
275 $msg = array();
276 for ($i=($c+1); $i<=$f; $i++) {
277 // check wether next update file must be loaded
278 if ($this->current_file != $this->getFileForStep($i)) {
279 $this->DB_UPDATE_FILE = $this->PATH . "setup/sql/" . $this->getFileForStep($i);
280 $this->readDBUpdateFile();
281 }
282
283 $this->initStep($i);
284
285 if ($this->applyUpdateNr($i) == false) {
286 $msg[] = array(
287 "msg" => "update_error: " . $this->error,
288 "nr" => $i
289 );
290 $this->updateMsg = $msg;
291 return false;
292 } else {
293 $msg[] = array(
294 "msg" => "update_applied",
295 "nr" => $i
296 );
297 }
298 }
299
300 $this->updateMsg = $msg;
301 } else {
302 $this->updateMsg = "no_changes";
303 }
304
305 if ($f < $this->fileVersion) {
306 return true;
307 } else {
308 return $this->loadXMLInfo();
309 }
310 }
311
312 public function loadXMLInfo()
313 {
315
316 // read module and service information into db
317 require_once "./setup/classes/class.ilModuleReader.php";
318 require_once "./setup/classes/class.ilServiceReader.php";
319 require_once "./setup/classes/class.ilCtrlStructureReader.php";
320
321 require_once "./Services/Component/classes/class.ilModule.php";
322 require_once "./Services/Component/classes/class.ilService.php";
325
326 $mr = new ilModuleReader("", "", "");
327 $mr->clearTables();
328 foreach ($modules as $module) {
329 $mr = new ilModuleReader(
330 ILIAS_ABSOLUTE_PATH . "/Modules/" . $module["subdir"] . "/module.xml",
331 $module["subdir"],
332 "Modules"
333 );
334 $mr->getModules();
335 unset($mr);
336 }
337
338 $sr = new ilServiceReader("", "", "");
339 $sr->clearTables();
340 foreach ($services as $service) {
341 $sr = new ilServiceReader(
342 ILIAS_ABSOLUTE_PATH . "/Services/" . $service["subdir"] . "/service.xml",
343 $service["subdir"],
344 "Services"
345 );
346 $sr->getServices();
347 unset($sr);
348 }
349
350 $ilCtrlStructureReader->readStructure();
351
352 return true;
353 }
354
361 public function applyUpdateNr($nr, $hotfix = false, $custom_update = false)
362 {
363 global $ilDB,$ilErr,$ilUser,$ilCtrlStructureReader,$ilModuleReader,$ilMySQLAbstraction;
364
365 //search for desired $nr
366 reset($this->filecontent);
367
368 if (!$hotfix && !$custom_update) {
369 $this->setRunningStatus($nr);
370 }
371
372 //init
373 $i = 0;
374
375 //go through filecontent
376 while (!preg_match("/^<\#" . $nr . ">/", $this->filecontent[$i]) && $i<count($this->filecontent)) {
377 $i++;
378 }
379
380 //update not found
381 if ($i == count($this->filecontent)) {
382 $this->error = "update_not_found";
383 return false;
384 }
385
386 $i++;
387
388 //update found, now extract this update to a new array
389 $update = array();
390 while ($i<count($this->filecontent) && !preg_match("/^<#" . ($nr+1) . ">/", $this->filecontent[$i])) {
391 $update[] = trim($this->filecontent[$i]);
392 $i++;
393 }
394
395 //now you have the update, now process it
396 $sql = array();
397 $php = array();
398 $mode = "sql";
399
400 foreach ($update as $row) {
401 if (preg_match("/<\?php/", $row)) {
402 if (count($sql)>0) {
403 if ($this->execQuery($this->db, implode("\n", $sql)) == false) {
404 $this->error = $this->error;
405 return false;
406 }
407 $sql = array();
408 }
409 $mode = "php";
410 } elseif (preg_match("/\?>/", $row)) {
411 if (count($php)>0) {
412 $code = implode("\n", $php);
413 if (eval($code) === false) {
414 $this->error = "Parse error: " . $code;
415 return false;
416 }
417 $php = array();
418 }
419 $mode = "sql";
420 } else {
421 if ($mode == "sql") {
422 $sql[] = $row;
423 }
424
425 if ($mode == "php") {
426 $php[] = $row;
427 }
428 } //else
429 } //foreach
430
431 if ($mode == "sql" && count($sql) > 0) {
432 if ($this->execQuery($this->db, implode("\n", $sql)) == false) {
433 $this->error = "dump_error: " . $this->error;
434 return false;
435 }
436 }
437
438 //increase db_Version number
439 if (!$hotfix && !$custom_update) {
440 $this->setCurrentVersion($nr);
441 } elseif ($hotfix) {
442 $this->setHotfixCurrentVersion($nr);
443 } elseif ($custom_update) {
445 }
446
447 if (!$hotfix && !$custom_update) {
448 $this->clearRunningStatus();
449 }
450 //$this->currentVersion = $ilias->getSetting("db_version");
451
452 return true;
453 }
454
455 public function getDBVersionStatus()
456 {
457 if ($this->fileVersion > $this->currentVersion) {
458 return false;
459 } else {
460 return true;
461 }
462 }
463
464 public function getTables()
465 {
466 $a = array();
467
468 $query = "SHOW TABLES";
469 $res = $this->db->query($query);
470 while ($row = $res->fetchRow()) {
471 $status = $this->getTableStatus($row[0]);
472 $a[] = array(
473 "name" => $status["Table"],
474 "table" => $row[0],
475 "status" => $status["Msg_text"]
476 );
477 }
478 return $a;
479 }
480
481 public function getTableStatus($table)
482 {
483 $a = array();
484
485 $query = "ANALYZE TABLE " . $table;
486 $res = $this->db->query($query);
488 return $row;
489 }
490
491
495
496
500 public function getHotfixCurrentVersion()
501 {
502 $this->readHotfixInfo();
503 return $this->hotfix_current_version;
504 }
505
509 public function setHotfixCurrentVersion($a_version)
510 {
511 $this->readHotfixInfo();
512 $this->hotfix_setting->set("db_hotfixes_" .
513 $this->hotfix_version[0] . "_" . $this->hotfix_version[1], $a_version);
514 $this->hotfix_current_version = $a_version;
515 return true;
516 }
517
521 public function getHotfixFileVersion()
522 {
523 $this->readHotfixInfo();
524 return $this->hotfix_file_version;
525 }
526
530 public function readHotfixFileVersion($a_file_content)
531 {
532 //go through filecontent and search for last occurence of <#x>
533 reset($a_file_content);
534 $regs = array();
535 foreach ($a_file_content as $row) {
536 if (preg_match("/^<#([0-9]+)>/", $row, $regs)) {
537 $version = $regs[1];
538 }
539 }
540
541 return (integer) $version;
542 }
543
547 public function readHotfixInfo($a_force = false)
548 {
549 if ($this->hotfix_info_read && !$a_force) {
550 return;
551 }
552 include_once './Services/Administration/classes/class.ilSetting.php';
553 $this->hotfix_setting = new ilSetting("common", true);
554 $ilias_version = ILIAS_VERSION_NUMERIC;
555 $version_array = explode(".", $ilias_version);
556 $this->hotfix_version[0] = $version_array[0];
557 $this->hotfix_version[1] = $version_array[1];
558 $hotfix_file = $this->PATH . "setup/sql/" . $this->hotfix_version[0] . "_" . $this->hotfix_version[1] . "_hotfixes.php";
559 if (is_file($hotfix_file)) {
560 $this->hotfix_content = @file($hotfix_file);
561 $this->hotfix_current_version = (int) $this->hotfix_setting->get("db_hotfixes_" .
562 $this->hotfix_version[0] . "_" . $this->hotfix_version[1]);
563 $this->hotfix_file_version = $this->readHotfixFileVersion($this->hotfix_content);
564 }
565 $this->hotfix_info_read = true;
566 }
567
571 public function hotfixAvailable()
572 {
573 $this->readHotfixInfo();
574 if ($this->hotfix_file_version > $this->hotfix_current_version) {
575 return true;
576 }
577 return false;
578 }
579
583 public function applyHotfix()
584 {
585 global $ilCtrlStructureReader, $ilMySQLAbstraction;
586
587 include_once './Services/Database/classes/class.ilMySQLAbstraction.php';
588
589 $ilMySQLAbstraction = new ilMySQLAbstraction();
590 $GLOBALS['ilMySQLAbstraction'] = $ilMySQLAbstraction;
591
592 $this->readHotfixInfo(true);
593
594 $f = $this->getHotfixFileVersion();
595 $c = $this->getHotfixCurrentVersion();
596
597 if ($c < $f) {
598 $msg = array();
599 for ($i=($c+1); $i<=$f; $i++) {
600 // $this->initStep($i); // nothings happens here
601
602 $this->filecontent = $this->hotfix_content;
603
604 if ($this->applyUpdateNr($i, true) == false) {
605 $msg[] = array(
606 "msg" => "update_error: " . $this->error,
607 "nr" => $i
608 );
609 $this->updateMsg = $msg;
610 return false;
611 } else {
612 $msg[] = array(
613 "msg" => "hotfix_applied",
614 "nr" => $i
615 );
616 }
617 }
618
619 $this->updateMsg = $msg;
620 } else {
621 $this->updateMsg = "no_changes";
622 }
623
624 return $this->loadXMLInfo();
625 }
626
628 {
629 $this->readCustomUpdatesInfo();
630 return $this->custom_updates_current_version;
631 }
632
633 public function setCustomUpdatesCurrentVersion($a_version)
634 {
635 $this->readCustomUpdatesInfo();
636 $this->custom_updates_setting->set('db_version_custom', $a_version);
637 $this->custom_updates_current_version = $a_version;
638 return true;
639 }
640
642 {
643 $this->readCustomUpdatesInfo();
644 return $this->custom_updates_file_version;
645 }
646
647 public function readCustomUpdatesFileVersion($a_file_content)
648 {
649 //go through filecontent and search for last occurence of <#x>
650 reset($a_file_content);
651 $regs = array();
652 foreach ($a_file_content as $row) {
653 if (preg_match("/^<#([0-9]+)>/", $row, $regs)) {
654 $version = $regs[1];
655 }
656 }
657
658 return (integer) $version;
659 }
660
661 public function readCustomUpdatesInfo($a_force = false)
662 {
663 if ($this->custom_updates_info_read && !$a_force) {
664 return;
665 }
666 include_once './Services/Administration/classes/class.ilSetting.php';
667
668 $this->custom_updates_setting = new ilSetting();
669 $custom_updates_file = $this->PATH . "setup/sql/dbupdate_custom.php";
670 if (is_file($custom_updates_file)) {
671 $this->custom_updates_content = @file($custom_updates_file);
672 $this->custom_updates_current_version = (int) $this->custom_updates_setting->get('db_version_custom', 0);
673 $this->custom_updates_file_version = $this->readCustomUpdatesFileVersion($this->custom_updates_content);
674 }
675 $this->custom_updates_info_read = true;
676 }
677
678 public function customUpdatesAvailable()
679 {
680 // trunk does not support custom updates
681 // return false;
682
683 $this->readCustomUpdatesInfo();
684 if ($this->custom_updates_file_version > $this->custom_updates_current_version) {
685 return true;
686 }
687 return false;
688 }
689
690 public function applyCustomUpdates()
691 {
692 global $ilCtrlStructureReader, $ilMySQLAbstraction;
693
694 include_once './Services/Database/classes/class.ilMySQLAbstraction.php';
695
696 $ilMySQLAbstraction = new ilMySQLAbstraction();
697 $GLOBALS['ilMySQLAbstraction'] = $ilMySQLAbstraction;
698
699 $this->readCustomUpdatesInfo(true);
700
701 $f = $this->getCustomUpdatesFileVersion();
702 $c = $this->getCustomUpdatesCurrentVersion();
703
704 if ($c < $f) {
705 $msg = array();
706 for ($i=($c+1); $i<=$f; $i++) {
707 // $this->initStep($i); // nothings happens here
708
709 $this->filecontent = $this->custom_updates_content;
710
711 if ($this->applyUpdateNr($i, false, true) == false) {
712 $msg[] = array(
713 "msg" => "update_error: " . $this->error,
714 "nr" => $i
715 );
716 $this->updateMsg = $msg;
717 return false;
718 } else {
719 $msg[] = array(
720 "msg" => "custom_update_applied",
721 "nr" => $i
722 );
723 }
724 }
725
726 $this->updateMsg = $msg;
727 } else {
728 $this->updateMsg = "no_changes";
729 }
730
731 return $this->loadXMLInfo();
732 }
733
739 public function getUpdateSteps($a_break = 0)
740 {
741 global $ilCtrlStructureReader, $ilMySQLAbstraction;
742
743 $str = "";
744
747
748 if ($a_break > $this->currentVersion &&
749 $a_break < $this->fileVersion) {
750 $f = $a_break;
751 }
752
753 if ($c < $f) {
754 $msg = array();
755 for ($i=($c+1); $i<=$f; $i++) {
756 // check wether next update file must be loaded
757 if ($this->current_file != $this->getFileForStep($i)) {
758 $this->DB_UPDATE_FILE = $this->PATH . "setup/sql/" . $this->getFileForStep($i);
759 $this->readDBUpdateFile();
760 }
761
762 $str.= $this->getUpdateStepNr($i);
763 }
764 }
765 return $str;
766 }
767
773 public function getHotfixSteps()
774 {
775 $this->readHotfixInfo(true);
776
777 $str = "";
778
779 $f = $this->getHotfixFileVersion();
780 $c = $this->getHotfixCurrentVersion();
781
782 if ($c < $f) {
783 $msg = array();
784 for ($i=($c+1); $i<=$f; $i++) {
785 $this->filecontent = $this->hotfix_content;
786
787 $str.= $this->getUpdateStepNr($i, true);
788 }
789 }
790
791 return $str;
792 }
793
794
798 public function getUpdateStepNr($nr, $hotfix = false, $custom_update = false)
799 {
800 global $ilDB,$ilErr,$ilUser,$ilCtrlStructureReader,$ilModuleReader,$ilMySQLAbstraction;
801
802 $str = "";
803
804 //search for desired $nr
805 reset($this->filecontent);
806
807 //init
808 $i = 0;
809
810 //go through filecontent
811 while (!preg_match("/^<#" . $nr . ">/", $this->filecontent[$i]) && $i<count($this->filecontent)) {
812 $i++;
813 }
814
815 //update not found
816 if ($i == count($this->filecontent)) {
817 return false;
818 }
819
820 $i++;
821
822 //update found, now extract this update to a new array
823 $update = array();
824 while ($i<count($this->filecontent) && !preg_match("/^<#" . ($nr+1) . ">/", $this->filecontent[$i])) {
825 $str.= $this->filecontent[$i];
826 $i++;
827 }
828
829 return "<pre><b><#" . $nr . "></b>\n" . htmlentities($str) . "</pre>";
830 }
831} // END class.DBUdate
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.
$i
Definition: disco.tpl.php:19
$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
$error
Definition: Error.php:17
$service
Definition: login.php:15
if($modEnd===false) $module
Definition: module.php:59
const PATH
Definition: proxy_ylocal.php:8
$query
if(empty($password)) $table
Definition: pwgen.php:24
global $ilErr
Definition: raiseError.php:16
foreach($_POST as $key=> $value) $res
global $ilDB
$ilUser
Definition: imgupload.php:18