/libraries/cms/schema/changeset.php

https://bitbucket.org/nlabyt/bcf-ball-4eb2 · PHP · 218 lines · 98 code · 17 blank · 103 comment · 7 complexity · 2f47b5195708ff3a6e7dd7ec627bd157 MD5 · raw file

  1. <?php
  2. /**
  3. * @package CMS.Library
  4. * @subpackage Schema
  5. *
  6. * @copyright Copyright (C) 2005 - 2012 Open Source Matters, Inc. All rights reserved.
  7. * @license GNU General Public License version 2 or later; see LICENSE
  8. */
  9. defined('JPATH_PLATFORM') or die;
  10. jimport('joomla.filesystem.file');
  11. jimport('joomla.filesystem.folder');
  12. JLoader::register('JSchemaChangeitem', JPATH_LIBRARIES . '/cms/schema/changeitem.php');
  13. /**
  14. * Contains a set of JSchemaChange objects for a particular instance of Joomla.
  15. * Each of these objects contains a DDL query that should have been run against
  16. * the database when this database was created or updated. This enables the
  17. * Installation Manager to check that the current database schema is up to date.
  18. *
  19. * @package CMS.Library
  20. * @subpackage Schema
  21. * @since 2.5
  22. */
  23. class JSchemaChangeset extends JObject
  24. {
  25. /**
  26. * Array of JSchemaChangeItem objects
  27. *
  28. * @var string
  29. */
  30. protected $changeItems = array();
  31. /**
  32. * JDatabase object
  33. *
  34. * @var string
  35. */
  36. protected $db = null;
  37. /**
  38. * Folder where SQL update files will be found
  39. *
  40. * @var string
  41. */
  42. protected $folder = null;
  43. /**
  44. *
  45. * Constructor: builds array of $changeItems by processing the .sql files in a folder.
  46. * The folder for the Joomla core updates is administrator/components/com_admin/sql/updates/<database>.
  47. *
  48. * @param JDatabase $db The current database object
  49. * @param string $folder The full path to the folder containing the update queries
  50. */
  51. public function __construct($db, $folder = null)
  52. {
  53. $this->db = $db;
  54. $this->folder = $folder;
  55. $updateFiles = $this->getUpdateFiles();
  56. $updateQueries = $this->getUpdateQueries($updateFiles);
  57. foreach ($updateQueries as $obj) {
  58. $this->changeItems[] = JSchemaChangeItem::getInstance($db, $obj->file, $obj->updateQuery);
  59. }
  60. }
  61. /**
  62. *
  63. * Returns the existing JSchemaChangeset object if it exists.
  64. * Otherwise, it creates a new one.
  65. *
  66. * @param JDatabase $db The current database object
  67. * @param string $folder The full path to the folder containing the update queries
  68. *
  69. * @since 2.5
  70. */
  71. public static function getInstance($db, $folder)
  72. {
  73. static $instance;
  74. if (!is_object($instance)) {
  75. $instance = new JSchemaChangeSet($db, $folder);
  76. }
  77. return $instance;
  78. }
  79. /**
  80. * Checks the database and returns an array of any errors found.
  81. * Note these are not database errors but rather situations where
  82. * the current schema is not up to date.
  83. *
  84. * @return array Array of errors if any.
  85. *
  86. * @since 2.5
  87. */
  88. public function check()
  89. {
  90. $errors = array();
  91. foreach ($this->changeItems as $item) {
  92. if ($item->check() === -2) { // error found
  93. $errors[] = $item;
  94. }
  95. }
  96. return $errors;
  97. }
  98. /**
  99. * Runs the update query to apply the change to the database
  100. *
  101. * @since 2.5
  102. */
  103. public function fix()
  104. {
  105. $this->check();
  106. foreach ($this->changeItems as $item) {
  107. $item->fix();
  108. }
  109. }
  110. /**
  111. * Returns an array of results for this set
  112. *
  113. * @return array associative array of changeitems grouped by unchecked, ok, error, and skipped
  114. *
  115. * @since 2.5
  116. */
  117. public function getStatus()
  118. {
  119. $result = array('unchecked' => array(), 'ok' => array(), 'error' => array(), 'skipped' => array());
  120. foreach ($this->changeItems as $item) {
  121. switch ($item->checkStatus) {
  122. case 0:
  123. $result['unchecked'][] = $item;
  124. break;
  125. case 1:
  126. $result['ok'][] = $item;
  127. break;
  128. case -2:
  129. $result['error'][] = $item;
  130. break;
  131. case -1:
  132. $result['skipped'][] = $item;
  133. break;
  134. }
  135. }
  136. return $result;
  137. }
  138. /**
  139. *
  140. * Gets the current database schema, based on the highest version number.
  141. * Note that the .sql files are named based on the version and date, so
  142. * the file name of the last file should match the database schema version
  143. * in the #__schemas table.
  144. *
  145. * @return string the schema version for the database
  146. *
  147. * @since 2.5
  148. */
  149. public function getSchema() {
  150. $updateFiles = $this->getUpdateFiles();
  151. $result = new SplFileInfo(array_pop($updateFiles));
  152. return $result->getBasename('.sql');
  153. }
  154. /**
  155. * Get list of SQL update files for this database
  156. *
  157. * @return array list of sql update full-path names
  158. *
  159. * @since 2.5
  160. */
  161. private function getUpdateFiles() {
  162. // get the folder from the database name
  163. $sqlFolder = $this->db->name;
  164. if (substr($sqlFolder, 0, 5) == 'mysql') {
  165. $sqlFolder = 'mysql';
  166. }
  167. // Default folder to core com_admin
  168. if (!$this->folder) {
  169. $this->folder = JPATH_ADMINISTRATOR.'/components/com_admin/sql/updates/'.$sqlFolder;
  170. }
  171. return JFolder::files($this->folder, '\.sql$', 1, true);
  172. }
  173. /**
  174. * Get array of SQL queries
  175. *
  176. * @param array $sqlfiles Array of .sql update filenames.
  177. *
  178. * @return array Array of stdClass objects where:
  179. * file=filename,
  180. * update_query = text of SQL update query
  181. *
  182. * @since 2.5
  183. */
  184. private function getUpdateQueries(array $sqlfiles) {
  185. $result = array(); // hold results as array of objects
  186. foreach ($sqlfiles as $file) {
  187. $buffer = file_get_contents($file);
  188. // Create an array of queries from the sql file
  189. $queries = $this->db->splitSql($buffer);
  190. foreach ($queries as $query) {
  191. if (trim($query)) {
  192. $fileQueries = new stdClass();
  193. $fileQueries->file = $file;
  194. $fileQueries->updateQuery = $query;
  195. $result[] = $fileQueries;
  196. }
  197. }
  198. }
  199. return $result;
  200. }
  201. }