* @copyright 2007-2011 PrestaShop SA * @version Release: $Revision: 7721 $ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) * International Registered Trademark & Property of PrestaShop SA */ include_once(PS_ADMIN_DIR.'/../classes/AdminTab.php'); class AdminBackup extends AdminTab { /** @var string The field we are sorting on */ protected $_sortBy = 'date'; public function __construct() { $this->table = 'backup'; $this->className = 'Backup'; parent::__construct(); $this->edit = false; $this->delete = true; $this->view = true; $this->deleted = false; $this->requiredDatabase = false; $this->fieldsDisplay = array ( 'date' => array('title' => $this->l('Date'), 'type' => 'datetime', 'width' => 120, 'align' => 'right'), 'age' => array('title' => $this->l('Age')), 'filename' => array('title' => $this->l('File name'), 'width' => 200), 'filesize' => array('title' => $this->l('File size'))); $this->optionTitle = $this->l('Backup options'); $this->_fieldsOptions = array( 'PS_BACKUP_ALL' => array('title' => $this->l('Ignore statistics tables:'), 'desc' => $this->l('The following tables will NOT be backed up if you enable this option:').'
'._DB_PREFIX_.'connections, '._DB_PREFIX_.'connections_page, '._DB_PREFIX_.'connections_source, '._DB_PREFIX_.'guest, '._DB_PREFIX_.'statssearch', 'cast' => 'intval', 'type' => 'bool'), 'PS_BACKUP_DROP_TABLE' => array('title' => $this->l('Drop existing tables during import:'), 'desc' => $this->l('Select this option to instruct the backup file to drop your tables prior to restoring the backed up data').'
(ie. "DROP TABLE IF EXISTS")', 'cast' => 'intval', 'type' => 'bool')); $this->identifier = 'filename'; } /** * Load class object using identifier in $_GET (if possible) * otherwise return an empty object * This method overrides the one in AdminTab because AdminTab assumes the id is a UnsignedInt * "Backups" Directory in admin directory must be writeable (CHMOD 777) * @param boolean $opt Return an empty object if load fail * @return object */ protected function loadObject($opt = false) { if ($id = Tools::getValue($this->identifier)) return new $this->className($id); return new $this->className(); } /** * Creates a new backup, and then displays the normal menu */ public function displayForm($isMainTab = true) { if (is_writable(PS_ADMIN_DIR.'/backups/')) { if (!($object = $this->loadObject())) return; if ($object->add()) { echo '
 '.$this->l('It appears that the Backup was successful, however, you must download and carefully verify the Backup file.').'
'; if ($this->tabAccess['view'] === '1') echo '
'.$this->l('Download').'

'.$this->l('Download the Backup file').' ('.number_format((filesize($object->id)*0.000001), 2, '.', '').$this->l('Mb').')

'.$this->l('Tip: You can also download this file by FTP, Backup files are located in "admin/backups" directory.').'

'; $this->displayHowTo(false); } elseif ($object->error) $this->_errors[] = $object->error; } else $this->_errors[] = $this->l('"Backups" Directory in admin directory must be writeable (CHMOD 755 / 777)'); $this->displayErrors(); } /** * Displays the page which allows the backup to be downloaded */ public function viewbackup() { global $currentIndex; if (!($object = $this->loadObject())) return; if ($object->id) { $url = $object->getBackupURL(); echo '
 '.$this->l('Beginning download ...').'
'; echo '
'.$this->l('Back-up file should automatically download.'); echo '

'.$this->l('If not,').' '.$this->l('please click here!').''; echo ''; echo '


'.$this->l('Back to list').'
'; } elseif ($object->error) $this->_errors[] = $object->error; $this->displayErrors(); } public function displayHowTo($showForm = true) { global $currentIndex; echo '

'.$this->l('Disclaimer before creating a new Backup').'

  1. '.$this->l('PrestaShop is not responsible for your database, Backups, restore and data.').'
  2. '.$this->l('PrestaShop is an Open-source software, you are using it at your own risk under the licence agreement.').'
  3. '.$this->l('You should Backup your data on a regular basis (both files and database).').'
  4. '.$this->l('This function only backs up your database, not your files.').'
  5. '.$this->l('By default, your existing database tables will be deleted during Backup restore (see options).').'
  6. '.$this->l('Always verify the quality and integrity of your Backups files.').'
  7. '.$this->l('Always verify that your Backups files are complete, up-to-date and valid. Even if you had a success message during the Backup process.').'
  8. '.$this->l('Always check your data.').'
  9. '.$this->l('Never restore a Backup on a live site.').'
'; if ($showForm) echo '
'; echo '

'.$this->l('How-to restore a database Backup in 10 easy steps').'

  1. '.$this->l('Turn off the "Enable Shop" option in the "Preferences" tab.').'
  2. '.$this->l('Download the Backup from the list below or from your FTP server (in the folder "admin/backups").').'
  3. '.$this->l('Check the Backup integrity: look for errors, incomplete file. Verify all your data.').'
  4. '.$this->l('Ask your hosting provider for a "phpMyAdmin" access to your database').'
  5. '.$this->l('Connect to "phpMyAdmin" and select your current database').'
  6. '.$this->l('Unless you enabled the "Drop existing tables" option, you must delete all tables from your current database.').'
  7. '.$this->l('At the top of the screen select the tab "Import"').'
  8. '.$this->l('Click on the "Browse..." button and select the Backup file from your hard drive').'
  9. '.$this->l('Check the max. allowed filesize (ie. Max: 16Mb)').'
    '.$this->l('If your Backup file exceeds this limit, contact your hosting provider').'
  10. '.$this->l('Click on the "Go" button and wait during the import, the process can take several minutes').'
'; } public function displayList() { global $currentIndex; // Test if the backup dir is writable if (!is_writable(PS_ADMIN_DIR.'/backups/')) $this->displayWarning($this->l('"Backups" Directory in admin directory must be writeable (CHMOD 755 / 777)')); $this->displayErrors(); $this->displayHowTo(); parent::displayList(); } public function getList($id_lang, $orderBy = NULL, $orderWay = NULL, $start = 0, $limit = NULL) { global $cookie; if (!Validate::isTableOrIdentifier($this->table)) die('filter is corrupted'); if (empty($orderBy)) $orderBy = Tools::getValue($this->table.'Orderby', $this->_defaultOrderBy); if (empty($orderWay)) $orderWay = Tools::getValue($this->table.'Orderway', 'ASC'); // Try and obtain getList arguments from $_GET $orderBy = Tools::getValue($this->table.'Orderby'); $orderWay = Tools::getValue($this->table.'Orderway'); // Validate the orderBy and orderWay fields switch ($orderBy) { case 'filename': case 'filesize': case 'date': case 'age': break; default: $orderBy = 'date'; } switch ($orderWay) { case 'asc': case 'desc': break; default: $orderWay = 'desc'; } if (empty($limit)) $limit = ((!isset($cookie->{$this->table.'_pagination'})) ? $this->_pagination[0] : $limit = $cookie->{$this->table.'_pagination'}); $limit = (int)(Tools::getValue('pagination', $limit)); $cookie->{$this->table.'_pagination'} = $limit; /* Determine offset from current page */ if (!empty($_POST['submitFilter'.$this->table]) AND is_numeric($_POST['submitFilter'.$this->table])) $start = (int)($_POST['submitFilter'.$this->table] - 1) * $limit; $this->_lang = (int)($id_lang); $this->_orderBy = $orderBy; $this->_orderWay = strtoupper($orderWay); $this->_list = array(); // Find all the backups $dh = @opendir(PS_ADMIN_DIR.'/backups/'); if ($dh === false) { $this->_errors[] = Tools::displayError('Unable to open backup directory .').addslashes(PS_ADMIN_DIR.'/backups/').'"'; return; } while (($file = readdir($dh)) !== false) { if (preg_match('/^([\d]+-[a-z\d]+)\.sql(\.gz|\.bz2)?$/', $file, $matches) == 0) continue; $timestamp = (int)($matches[1]); $date = date('Y-m-d H:i:s', $timestamp); $age = time() - $timestamp; if ($age < 3600) $age = '< 1 '.$this->l('hour'); elseif ($age < 86400) { $age = floor($age / 3600); $age = $age.' '.(($age == 1) ? $this->l('hour') : $this->l('hours')); } else { $age = floor($age / 86400); $age = $age.' '.(($age == 1) ? $this->l('day') : $this->l('days')); } $size = filesize(PS_ADMIN_DIR.'/backups/'.$file); $this->_list[] = array( 'filename' => $file, 'age' => $age, 'date' => $date, 'filesize' => number_format($size / 1000, 2).' Kb', 'timestamp' => $timestamp, 'filesize_sort' => $size, ); } closedir($dh); $this->_listTotal = count($this->_list); // Sort the _list based on the order requirements switch ($this->_orderBy) { case 'filename': $this->_sortBy = 'filename'; $sorter = 'str_sort'; break; case 'filesize': $this->_sortBy = 'filesize_sort'; $sorter = 'int_sort'; break; case 'age': case 'date': $this->_sortBy = 'timestamp'; $sorter = 'int_sort'; break; } usort($this->_list, array($this, $sorter)); $this->_list = array_slice($this->_list, $start, $limit); } public function int_sort($a, $b) { return $this->_orderWay == 'ASC' ? $a[$this->_sortBy] - $b[$this->_sortBy] : $b[$this->_sortBy] - $a[$this->_sortBy]; } public function str_sort($a, $b) { return $this->_orderWay == 'ASC' ? strcmp($a[ $this->_sortBy], $b[$this->_sortBy]) : strcmp($b[ $this->_sortBy], $a[$this->_sortBy]); } }