| [ Index ] |
PHP Cross Reference of Joomla 2.5.4 DE |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * @package Joomla.Installation 4 * @copyright Copyright (C) 2005 - 2012 Open Source Matters, Inc. All rights reserved. 5 * @license GNU General Public License version 2 or later; see LICENSE.txt 6 */ 7 8 defined('_JEXEC') or die; 9 10 jimport('joomla.application.component.model'); 11 jimport('joomla.filesystem.file'); 12 require_once JPATH_INSTALLATION.'/helpers/database.php'; 13 14 /** 15 * Database configuration model for the Joomla Core Installer. 16 * 17 * @package Joomla.Installation 18 * @since 1.6 19 */ 20 class JInstallationModelDatabase extends JModel 21 { 22 23 function initialise($options) 24 { 25 // Get the options as a JObject for easier handling. 26 $options = JArrayHelper::toObject($options, 'JObject'); 27 28 // Load the back-end language files so that the DB error messages work 29 $jlang = JFactory::getLanguage(); 30 // Pre-load en-GB in case the chosen language files do not exist 31 $jlang->load('joomla', JPATH_ADMINISTRATOR, 'en-GB', true); 32 // Load the selected language 33 $jlang->load('joomla', JPATH_ADMINISTRATOR, $options->language, true); 34 35 // Ensure a database type was selected. 36 if (empty($options->db_type)) { 37 $this->setError(JText::_('INSTL_DATABASE_INVALID_TYPE')); 38 return false; 39 } 40 41 // Ensure that a valid hostname and user name were input. 42 if (empty($options->db_host) || empty($options->db_user)) { 43 $this->setError(JText::_('INSTL_DATABASE_INVALID_DB_DETAILS')); 44 return false; 45 } 46 47 // Ensure that a database name was input. 48 if (empty($options->db_name)) { 49 $this->setError(JText::_('INSTL_DATABASE_EMPTY_NAME')); 50 return false; 51 } 52 53 // Validate database table prefix. 54 if (!preg_match('#^[a-zA-Z]+[a-zA-Z0-9_]*$#', $options->db_prefix)) { 55 $this->setError(JText::_('INSTL_DATABASE_PREFIX_INVALID_CHARS')); 56 return false; 57 } 58 59 // Validate length of database table prefix. 60 if (strlen($options->db_prefix) > 15) { 61 $this->setError(JText::_('INSTL_DATABASE_FIX_TOO_LONG')); 62 return false; 63 } 64 65 // Validate length of database name. 66 if (strlen($options->db_name) > 64) { 67 $this->setError(JText::_('INSTL_DATABASE_NAME_TOO_LONG')); 68 return false; 69 } 70 71 // If the database is not yet created, create it. 72 if (empty($options->db_created)) { 73 // Get a database object. 74 try 75 { 76 $db = JInstallationHelperDatabase::getDbo($options->db_type, $options->db_host, $options->db_user, $options->db_pass, null, $options->db_prefix, false); 77 } 78 catch (JDatabaseException $e) 79 { 80 $this->setError(JText::sprintf('INSTL_DATABASE_COULD_NOT_CONNECT', $e->getMessage())); 81 return false; 82 } 83 84 // Check database version. 85 $db_version = $db->getVersion(); 86 if (($position = strpos($db_version, '-')) !== false) { 87 $db_version = substr($db_version, 0, $position); 88 } 89 90 if (!version_compare($db_version, '5.0.4', '>=')) { 91 $this->setError(JText::sprintf('INSTL_DATABASE_INVALID_MYSQL_VERSION', $db_version)); 92 return false; 93 } 94 // @internal MySQL versions pre 5.1.6 forbid . / or \ or NULL 95 if ((preg_match('#[\\\/\.\0]#', $options->db_name)) && (!version_compare($db_version, '5.1.6', '>='))) { 96 $this->setError(JText::sprintf('INSTL_DATABASE_INVALID_NAME', $db_version)); 97 return false; 98 } 99 100 // @internal Check for spaces in beginning or end of name 101 if (strlen(trim($options->db_name)) <> strlen($options->db_name)) { 102 $this->setError(JText::_('INSTL_DATABASE_NAME_INVALID_SPACES')); 103 return false; 104 } 105 106 // @internal Check for asc(00) Null in name 107 if (strpos($options->db_name, chr(00)) !== false) { 108 $this->setError(JText::_('INSTL_DATABASE_NAME_INVALID_CHAR')); 109 return false; 110 } 111 112 // Try to select the database 113 try 114 { 115 $db->select($options->db_name); 116 } 117 catch (JDatabaseException $e) 118 { 119 // If the database could not be selected, attempt to create it and then select it. 120 if ($this->createDatabase($db, $options->db_name)) { 121 $db->select($options->db_name); 122 } else { 123 $this->setError(JText::sprintf('INSTL_DATABASE_ERROR_CREATE', $options->db_name)); 124 return false; 125 } 126 } 127 128 // Set the character set to UTF-8 for pre-existing databases. 129 $this->setDatabaseCharset($db, $options->db_name); 130 131 // Should any old database tables be removed or backed up? 132 if ($options->db_old == 'remove') { 133 // Attempt to delete the old database tables. 134 if (!$this->deleteDatabase($db, $options->db_name, $options->db_prefix)) { 135 $this->setError(JText::_('INSTL_DATABASE_ERROR_DELETE')); 136 return false; 137 } 138 } else { 139 // If the database isn't being deleted, back it up. 140 if (!$this->backupDatabase($db, $options->db_name, $options->db_prefix)) { 141 $this->setError(JText::_('INSTL_DATABASE_ERROR_BACKINGUP')); 142 return false; 143 } 144 } 145 146 // Set the appropriate schema script based on UTF-8 support. 147 $type = $options->db_type; 148 if ($type == 'mysqli' || $type == 'mysql') 149 { 150 $schema = 'sql/'.(($type == 'mysqli') ? 'mysql' : $type).'/joomla.sql'; 151 } 152 elseif ($type == 'sqlsrv' || $type == 'sqlazure') 153 { 154 $schema = 'sql/'.(($type == 'sqlsrv') ? 'sqlazure' : $type).'/joomla.sql'; 155 } 156 // Check if the schema is a valid file 157 if (!JFile::exists($schema)) { 158 $this->setError(JText::sprintf('INSTL_ERROR_DB', JText::_('INSTL_DATABASE_NO_SCHEMA'))); 159 return false; 160 } 161 162 // Attempt to import the database schema. 163 if (!$this->populateDatabase($db, $schema)) { 164 $this->setError(JText::sprintf('INSTL_ERROR_DB', $this->getError())); 165 return false; 166 } 167 168 // Attempt to update the table #__schema. 169 $files = JFolder::files(JPATH_ADMINISTRATOR . '/components/com_admin/sql/updates/mysql/', '\.sql$'); 170 if (empty($files)) { 171 $this->setError(JText::_('INSTL_ERROR_INITIALISE_SCHEMA')); 172 return false; 173 } 174 $version = ''; 175 foreach ($files as $file) { 176 if (version_compare($version, JFile::stripExt($file)) <0) { 177 $version = JFile::stripExt($file); 178 } 179 } 180 $query = $db->getQuery(true); 181 $query->insert('#__schemas'); 182 $query->columns( 183 array( 184 $db->quoteName('extension_id'), 185 $db->quoteName('version_id'))); 186 $query->values('700, '. $db->quote($version)) ; 187 $db->setQuery($query); 188 189 try 190 { 191 $db->query(); 192 } 193 catch (JDatabaseException $e) 194 { 195 $this->setError($e->getMessage()); 196 return false; 197 } 198 199 // Attempt to refresh manifest caches 200 $query = $db->getQuery(true); 201 $query->select('*'); 202 $query->from('#__extensions'); 203 $db->setQuery($query); 204 205 try 206 { 207 $extensions = $db->loadObjectList(); 208 } 209 catch (JDatabaseException $e) 210 { 211 $this->setError($e->getMessage()); 212 $return = false; 213 } 214 215 JFactory::$database = $db; 216 $installer = JInstaller::getInstance(); 217 foreach ($extensions as $extension) { 218 if (!$installer->refreshManifestCache($extension->extension_id)) { 219 $this->setError(JText::sprintf('INSTL_DATABASE_COULD_NOT_REFRESH_MANIFEST_CACHE', $extension->name)); 220 return false; 221 } 222 } 223 224 // Load the localise.sql for translating the data in joomla.sql/joomla_backwards.sql 225 $dblocalise = 'sql/'.(($type == 'mysqli') ? 'mysql' : $type).'/localise.sql'; 226 if (JFile::exists($dblocalise)) { 227 if (!$this->populateDatabase($db, $dblocalise)) { 228 $this->setError(JText::sprintf('INSTL_ERROR_DB', $this->getError())); 229 return false; 230 } 231 } 232 $dblocalise_sql = 'sql/'.(($type == 'sqlsrv') ? 'sqlazure' : $type).'/localise.sql'; 233 if (JFile::exists($dblocalise_sql)) { 234 if (!$this->populateDatabase($db, $dblocalise_sql)) { 235 $this->setError(JText::sprintf('INSTL_ERROR_DB', $this->getError())); 236 return false; 237 } 238 } 239 240 // Handle default backend language setting. This feature is available for localized versions of Joomla 1.5. 241 $app = JFactory::getApplication(); 242 $languages = $app->getLocaliseAdmin($db); 243 if (in_array($options->language, $languages['admin']) || in_array($options->language, $languages['site'])) { 244 // Build the language parameters for the language manager. 245 $params = array(); 246 247 // Set default administrator/site language to sample data values: 248 $params['administrator'] = 'en-GB'; 249 $params['site'] = 'en-GB'; 250 251 if (in_array($options->language, $languages['admin'])) { 252 $params['administrator'] = $options->language; 253 } 254 if (in_array($options->language, $languages['site'])) { 255 $params['site'] = $options->language; 256 } 257 $params = json_encode($params); 258 259 // Update the language settings in the language manager. 260 $db->setQuery( 261 'UPDATE '.$db->quoteName('#__extensions') . 262 ' SET '.$db->quoteName('params').' = '.$db->Quote($params) . 263 ' WHERE '.$db->quoteName('element').'=\'com_languages\'' 264 ); 265 266 try 267 { 268 $db->query(); 269 } 270 catch (JDatabaseException $e) 271 { 272 $this->setError($e->getMessage()); 273 $return = false; 274 } 275 } 276 } 277 278 return true; 279 } 280 281 function installSampleData($options) 282 { 283 // Get the options as a JObject for easier handling. 284 $options = JArrayHelper::toObject($options, 'JObject'); 285 286 // Get a database object. 287 try 288 { 289 $db = JInstallationHelperDatabase::getDBO($options->db_type, $options->db_host, $options->db_user, $options->db_pass, $options->db_name, $options->db_prefix); 290 } 291 catch (JDatabaseException $e) 292 { 293 $this->setError(JText::sprintf('INSTL_DATABASE_COULD_NOT_CONNECT', $e->getMessage())); 294 return false; 295 } 296 297 // Build the path to the sample data file. 298 $type = $options->db_type; 299 if ($type == 'mysqli') { 300 $type = 'mysql'; 301 } 302 elseif ($type == 'sqlsrv') { 303 $type = 'sqlazure'; 304 } 305 306 $data = JPATH_INSTALLATION.'/sql/'.$type.'/' . $options->sample_file; 307 308 // Attempt to import the database schema. 309 if (!file_exists($data)) { 310 $this->setError(JText::sprintf('INSTL_DATABASE_FILE_DOES_NOT_EXIST', $data)); 311 return false; 312 } 313 elseif (!$this->populateDatabase($db, $data)) { 314 $this->setError(JText::sprintf('INSTL_ERROR_DB', $this->getError())); 315 return false; 316 } 317 318 return true; 319 } 320 321 /** 322 * Method to backup all tables in a database with a given prefix. 323 * 324 * @param JDatabase &$db JDatabase object. 325 * @param string $name Name of the database to process. 326 * @param string $prefix Database table prefix. 327 * 328 * @return boolean True on success. 329 * @since 1.0 330 */ 331 public function backupDatabase(& $db, $name, $prefix) 332 { 333 // Initialise variables. 334 $return = true; 335 $backup = 'bak_' . $prefix; 336 337 // Get the tables in the database. 338 $tables = $db->getTableList(); 339 if ($tables) { 340 foreach ($tables as $table) 341 { 342 // If the table uses the given prefix, back it up. 343 if (strpos($table, $prefix) === 0) { 344 // Backup table name. 345 $backupTable = str_replace($prefix, $backup, $table); 346 347 // Drop the backup table. 348 try 349 { 350 $db->dropTable($backupTable, true); 351 } 352 catch (JDatabaseException $e) 353 { 354 $this->setError($e->getMessage()); 355 $return = false; 356 } 357 358 // Rename the current table to the backup table. 359 try 360 { 361 $db->renameTable($table, $backupTable, $backup, $prefix); 362 } 363 catch (JDatabaseException $e) 364 { 365 $this->setError($e->getMessage()); 366 $return = false; 367 } 368 } 369 } 370 } 371 372 return $return; 373 } 374 375 /** 376 * Method to create a new database. 377 * 378 * @param JDatabase &$db JDatabase object. 379 * @param string $name Name of the database to create. 380 * 381 * @return boolean True on success. 382 * @since 1.0 383 */ 384 public function createDatabase(& $db, $name) 385 { 386 // Build the create database query. 387 $query = 'CREATE DATABASE '.$db->quoteName($name).' CHARACTER SET `utf8`'; 388 389 // Run the create database query. 390 $db->setQuery($query); 391 392 try 393 { 394 $db->query(); 395 } 396 catch (JDatabaseException $e) 397 { 398 // If an error occurred return false. 399 return false; 400 } 401 402 return true; 403 } 404 405 /** 406 * Method to delete all tables in a database with a given prefix. 407 * 408 * @param JDatabase &$db JDatabase object. 409 * @param string $name Name of the database to process. 410 * @param string $prefix Database table prefix. 411 * 412 * @return boolean True on success. 413 * @since 1.0 414 */ 415 public function deleteDatabase(& $db, $name, $prefix) 416 { 417 // Initialise variables. 418 $return = true; 419 420 // Get the tables in the database. 421 $tables = $db->getTableList(); 422 if ($tables) 423 { 424 foreach ($tables as $table) 425 { 426 // If the table uses the given prefix, drop it. 427 if (strpos($table, $prefix) === 0) { 428 // Drop the table. 429 try 430 { 431 $db->dropTable($table); 432 } 433 catch (JDatabaseException $e) 434 { 435 $this->setError($e->getMessage()); 436 $return = false; 437 } 438 } 439 } 440 } 441 442 return $return; 443 } 444 445 /** 446 * Method to import a database schema from a file. 447 * 448 * @param JDatabase &$db JDatabase object. 449 * @param string $schema Path to the schema file. 450 * 451 * @return boolean True on success. 452 * @since 1.0 453 */ 454 public function populateDatabase(& $db, $schema) 455 { 456 // Initialise variables. 457 $return = true; 458 459 // Get the contents of the schema file. 460 if (!($buffer = file_get_contents($schema))) { 461 $this->setError($db->getErrorMsg()); 462 return false; 463 } 464 465 // Get an array of queries from the schema and process them. 466 $queries = $this->_splitQueries($buffer); 467 foreach ($queries as $query) 468 { 469 // Trim any whitespace. 470 $query = trim($query); 471 472 // If the query isn't empty and is not a comment, execute it. 473 if (!empty($query) && ($query{0} != '#')) { 474 // Execute the query. 475 $db->setQuery($query); 476 477 try 478 { 479 $db->query(); 480 } 481 catch (JDatabaseException $e) 482 { 483 $this->setError($e->getMessage()); 484 $return = false; 485 } 486 } 487 } 488 489 return $return; 490 } 491 492 /** 493 * Method to set the database character set to UTF-8. 494 * 495 * @param JDatabase &$db JDatabase object. 496 * @param string $name Name of the database to process. 497 * 498 * @return boolean True on success. 499 * @since 1.0 500 */ 501 public function setDatabaseCharset(& $db, $name) 502 { 503 // Run the create database query. 504 $db->setQuery( 505 'ALTER DATABASE '.$db->quoteName($name).' CHARACTER' . 506 ' SET `utf8`' 507 ); 508 509 try 510 { 511 $db->query(); 512 } 513 catch (JDatabaseException $e) 514 { 515 return false; 516 } 517 518 return true; 519 } 520 521 /** 522 * Method to split up queries from a schema file into an array. 523 * 524 * @param string $sql SQL schema. 525 * 526 * @return array Queries to perform. 527 * @since 1.0 528 * @access protected 529 */ 530 function _splitQueries($sql) 531 { 532 // Initialise variables. 533 $buffer = array(); 534 $queries = array(); 535 $in_string = false; 536 537 // Trim any whitespace. 538 $sql = trim($sql); 539 540 // Remove comment lines. 541 $sql = preg_replace("/\n\#[^\n]*/", '', "\n".$sql); 542 543 // Parse the schema file to break up queries. 544 for ($i = 0; $i < strlen($sql) - 1; $i ++) 545 { 546 if ($sql[$i] == ";" && !$in_string) { 547 $queries[] = substr($sql, 0, $i); 548 $sql = substr($sql, $i +1); 549 $i = 0; 550 } 551 552 if ($in_string && ($sql[$i] == $in_string) && $buffer[1] != "\\") { 553 $in_string = false; 554 } 555 elseif (!$in_string && ($sql[$i] == '"' || $sql[$i] == "'") && (!isset ($buffer[0]) || $buffer[0] != "\\")) { 556 $in_string = $sql[$i]; 557 } 558 if (isset ($buffer[1])) { 559 $buffer[0] = $buffer[1]; 560 } 561 $buffer[1] = $sql[$i]; 562 } 563 564 // If the is anything left over, add it to the queries. 565 if (!empty($sql)) { 566 $queries[] = $sql; 567 } 568 569 return $queries; 570 } 571 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Tue Apr 3 11:40:28 2012 | Cross-referenced by PHPXref 0.7.1 |