%PDF- %PDF-
Direktori : /home/lightco1/www/lightingrepublic.com.au/administrator/components/com_akeeba/models/ |
Current File : /home/lightco1/www/lightingrepublic.com.au/administrator/components/com_akeeba/models/selfheal.php |
<?php /** * @package AkeebaBackup * @copyright Copyright (c)2009-2013 Nicholas K. Dionysopoulos * @license GNU General Public License version 3, or later * @since 3.3 */ // Protect from unauthorized access defined('_JEXEC') or die(); /** * Self-healing database schema features * */ class AkeebaModelSelfheal extends FOFModel { private $schemata = array(); public function __construct($config = array()) { parent::__construct($config); $schemata['#__ak_profiles'] = <<<ENDSQL CREATE TABLE IF NOT EXISTS `#__ak_profiles` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `description` varchar(255) NOT NULL, `configuration` longtext, `filters` longtext, PRIMARY KEY (`id`) ) DEFAULT CHARACTER SET utf8; ENDSQL; $schemata['default_profile'] = <<<ENDSQL INSERT IGNORE INTO `#__ak_profiles` (`id`,`description`, `configuration`, `filters`) VALUES (1,'Default Backup Profile','',''); ENDSQL; $schemata['#__ak_stats'] = <<<ENDSQL CREATE TABLE IF NOT EXISTS `#__ak_stats` ( `id` bigint(20) unsigned NOT NULL auto_increment, `description` varchar(255) NOT NULL, `comment` longtext, `backupstart` timestamp NOT NULL default '0000-00-00 00:00:00', `backupend` timestamp NOT NULL default '0000-00-00 00:00:00', `status` enum('run','fail','complete') NOT NULL default 'run', `origin` VARCHAR(30) NOT NULL DEFAULT 'backend', `type` VARCHAR(30) NOT NULL DEFAULT 'full', `profile_id` bigint(20) NOT NULL default '1', `archivename` longtext, `absolute_path` longtext, `multipart` INT NOT NULL DEFAULT 0, `tag` VARCHAR(255) NULL, `filesexist` TINYINT(3) NOT NULL DEFAULT '1', `remote_filename` varchar(1000) DEFAULT NULL, `total_size` bigint(20) NOT NULL DEFAULT '0', INDEX `idx_fullstatus`(`filesexist`, `status`), INDEX `idx_stale`(`status`, `origin`), PRIMARY KEY (`id`) ) DEFAULT CHARACTER SET utf8; ENDSQL; $schemata['#__ak_storage'] = <<<ENDSQL CREATE TABLE IF NOT EXISTS `#__ak_storage` ( `tag` VARCHAR(255) NOT NULL, `lastupdate` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `data` LONGTEXT, PRIMARY KEY (`tag`) ) DEFAULT CHARACTER SET utf8; ENDSQL; } /** * Heals the database schema. * * @return bool False if self-healing failed */ public function healSchema() { // Only run when this component runs under the MySQL database engine //if(!$this->isMySQL()) return true; $db = JFactory::getDBO(); // Fix missing tables if(!$this->tableExists('#__ak_profiles')) { if(!$this->runSQL($this->schemata['#__ak_profiles'])) return false; if(!$this->runSQL($this->schemata['default_profile'])) return false; } foreach(array('#__ak_stats','#__ak_storage') as $table) { if(!$this->tableExists($table)) { if(!$this->runSQL($this->schemata[$table])) return false; } } // Fix the #__ak_stats table (req. for upgrades from 3.0/.a1 to 3.1./3.1 releases) if(!$this->columnExists('#__ak_stats', 'total_size')) { $hasTagColumn = !$this->columnExists('#__ak_stats', 'tag'); // Drop any existing #__ak_stats_bak table if(!$this->runSQL('DROP TABLE IF EXISTS `#__ak_stats_bak`')) { if($db->getErrorNum() != 1060) return false; } // Create a new #__ak_stats_bak table $sql = $this->schemata['#__ak_stats']; $sql = str_replace('#__ak_stats', '#__ak_stats_bak', $sql); if(!$this->runSQL($sql)) { if($db->getErrorNum() != 1060) return false; } // Copy existing data from #__ak_stats to #__ak_stats_bak if($hasTagColumn) { // Upgrade from 3.1.3 or later (has tag and filesexist columns) $sql = <<<ENDSQL INSERT IGNORE INTO `#__ak_stats_bak` (`id`,`description`,`comment`,`backupstart`,`backupend`,`status`,`origin`,`type`,`profile_id`,`archivename`,`absolute_path`,`multipart`,`tag`,`filesexist`) SELECT `id`,`description`,`comment`,`backupstart`,`backupend`,`status`,`origin`,`type`,`profile_id`,`archivename`,`absolute_path`,`multipart`,`tag`,`filesexist` FROM `#__ak_stats`; ENDSQL; } else { // Upgrade from 3.1.2 or earlier $sql = <<<ENDSQL INSERT IGNORE INTO `#__ak_stats_bak` (`id`,`description`,`comment`,`backupstart`,`backupend`,`status`,`origin`,`type`,`profile_id`,`archivename`,`absolute_path`,`multipart`) SELECT `id`,`description`,`comment`,`backupstart`,`backupend`,`status`,`origin`,`type`,`profile_id`,`archivename`,`absolute_path`,`multipart` FROM `#__ak_stats`; ENDSQL; } if(!$this->runSQL($sql)) { if($db->getErrorNum() != 1060) return false; } // Drop the broken #__ak_stats table if(!$this->runSQL('DROP TABLE IF EXISTS `#__ak_stats`')) return false; // Create the #__ak_stats table afresh if(!$this->runSQL($this->schemata['#__ak_stats'])) return false; // Move data from the #__ak_stats_bak to the new #__ak_stats table if(!$this->runSQL('INSERT IGNORE INTO `#__ak_stats` SELECT * FROM `#__ak_stats_bak`')) return false; // Drop the #__ak_stats_bak table if(!$this->runSQL('DROP TABLE IF EXISTS `#__ak_stats_bak`')) return false; } // If we're still here, our schema is up-to-date! return true; } /** * Runs a SQL statement and return false if the query failed * @param string $sql The SQL command to run * @return bool */ private function runSQL($sql) { $db = JFactory::getDBO(); $db->setQuery($sql); try { $db->execute(); } catch(DatabaseException $e) { return false; } return true; } /** * Checks if a particular column exists in a table * @param string $table The table name to check, e.g. #__ak_stats * @param string $column The column to check, e.g. tag * * @return bool True if the column exists */ private function columnExists($table, $column) { $db = JFactory::getDBO(); // First, try using DESCRIBE (preferred method) $db->setQuery('DESCRIBE '.$db->qn($table)); try { $columns = $db->loadColumn(0); } catch(DatabaseException $e) { $columns = null; } if(!is_null($columns)) { return in_array($column, $columns); } // DESCRIBE failed. Try the hard way... $db->setQuery('SHOW CREATE TABLE '.$db->qn($table)); try { $creates = $db->loadColumn(1); } catch(DatabaseException $e) { return false; } $create = $creates[0]; $search = $db->qn($column); return strpos($search, $create) !== false; } /** * Checks if a specific table exists in the database * @param string $table Table name, e.g. #__ak_stats * * @return bool */ private function tableExists($table) { $db = JFactory::getDBO(); return $this->runSQL('SELECT COUNT(*) FROM '.$db->qn($table)); } private function isMySQL() { $db = JFactory::getDbo(); return strtolower(substr($db->name, 0, 5)) == 'mysql'; } }