[ Index ]

PHP Cross Reference of Joomla 2.5.4 DE

title

Body

[close]

/installation/models/ -> database.php (source)

   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  }


Generated: Tue Apr 3 11:40:28 2012 Cross-referenced by PHPXref 0.7.1