<?php

/**
 *--------------------------------------
 * database
 *--------------------------------------
 * @project		: loga
 * @author		: cblee
 * @created		: 2016-07-02
 * @copyright	: (c)2016 AsThis
 *--------------------------------------
 */
defined('PFA_PATH') or exit('Access Denied');

class DatabaseCtrlr extends ManageCtrlr {
	public function list_table() {
		$_TL = M('Database')->get_tableList();
		$this->assign('_TL', $_TL);
		$this->display('database/list_table');
	}

	public function list_field() {
		$table = ARequest::get('table');
		if(empty($table)) {
			exit();
		}
		$_FL = M()->db->get_fields($table);
		$this->assign('_FL', $_FL);
		$this->display('database/list_field');
	}

	public function backup_do() {
		$volumeSize = ARequest::get('volume_size') ? intval(ARequest::get('volume_size')) : 2048;
		$volumeItem = ARequest::get('volume_item') ? intval(ARequest::get('volume_item')) : 5000;
		$mark = trim(str_replace(array('\\', '/'), '', ARequest::get('mark'))) ? trim(str_replace(array('\\', '/'), '', ARequest::get('mark'))) : date('Ymd');

		$dataDir = RUNTIME_PATH.D_S.'bak'.D_S.$mark;
		if(!is_dir($dataDir)) {
			mk_dir($dataDir);
		}

		$_BFL = F('_backup_file_list_'.$mark);
		if(empty($_BFL)) {
			$_BFL = M('Database')->get_backupFileList($mark);
		}

		$table = F('_data_table_list_'.$mark);
		if(empty($table)) {
			if(!check_token()) {
				$this->error(L('DATA_INVALID'), AServer::get_preUrl());
			}

			$backupStructure = ARequest::get('backup_structure') ? true : false;
			$table = $this->_get_postTable();

			if(empty($table) and !$backupStructure) {
				M('Log')->add_log(L('BACKUP_DATABASE').': '.L('NO_TABLE_SELECTED'), 0);
				$this->error(L('NO_TABLE_SELECTED'), Url::U('database/list_backup_file'));
			}
			if($backupStructure) {
				if(!M('Database')->backup_tableStructure($table, $mark)) {
					M('Log')->add_log(L('BACKUP_DATABASE_STRUCTURE_FAILED'), 0);
					$this->error(L('BACKUP_DATABASE_STRUCTURE_FAILED'), Url::U('database/list_table'));
				}
				/* delete old structure file */
				if(isset($_BFL['structure']) and !empty($_BFL['structure'])) {
					@unlink($dataDir.D_S.$_BFL['structure']['filename']);
				}
			}
			F('_data_table_list_'.$mark, $table);
		}

		$total = count($table);
		$current = ARequest::get('current') ? ARequest::get('current') : 1;

		if(!M('Database')->backup_tableData($table[$current - 1], $mark, $volumeSize, $volumeItem)) {
			M('Log')->add_log(L('BACKUP_DATABASE_DATA_FAILED').': TABLE['.$table[$current - 1].']', 0);
			$this->error(L('BACKUP_DATABASE_DATA_FAILED').': TABLE['.$table[$current - 1].']', Url::U('database/list_table'));
		}

		/* delete old data file */
		foreach($_BFL['data_core'] as $dc) {
			if(preg_match("/^".$table[$current - 1]."\_\d+\_/", $dc['filename'])) {
				@unlink($dataDir.D_S.$dc['filename']);
			}
		}
		/* delete old other data file */
		foreach($_BFL['data_other'] as $do) {
			if(preg_match("/^".$table[$current - 1]."\_\d+\_/", $do['filename'])) {
				@unlink($dataDir.D_S.$do['filename']);
			}
		}

		set_time_limit(99999999);
		$this->display('cache/progress');

		/* progress and next page */
		if($current < $total) {
			$progress = round($current / $total * 100, 1);
			$nextUrl = Url::U('database/backup_do?volume_size='.$volumeSize.'&volume_item='.$volumeItem.'&mark='.$mark.'&current='.($current + 1));
			M('Database')->show_progress($progress.'% ['.$current.'/'.$total.']: '.$table[$current - 1], $progress);
			M('Database')->show_direction($nextUrl);
		}
		else {
			M('Database')->show_progress('100% ['.$current.'/'.$total.']: '.L('BACKUP_COMPLETE'), 100);
			set_time_limit(30);
			F('_data_table_list_'.$mark, null);
			F('_backup_file_list_'.$mark, null);
			M('Log')->add_log(L('BACKUP_DATABASE_SUCCESS'));
			M('Database')->show_direction(Url::U('database/list_backup_file?mark='.$mark), true);
		}
	}

	public function repair_do() {
		if(!check_token()) {
			$this->error(L('DATA_INVALID'), AServer::get_preUrl());
		}

		$table = $this->_get_postTable();
		if(empty($table)) {
			M('Log')->add_log(L('REPAIR_DATABASE').': '.L('NO_TABLE_SELECTED'), 0);
			$this->error(L('NO_TABLE_SELECTED'), Url::U('database/list_table'));
		}

		foreach($table as $table) {
			if(false == M('Database')->repair_table($table)) {
				M('Log')->add_log(L('REPAIR_DATABASE_FAILED'), 0);
				$this->error(L('REPAIR_DATABASE_FAILED'), Url::U('database/list_table'));
			}
		}

		M('Log')->add_log(L('REPAIR_DATABASE_SUCCESS'));
		$this->success(L('REPAIR_DATABASE_SUCCESS'), Url::U('database/list_table'));
	}

