* @category class * @package core * @subpackage util * @copyright 2005-2017 Titan Framework * @license http://www.titanframework.com/license/ BSD License (3 Clause) * @see Instance * @link http://www.titanframework.com/docs/tutorials/backup/ */ class Backup { static private $backup = FALSE; static private $lock = FALSE; private $path = FALSE; private $validity = 86400; private $timeout = 86400; private $folder = FALSE; private final function __construct () { $array = Instance::singleton ()->getBackup (); if (!is_array ($array) || !array_key_exists ('path', $array) || trim ($array ['path']) == '') return; $this->path = $array ['path']; if (!file_exists ($this->path) && !@mkdir ($this->path, 0777)) throw new Exception ('Impossible to create folder ['. $this->path .'].'); if (array_key_exists ('validity', $array) && is_numeric ($array ['validity']) && (int) $array ['validity']) $this->validity = (int) $array ['validity']; if (array_key_exists ('timeout', $array) && is_numeric ($array ['timeout']) && (int) $array ['timeout']) $this->timeout = (int) $array ['timeout']; self::$lock = uniqid (rand (), TRUE); } static public function singleton () { if (self::$backup !== FALSE) return self::$backup; $class = __CLASS__; self::$backup = new $class (); return self::$backup; } public function isActive () { return self::$lock !== FALSE; } public function getPath () { return $this->path; } public function getRealPath () { return realpath ($this->path); } public function getLockPath () { return $this->getRealPath () . DIRECTORY_SEPARATOR .'.lock'; } public function getLockId () { return self::$lock; } public function getValidity () { return (string) $this->validity; } public function getTimeout () { return (string) $this->timeout; } public function getLock () { $handle = fopen ($this->getLockPath (), 'a+'); if ($handle === FALSE) throw new Exception ('Impossible to read/create lock ['. $this->getLockPath () .'].'); if (flock ($handle, LOCK_EX) && (filemtime ($this->getLockPath ()) < strtotime ('-'. $this->getTimeout () .' seconds') || !filesize ($this->getLockPath ()))) { ftruncate ($handle, 0); rewind ($handle); fwrite ($handle, (string) self::$lock); flock ($handle, LOCK_UN); fclose ($handle); return TRUE; } fclose ($handle); return FALSE; } public function releaseLock () { if (file_exists ($this->getLockPath ()) && self::$lock === trim (@file_get_contents ($this->getLockPath ()))) return @unlink ($this->getLockPath ()); return FALSE; } public function getFolder () { if ($this->folder === FALSE) { do { $folder = 'B'. shortlyHash (md5 (uniqid (rand (), TRUE))); } while (file_exists ($this->getRealPath () . DIRECTORY_SEPARATOR . $folder)); if (!@mkdir ($this->getRealPath () . DIRECTORY_SEPARATOR . $folder, 0777)) throw new Exception ('Impossible to create unique backup folder ['. $this->getRealPath () . DIRECTORY_SEPARATOR . $folder .'].'); $this->folder = $folder; } return $this->folder; } static public function clear () { $folders = glob (self::singleton ()->getRealPath () . DIRECTORY_SEPARATOR .'B*'); if (is_array ($folders)) foreach ($folders as $trash => $folder) if (is_dir ($folder) && filemtime ($folder) < strtotime ('-'. self::singleton ()->getValidity () .' seconds')) { unlink ($folder . DIRECTORY_SEPARATOR .'.htaccess'); unlink ($folder . DIRECTORY_SEPARATOR .'.htpasswd'); removeDir ($folder); toLog ('Backup folder deleted ['. $folder .'].'); } return TRUE; } }