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 
29  public $fileVersion;
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");
127  return $this->currentVersion;
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 
266  $f = $this->fileVersion;
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  {
314  global $ilCtrlStructureReader;
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) {
444  $this->setCustomUpdatesCurrentVersion($nr);
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 
641  public function getCustomUpdatesFileVersion()
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 
745  $f = $this->fileVersion;
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
global $ilErr
Definition: raiseError.php:16
getFileForStep($a_version)
Get db update file name for db step.
This class includes methods that help to abstract ILIAS 3.10.x MySQL tables for the use with MDB2 abs...
const ILIAS_VERSION_NUMERIC
setRunningStatus($a_nr)
Set running status for a step.
getHotfixSteps()
Get hotfix steps.
$code
Definition: example_050.php:99
$DB_UPDATE_FILE
db update file
Class ilServiceReader.
$GLOBALS['loaded']
Global hash that tracks already loaded includes.
$ilCtrlStructureReader
setCustomUpdatesCurrentVersion($a_version)
getHotfixFileVersion()
Get current hotfix version.
applyHotfix()
Apply hotfix.
$service
Definition: login.php:15
applyUpdateNr($nr, $hotfix=false, $custom_update=false)
apply an update
const PATH
Definition: proxy_ylocal.php:8
Class ilDatabaseException.
if($modEnd===false) $module
Definition: module.php:59
getTableStatus($table)
readHotfixInfo($a_force=false)
Get status of hotfix file.
$error
Definition: Error.php:17
$r
Definition: example_031.php:79
initStep($i)
Init Step.
execQuery($db, $str)
execute a query
foreach($_POST as $key=> $value) $res
setHotfixCurrentVersion($a_version)
Set current hotfix version.
readCustomUpdatesFileVersion($a_file_content)
static getAvailableCoreServices()
Get all available core services.
__construct($a_db_handler=0, $tmp_flag=false)
constructor
getHotfixCurrentVersion()
Get current hotfix version.
$ilUser
Definition: imgupload.php:18
Reload workbook from saved file
getUpdateStepNr($nr, $hotfix=false, $custom_update=false)
Get single update step for presentation.
readHotfixFileVersion($a_file_content)
Set current hotfix version.
$query
checkQuery($q)
check query
Database Update class.
Create styles array
The data for the language used.
getFileVersion()
Get Version of file.
readCustomUpdatesInfo($a_force=false)
setCurrentVersion($a_version)
getUpdateSteps($a_break=0)
Get update steps as string (for presentation)
hotfixAvailable()
Get status of hotfix file.
global $ilDB
$i
Definition: disco.tpl.php:19
getRunningStatus()
Get running status.
getCustomUpdatesCurrentVersion()
if(empty($password)) $table
Definition: pwgen.php:24
clearRunningStatus()
Clear running status.
Class ilModuleReader.
applyUpdate($a_break=0)
Apply update.
$php
Definition: flush.php:22
static getAvailableCoreModules()
Get all available core modules.