	public function optimize_do() {
		if(!check_token()) {
			$this->error(L('DATA_INVALID'), AServer::get_preUrl());
		}

		$table = $this->_get_postTable();
		if(empty($table)) {
			M('Log')->add_log(L('OPTIMIZE_DATABASE').': '.L('NO_TABLE_SELECTED'), 0);
			$this->error(L('NO_TABLE_SELECTED'), Url::U('database/list_table'));
		}

		foreach($table as $table) {
			if(false == M('Database')->optimize_table($table)) {
				M('Log')->add_log(L('OPTIMIZE_DATABASE_FAILED'), 0);
				$this->error(L('OPTIMIZE_DATABASE_FAILED'), Url::U('database/list_table'));
			}
		}

		M('Log')->add_log(L('OPTIMIZE_DATABASE_SUCCESS'));
		$this->success(L('OPTIMIZE_DATABASE_SUCCESS'), Url::U('database/list_table'));
	}

	public function list_backup_file() {
		$mark = trim(str_replace(array('\\', '/'), '', ARequest::get('mark')));

		/* backup mark list */
		$_ML = M('Database')->get_backupMarkList();
		$this->assign('_ML', $_ML);

		$_V = array(
			'mark' => $mark);
		$this->assign('_V', $_V);

		/* backuped file list */
		$_BFL = M('Database')->get_backupFileList($mark);
		$this->assign('_BFL', $_BFL);
		$this->display('database/list_backup_file');
	}

	public function restore_do() {
		$mark = trim(str_replace(array('\\', '/'), '', ARequest::get('mark')));

		$dataFile = F('_data_file_list_'.$mark);
		if(empty($dataFile)) {
			if(!check_token()) {
				$this->error(L('DATA_INVALID'), AServer::get_preUrl());
			}

			$dataFile = ARequest::get('data_file') ? ARequest::get('data_file') : array();
			$restoreStructure = ARequest::get('restore_structure') ? true : false;

			if(empty($dataFile) and !$restoreStructure) {
				M('Log')->add_log(L('BACKUP_DATABASE').': '.L('NO_TABLE_SELECTED'), 0);
				$this->error(L('NO_TABLE_SELECTED'), Url::U('database/list_backup_file?mark='.$mark));
			}

			$_BFL = M('Database')->get_backupFileList($mark);
			if($restoreStructure) {
				if(empty($_BFL['structure'])) {
					M('Log')->add_log(L('BACKUP_DATABASE').': '.L('STRUCTURE_FILE_INEXISTENCE'), 0);
					$this->error(L('STRUCTURE_FILE_INEXISTENCE'), Url::U('database/list_backup_file?mark='.$mark));
				}
				array_unshift($dataFile, $_BFL['structure']['filename']);
			}
			F('_data_file_list_'.$mark, $dataFile);
		}

		$total = count($dataFile);
		$current = ARequest::get('current') ? ARequest::get('current') : 1;

		if(false == M('Database')->restore_data($dataFile[$current - 1], $mark)) {
			M('Log')->add_log(L('RESTORE_DATABASE_FAILED').': FILE['.$mark.'|'.$dataFile[$current - 1].']', 0);
			$this->error(L('RESTORE_DATABASE_FAILED').': FILE['.$mark.'|'.$dataFile[$current - 1].']', Url::U('database/list_backup_file?mark='.$mark));
		}

		set_time_limit(99999999);
		$this->display('cache/progress');

		/* progress and next page */
		if($current < $total) {
			$progress = round($current / $total * 100, 1);
			$nextUrl = Url::U('database/restore_do?current='.($current + 1).'&mark='.$mark);
			M('Database')->show_progress($progress.'% ['.$current.'/'.$total.']: '.$mark.'|'.$dataFile[$current - 1], $progress);
			M('Database')->show_direction($nextUrl);
		}
		else {
			M('Database')->show_progress('100% ['.$current.'/'.$total.']: '.L('RESTORE_COMPLETE'), 100);
			set_time_limit(30);
			F('_data_file_list_'.$mark, null);
			M('Log')->add_log(L('RESTORE_DATABASE_SUCCESS'));
			M('Database')->show_direction(Url::U('database/list_table'), true);
		}
	}

	public function delete_backup_file_do() {
		if(!check_token()) {
			$this->error(L('DATA_INVALID'), AServer::get_preUrl());
		}

		$mark = trim(str_replace(array('\\', '/'), '', ARequest::get('mark')));
		if(empty($mark)) {
			$this->error(L('SELECT_BACKUP_FILE'), Url::U('database/list_backup_file'));
		}

		$dataDir = RUNTIME_PATH.D_S.'bak'.D_S.$mark;
		if(is_dir($dataDir)) {
			if(!clear_dir($dataDir, true, array(), true)) {
				M('Log')->add_log(L('DELETE_BACKUP_FILE_FAILED').': MARK['.$mark.']', 0);
				$this->error(L('DELETE_BACKUP_FILE_FAILED'), Url::U('database/list_backup_file'));
			}
		}

		M('Log')->add_log(L('DELETE_BACKUP_FILE_SUCCESS').': MARK['.$mark.']');
		$this->success(L('DELETE_BACKUP_FILE_SUCCESS'), Url::U('database/list_backup_file'));
	}

	private function _get_postTable() {
		$table = ARequest::get('table');
		if(is_string($table)) {
			$table = array($table);
		}
		return $table;
	}
}

?>