[ Index ] |
PHP Cross Reference of Joomla 4.2.2 documentation |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * Joomla! Content Management System 5 * 6 * @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org> 7 * @license GNU General Public License version 2 or later; see LICENSE.txt 8 */ 9 10 namespace Joomla\CMS\Schema; 11 12 use Joomla\CMS\Filesystem\Folder; 13 use Joomla\Database\DatabaseDriver; 14 15 // phpcs:disable PSR1.Files.SideEffects 16 \defined('JPATH_PLATFORM') or die; 17 // phpcs:enable PSR1.Files.SideEffects 18 19 /** 20 * Contains a set of JSchemaChange objects for a particular instance of Joomla. 21 * Each of these objects contains a DDL query that should have been run against 22 * the database when this database was created or updated. This enables the 23 * Installation Manager to check that the current database schema is up to date. 24 * 25 * @since 2.5 26 */ 27 class ChangeSet 28 { 29 /** 30 * Array of ChangeItem objects 31 * 32 * @var ChangeItem[] 33 * @since 2.5 34 */ 35 protected $changeItems = array(); 36 37 /** 38 * DatabaseDriver object 39 * 40 * @var DatabaseDriver 41 * @since 2.5 42 */ 43 protected $db = null; 44 45 /** 46 * Folder where SQL update files will be found 47 * 48 * @var string 49 * @since 2.5 50 */ 51 protected $folder = null; 52 53 /** 54 * The singleton instance of this object 55 * 56 * @var ChangeSet 57 * @since 3.5.1 58 */ 59 protected static $instance; 60 61 /** 62 * Constructor: builds array of $changeItems by processing the .sql files in a folder. 63 * The folder for the Joomla core updates is `administrator/components/com_admin/sql/updates/<database>`. 64 * 65 * @param DatabaseDriver $db The current database object 66 * @param string $folder The full path to the folder containing the update queries 67 * 68 * @since 2.5 69 */ 70 public function __construct($db, $folder = null) 71 { 72 $this->db = $db; 73 $this->folder = $folder; 74 $updateFiles = $this->getUpdateFiles(); 75 76 // If no files were found nothing more we can do - continue 77 if ($updateFiles === false) { 78 return; 79 } 80 81 $updateQueries = $this->getUpdateQueries($updateFiles); 82 83 foreach ($updateQueries as $obj) { 84 $this->changeItems[] = ChangeItem::getInstance($db, $obj->file, $obj->updateQuery); 85 } 86 87 // If on mysql, add a query at the end to check for utf8mb4 conversion status 88 if ($this->db->getServerType() === 'mysql') { 89 // Check if the #__utf8_conversion table exists 90 $this->db->setQuery('SHOW TABLES LIKE ' . $this->db->quote($this->db->getPrefix() . 'utf8_conversion')); 91 92 try { 93 $rows = $this->db->loadRowList(0); 94 95 $tableExists = \count($rows); 96 } catch (\RuntimeException $e) { 97 $tableExists = 0; 98 } 99 100 // If the table exists add a change item for utf8mb4 conversion to the end 101 if ($tableExists > 0) { 102 // Let the update query do nothing 103 $tmpSchemaChangeItem = ChangeItem::getInstance( 104 $db, 105 'database.php', 106 'UPDATE ' . $this->db->quoteName('#__utf8_conversion') 107 . ' SET ' . $this->db->quoteName('converted') . ' = ' 108 . $this->db->quoteName('converted') . ';' 109 ); 110 111 // Set to not skipped 112 $tmpSchemaChangeItem->checkStatus = 0; 113 114 // Set the check query 115 $tmpSchemaChangeItem->queryType = 'UTF8_CONVERSION_UTF8MB4'; 116 117 $tmpSchemaChangeItem->checkQuery = 'SELECT ' 118 . $this->db->quoteName('converted') 119 . ' FROM ' . $this->db->quoteName('#__utf8_conversion') 120 . ' WHERE ' . $this->db->quoteName('converted') . ' = 5'; 121 122 // Set expected records from check query 123 $tmpSchemaChangeItem->checkQueryExpected = 1; 124 125 $tmpSchemaChangeItem->msgElements = array(); 126 127 $this->changeItems[] = $tmpSchemaChangeItem; 128 } 129 } 130 } 131 132 /** 133 * Returns a reference to the ChangeSet object, only creating it if it doesn't already exist. 134 * 135 * @param DatabaseDriver $db The current database object 136 * @param string $folder The full path to the folder containing the update queries 137 * 138 * @return ChangeSet 139 * 140 * @since 2.5 141 */ 142 public static function getInstance($db, $folder = null) 143 { 144 if (!\is_object(static::$instance)) { 145 static::$instance = new static($db, $folder); 146 } 147 148 return static::$instance; 149 } 150 151 /** 152 * Checks the database and returns an array of any errors found. 153 * Note these are not database errors but rather situations where 154 * the current schema is not up to date. 155 * 156 * @return array Array of errors if any. 157 * 158 * @since 2.5 159 */ 160 public function check() 161 { 162 $errors = array(); 163 164 foreach ($this->changeItems as $item) { 165 if ($item->check() === -2) { 166 // Error found 167 $errors[] = $item; 168 } 169 } 170 171 return $errors; 172 } 173 174 /** 175 * Runs the update query to apply the change to the database 176 * 177 * @return void 178 * 179 * @since 2.5 180 */ 181 public function fix() 182 { 183 $this->check(); 184 185 foreach ($this->changeItems as $item) { 186 $item->fix(); 187 } 188 } 189 190 /** 191 * Returns an array of results for this set 192 * 193 * @return array associative array of changeitems grouped by unchecked, ok, error, and skipped 194 * 195 * @since 2.5 196 */ 197 public function getStatus() 198 { 199 $result = array('unchecked' => array(), 'ok' => array(), 'error' => array(), 'skipped' => array()); 200 201 foreach ($this->changeItems as $item) { 202 switch ($item->checkStatus) { 203 case 0: 204 $result['unchecked'][] = $item; 205 break; 206 case 1: 207 $result['ok'][] = $item; 208 break; 209 case -2: 210 $result['error'][] = $item; 211 break; 212 case -1: 213 $result['skipped'][] = $item; 214 break; 215 } 216 } 217 218 return $result; 219 } 220 221 /** 222 * Gets the current database schema, based on the highest version number. 223 * Note that the .sql files are named based on the version and date, so 224 * the file name of the last file should match the database schema version 225 * in the #__schemas table. 226 * 227 * @return string the schema version for the database 228 * 229 * @since 2.5 230 */ 231 public function getSchema() 232 { 233 $updateFiles = $this->getUpdateFiles(); 234 235 // No schema files found - abort and return empty string 236 if (empty($updateFiles)) { 237 return ''; 238 } 239 240 $result = new \SplFileInfo(array_pop($updateFiles)); 241 242 return $result->getBasename('.sql'); 243 } 244 245 /** 246 * Get list of SQL update files for this database 247 * 248 * @return array|boolean list of sql update full-path names. False if directory doesn't exist 249 * 250 * @since 2.5 251 */ 252 private function getUpdateFiles() 253 { 254 // Get the folder from the database name 255 $sqlFolder = $this->db->getServerType(); 256 257 // For `mssql` server types, convert the type to `sqlazure` 258 if ($sqlFolder === 'mssql') { 259 $sqlFolder = 'sqlazure'; 260 } 261 262 // Default folder to core com_admin 263 if (!$this->folder) { 264 $this->folder = JPATH_ADMINISTRATOR . '/components/com_admin/sql/updates/'; 265 } 266 267 // We don't want to enqueue an error if the directory doesn't exist - this can be handled elsewhere/ 268 // So bail here. 269 if (!is_dir($this->folder . '/' . $sqlFolder)) { 270 return []; 271 } 272 273 return Folder::files( 274 $this->folder . '/' . $sqlFolder, 275 '\.sql$', 276 1, 277 true, 278 array('.svn', 'CVS', '.DS_Store', '__MACOSX'), 279 array('^\..*', '.*~'), 280 true 281 ); 282 } 283 284 /** 285 * Get array of SQL queries 286 * 287 * @param array $sqlfiles Array of .sql update filenames. 288 * 289 * @return array Array of \stdClass objects where: 290 * file=filename, 291 * update_query = text of SQL update query 292 * 293 * @since 2.5 294 */ 295 private function getUpdateQueries(array $sqlfiles) 296 { 297 // Hold results as array of objects 298 $result = array(); 299 300 foreach ($sqlfiles as $file) { 301 $buffer = file_get_contents($file); 302 303 // Create an array of queries from the sql file 304 $queries = DatabaseDriver::splitSql($buffer); 305 306 foreach ($queries as $query) { 307 $fileQueries = new \stdClass(); 308 $fileQueries->file = $file; 309 $fileQueries->updateQuery = $query; 310 $result[] = $fileQueries; 311 } 312 } 313 314 return $result; 315 } 316 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Sep 7 05:41:13 2022 | Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer |