ptut-vhost/build/api/module/department/versionController.php

299 lines
6.9 KiB
PHP

<?php
/**
* Created by PhpStorm.
* User: lucas
* Date: 15/03/18
* Time: 15:50
*/
namespace api\module\department;
use database\core\Repo;
use error\core\Error;
use error\core\Err;
use database\repo\department;
use Ifsnop\Mysqldump\Mysqldump;
class versionController{
/* Attributes
---------------------------------------------------------*/
private $backup_path;
private $origin_dbname;
/* (1) Initialize object
*
---------------------------------------------------------*/
public function __construct(){
$this->backup_path = null;
$this->origin_dbname = null;
}
/* (2) Initializes a directory
*
* @db_name<String> The database name
*
* @return outName<outType> outDesc
*
--------------------------------------------------------*/
private function initDir(string $db_name){
/* (1) Manage 'BACKUP' root directory
---------------------------------------------------------*/
/* (1) If not exists -> try to create it */
if( !is_dir(__BACKUP__) )
mkdir(__BACKUP__);
/* (2) Try to override permissions */
chmod(__BACKUP__, 0775);
/* (2) Manage sub-directory
---------------------------------------------------------*/
/* (1) If @db_name is 'preview_@database_hash' -> extract @database */
if( preg_match('/^preview_(\w+)_[a-f0-9]+$/', $db_name, $m) )
$db_name = $m[1];
/* (2) Store @db_name as origin */
$this->origin_dbname = $db_name;
/* (3) Store backup path */
$this->backup_path =__BACKUP__."/$db_name";
/* (4) If dir. already exists -> do nothing more */
if( is_dir($this->backup_path) )
return;
/* (4) Else -> try to create + set permissions */
mkdir($this->backup_path);
chmod($this->backup_path, 0775);
}
/* (3) Scan directory files
*
* @path<String> Directory path
*
* @return files<array> Array containing file names
*
---------------------------------------------------------*/
private function scandir(string $path) : array {
/* (1) Return [] if not a directory */
if( !is_dir($path) )
return [];
/* (2) Scan the directory */
$files = scandir($path);
/* (3) Remove '.' and '..' (2 first elements) */
$files = array_slice($files, 2);
/* (4) Return file list */
return $files;
}
/* (4) List available versions for this department
*
* @return versions<array> Version list
*
---------------------------------------------------------*/
public function get($args){
/* (1) Initialize directory for current database (department) */
$this->initDir( $_SESSION['CurrentDatabase'] );
/* (2) Strip extensions */
$versions = array_map(
function($e){ return pathinfo($e, PATHINFO_FILENAME); },
$this->scandir($this->backup_path)
);
/* (3) Return versions */
return ['versions' => $versions ];
}
/* (5) Remove an existing version for this department
*
* @version<String> Version name (typically snapshot date)
*
* @return deleted<bool> Whether the version has been deleted
*
---------------------------------------------------------*/
public function delete($args){
$version = null;
extract($args);
/* (1) Initialize directory for current database (department) */
$this->initDir( $_SESSION['CurrentDatabase'] );
/* (2) Dispatch 'unlink' result */
return [ 'deleted' => unlink($this->backup_path."/$version.sql") ];
}
/* (6) Creates a new version (snapshot of database) from now
*
* @return created_id<String> The created version id (date)
*
---------------------------------------------------------*/
public function post($args){
/* (1) Initialize directory for current database (department) */
$this->initDir( $_SESSION['CurrentDatabase'] );
/* (2) Try to create the snapshot */
try{
/* (2.1) Get database configuration */
$conf = Repo::getDBConfig();
/* (2.2) Try to dump the database */
$dump = new Mysqldump(
'mysql:host='.$conf['host'].';dbname='.$conf['dbname'],
$conf['username'],
$conf['password'],
[ "compress" => Mysqldump::GZIP ]
);
/* (2.3) Get current date (for naming the version) */
$current_date = date('d-m-Y');
/* (2.4) Store the version */
$dump->start($this->backup_path."/$current_date.sql");
/* (2.5) Return status */
return ['created_id' => $current_date ];
/* (3) On error -> dispatch error */
}catch(\Exception $e){
return ['error' => new Error(Err::RepoError)];
}
}
/* (6) ( Switches to preview || Applies on prod ) for a version
*
* @apply<int> If 0 -> preview version
* If 1 -> apply version into prod database
* @version<String> [OPT] Version name to use (if ommited, switch back to prod database)
*
* @return created_id<String> The created version id (date)
*
---------------------------------------------------------*/
public function put($args){
$apply = null;
$version = null;
extract($args);
/* (1) Initialisation
---------------------------------------------------------*/
/* (1) Initialize directory for current database (department) */
$this->initDir( $_SESSION['CurrentDatabase'] );
/* (2) Get department repository */
/** @var department $dept_repo */
$dept_repo = Repo::getRepo('department');
/* (3) Check whether we have to [apply OR preview] */
$apply = ( $apply === '1' );
/* (2) If back to 'prod' database
---------------------------------------------------------*/
if( is_null($version) ){
/* (1) Reset database to 'prod' */
$_SESSION['CurrentDatabase'] = $this->origin_dbname;
$_SESSION['VERSION'] = null;
/* (2) Return success */
return [ 'updated' => true ];
}
/* (3) Read the backup version
---------------------------------------------------------*/
/* (1) Start buffer */
ob_start();
/* (2) Read backup file */
readgzfile($this->backup_path."/$version.sql");
/* (3) Store & Flush buffer into variable */
$snapshot = ob_get_clean();
/* (4) Manage error */
if( strlen($snapshot) === 0 )
return ['error' => new Error(Err::RepoError)];
/* (4) APPLY into 'prod' database
---------------------------------------------------------*/
if( $apply ){
/* (1) Restore from this version */
$restored = $dept_repo->restore($this->origin_dbname, $snapshot);
$_SESSION['VERSION'] = null;
/* (2) Dispatch repo execution status */
return [ 'updated' => $restored ];
}
/* (5) PREVIEW version database
---------------------------------------------------------*/
/* (1) Try to get 'preview' database name */
$preview_dbname = $dept_repo->previewExists($this->origin_dbname, $version);
/* (2) If does not exist -> create it */
if( is_null($preview_dbname) ){
/* 1. Try to create preview */
$preview_dbname = $dept_repo->createPreview($this->origin_dbname, $version);
/* 2. Switch to preview */
$dept_repo->restore($preview_dbname, $snapshot);
}
/* (3) Store 'preview' database in session */
$_SESSION['CurrentDatabase'] = $preview_dbname;
$_SESSION['VERSION'] = $version;
/* (4) Return status */
return [ 'updated' => true ];
}
}