schemaupdater.php 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. <?php
  2. // This file is part of GNU social - https://www.gnu.org/software/social
  3. //
  4. // GNU social is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Affero General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // GNU social is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Affero General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Affero General Public License
  15. // along with GNU social. If not, see <http://www.gnu.org/licenses/>.
  16. /**
  17. * Database schema utilities
  18. *
  19. * @category Database
  20. * @package GNUsocial
  21. * @author Evan Prodromou <evan@status.net>
  22. * @copyright 2009 StatusNet, Inc.
  23. * @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
  24. */
  25. defined('GNUSOCIAL') || die();
  26. class SchemaUpdater
  27. {
  28. public function __construct($schema)
  29. {
  30. $this->schema = $schema;
  31. $this->checksums = $this->getChecksums();
  32. }
  33. /**
  34. * @param string $tableName
  35. * @param array $tableDef
  36. */
  37. public function register($tableName, array $tableDef)
  38. {
  39. // Check if the table we're registering is related to a Managed_DataObject
  40. if (is_a(ucfirst($tableName), 'Managed_DataObject', true)) {
  41. call_user_func("{$tableName}::beforeSchemaUpdate");
  42. }
  43. $this->tables[$tableName] = $tableDef;
  44. }
  45. /**
  46. * Go ping em!
  47. *
  48. * @fixme handle tables that belong on different database servers...?
  49. */
  50. public function checkSchema()
  51. {
  52. $checksums = $this->checksums;
  53. foreach ($this->tables as $table => $def) {
  54. $checksum = $this->checksum($def);
  55. if (empty($checksums[$table])) {
  56. common_log(LOG_DEBUG, "No previous schema_version for $table: updating to $checksum");
  57. } elseif ($checksums[$table] === $checksum) {
  58. common_log(LOG_DEBUG, "Last schema_version for $table up to date: $checksum");
  59. continue;
  60. } else {
  61. common_log(LOG_DEBUG, "Last schema_version for $table is {$checksums[$table]}: updating to $checksum");
  62. }
  63. //$this->conn->query('START TRANSACTION');
  64. $this->schema->ensureTable($table, $def);
  65. $this->saveChecksum($table, $checksum);
  66. //$this->conn->commit();
  67. }
  68. }
  69. /**
  70. * Calculate a checksum for this table definition array.
  71. *
  72. * @param array $def
  73. * @return string
  74. */
  75. public function checksum(array $def)
  76. {
  77. $flat = serialize($def);
  78. return hash('sha3-256', $flat);
  79. }
  80. /**
  81. * Pull all known table checksums into an array for easy lookup.
  82. *
  83. * @return array: associative array of table names to checksum strings
  84. */
  85. protected function getChecksums()
  86. {
  87. $checksums = array();
  88. try {
  89. $sv = new Schema_version();
  90. $sv->find();
  91. while ($sv->fetch()) {
  92. $checksums[$sv->table_name] = $sv->checksum;
  93. }
  94. return $checksums;
  95. } catch (Exception $e) {
  96. // no dice!
  97. common_log(LOG_DEBUG, "Possibly schema_version table doesn't exist yet.");
  98. }
  99. return $checksums;
  100. }
  101. /**
  102. * Save or update current available checksums.
  103. *
  104. * @param string $table
  105. * @param string $checksum
  106. */
  107. protected function saveChecksum($table, $checksum)
  108. {
  109. try {
  110. $sv = new Schema_version();
  111. $sv->table_name = $table;
  112. $sv->checksum = $checksum;
  113. $sv->modified = common_sql_now();
  114. if (isset($this->checksums[$table])) {
  115. $sv->update();
  116. } else {
  117. $sv->insert();
  118. }
  119. } catch (Exception $e) {
  120. // no dice!
  121. common_log(LOG_DEBUG, "Possibly schema_version table doesn't exist yet.");
  122. }
  123. $this->checksums[$table] = $checksum;
  124. }
  125. }