Upgrader.php 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. <?php
  2. class Upgrader {
  3. public static function upgraderRoot() {
  4. return UOJContext::documentRoot().'/app/upgrade';
  5. }
  6. public static function runSQL($filename) {
  7. passthru('mysql '.escapeshellarg(UOJConfig::$data['database']['database'])
  8. .' -u '.escapeshellarg(UOJConfig::$data['database']['username'])
  9. .' --password='.escapeshellarg(UOJConfig::$data['database']['password'])
  10. .'<'.escapeshellarg($filename), $ret);
  11. if ($ret !== 0) {
  12. die("run sql failed: ".HTML::escape($filename)."\n");
  13. }
  14. }
  15. public static function runShell($cmd) {
  16. passthru("$cmd", $ret);
  17. if ($ret !== 0) {
  18. die("run shell failed: ".HTML::escape($cmd)."\n");
  19. }
  20. }
  21. public static function transaction($fun) {
  22. if (!DB::checkTableExists('upgrades')) {
  23. self::runSQL(self::upgraderRoot().'/create_table_upgrades.sql');
  24. echo "table upgrades created.\n";
  25. }
  26. DB::query('LOCK TABLES upgrades WRITE');
  27. $fun();
  28. DB::query('UNLOCK TABLES');
  29. }
  30. public static function getStatus($name) {
  31. $u = DB::selectFirst("select * from upgrades where name = '".DB::escape($name)."'");
  32. if ($u) {
  33. return $u['status'];
  34. } else {
  35. return 'down';
  36. }
  37. }
  38. public static function upgrade($name, $type) {
  39. if ($type != 'up' && $type != 'down') {
  40. die("invalid upgrade type\n");
  41. }
  42. echo $type.' '.HTML::escape($name).': ';
  43. $dir = self::upgraderRoot().'/'.$name;
  44. if (!is_dir($dir)) {
  45. die("invalid upgrade name\n");
  46. }
  47. if (self::getStatus($name) == $type) {
  48. echo "OK\n";
  49. return;
  50. }
  51. if (is_file($dir.'/upgrade.php')) {
  52. $fun = include $dir.'/upgrade.php';
  53. $fun($type);
  54. }
  55. if (is_file($dir.'/'.$type.'.sql')) {
  56. self::runSQL($dir.'/'.$type.'.sql');
  57. }
  58. if (is_file($dir.'/upgrade.sh')) {
  59. self::runShell('/bin/bash'.' '.escapeshellarg($dir.'/upgrade.sh').' '.$type);
  60. }
  61. DB::insert("insert into upgrades (name, status, updated_at) values ('".DB::escape($name)."', '$type', now()) on duplicate key update status = '$type', updated_at = now()");
  62. echo "DONE\n";
  63. }
  64. public static function up($name) {
  65. self::upgrade($name, 'up');
  66. }
  67. public static function down($name) {
  68. self::upgrade($name, 'down');
  69. }
  70. public static function refresh($name) {
  71. self::upgrade($name, 'down');
  72. self::upgrade($name, 'up');
  73. }
  74. public static function remove($name) {
  75. self::upgrade($name, 'down');
  76. DB::delete("delete from upgrades where name = '".DB::escape($name)."'");
  77. }
  78. public static function removeAll() {
  79. $names = [];
  80. foreach (DB::selectAll("select * from upgrades") as $u) {
  81. $names[] = $u['name'];
  82. }
  83. natsort($names);
  84. foreach (array_reverse($names) as $name) {
  85. self::upgrade($name, 'down');
  86. }
  87. DB::delete("delete from upgrades");
  88. }
  89. public static function upgradeToLatest() {
  90. $names = array_filter(scandir(self::upgraderRoot()), function ($name) {
  91. return is_dir(self::upgraderRoot().'/'.$name) && preg_match('/^\d+_[a-zA-Z_]+$/', $name);
  92. });
  93. natsort($names);
  94. $names_table = [];
  95. foreach ($names as $name) {
  96. $names_table[$name] = true;
  97. }
  98. $dres = DB::selectAll("select * from upgrades");
  99. foreach ($dres as $u) {
  100. if (!isset($names_table[$u['name']])) {
  101. die('missing: '.HTML::escape($name)."\n");
  102. }
  103. }
  104. foreach ($names as $name) {
  105. self::up($name);
  106. }
  107. }
  108. }