219 lines
6.2 KiB
PHP
219 lines
6.2 KiB
PHP
<?php
|
||
|
||
/**
|
||
* <code>
|
||
* $setup = new Setup('test.xml');
|
||
* $setup->set('target', 'dst');
|
||
* $setup->executeActions('install');
|
||
* </code>
|
||
*/
|
||
namespace ctiso;
|
||
use ZipArchive,
|
||
ctiso\Tools\SQLStatementExtractor;
|
||
|
||
class Setup
|
||
{
|
||
protected $actions = array();
|
||
public $context = array();
|
||
protected $file;
|
||
protected $action;
|
||
protected $node;
|
||
protected $stack = array();
|
||
|
||
public $zip;
|
||
|
||
public $target;
|
||
public $source;
|
||
|
||
public function __construct($file)
|
||
{
|
||
$this->file = $file;
|
||
$this->node = simplexml_load_file($file);
|
||
|
||
$this->target = '';
|
||
$this->source = '';
|
||
$this->zip = new ZipArchive();
|
||
$this->zip->open(strtr($file, array('.xml' => '.zip')));
|
||
|
||
|
||
array_push($this->stack, $this->node);
|
||
|
||
$this->registerAction('copy', array($this, 'copyFile'));
|
||
$this->registerAction('make-directory', array($this, 'makeDirectory'));
|
||
$this->registerAction('make-link', array($this, 'makeLink'));
|
||
$this->registerAction('include', array($this, 'includeFile'));
|
||
$this->registerAction('when', array($this, 'testWhen'));
|
||
}
|
||
|
||
/**
|
||
* Регистрация новых действия для установки
|
||
*/
|
||
public function registerAction($name, $action)
|
||
{
|
||
$this->actions[$name] = $action;
|
||
}
|
||
|
||
/**
|
||
* Установка переменных для шаблона
|
||
*/
|
||
public function set($name, $value)
|
||
{
|
||
$this->context[$name] = $value;
|
||
}
|
||
|
||
function replaceFn($matches) {
|
||
if (isset($this->context[$matches[2]])) {
|
||
$v = $this->context[$matches[2]];
|
||
} else {
|
||
$v = $matches[2];
|
||
}
|
||
|
||
if ($matches[1] == '*') {
|
||
return addslashes($v);
|
||
}
|
||
return $v;
|
||
}
|
||
|
||
public function fileContent($file, array $tpl)
|
||
{
|
||
$result = $this->zip->getFromName($file);
|
||
$result = preg_replace_callback('/\{\{\s*(\*?)(\w+)\s*\}\}/', array($this, 'replaceFn'), $result);
|
||
return $result;
|
||
}
|
||
|
||
function callAction($name, array $attributes)
|
||
{
|
||
if(isset($this->actions[$name])) {
|
||
call_user_func_array($this->actions[$name], $attributes);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Заменяет переменные на их значения в строке
|
||
*/
|
||
function replaceVariable(array $match)
|
||
{
|
||
if (isset($this->context[$match[1]])) {
|
||
return $this->context[$match[1]];
|
||
}
|
||
return $match[0];
|
||
}
|
||
|
||
/**
|
||
* Для всех аттрибутов заменяет переменные на их значения
|
||
*/
|
||
function resolve($attributes)
|
||
{
|
||
$result = array();
|
||
foreach ($attributes as $key => $value) {
|
||
$result [$key] = preg_replace_callback("/\\\${(\w+)}/", array($this, 'replaceVariable'), $value);
|
||
}
|
||
return $result;
|
||
}
|
||
|
||
/**
|
||
* Выполняет список действий если для действия не указан аттрибут when то оно выполняется всегда
|
||
*
|
||
* @param $action специальное действие
|
||
*/
|
||
function executeActions($action = "install")
|
||
{
|
||
$this->action = $action;
|
||
if ($this->stack[count($this->stack) - 1] === false) {
|
||
return;
|
||
}
|
||
|
||
/*.\SimpleXMLElement.*/$item = $this->stack[count($this->stack) - 1];
|
||
$root = $item->children();
|
||
foreach ($root as $node)
|
||
{
|
||
$attributes = $node->attributes();
|
||
array_push($this->stack, $node);
|
||
$this->callAction($node->getName(), array($this->resolve($attributes)));
|
||
array_pop($this->stack);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Копирования файла
|
||
* @param preserve Не переписывать файл если он существует
|
||
* @param template Файл является шаблоном подставить параметры до копирования
|
||
* @param src Исходный файл
|
||
* @param dst Новый файл
|
||
*/
|
||
public function copyFile(array $attributes)
|
||
{
|
||
$path = $this->targetPath($attributes['dst']);
|
||
|
||
if (!(file_exists($path) && isset($attributes['preserve']))) {
|
||
file_put_contents($path, $this->fileContent($attributes['src'], $this->context));
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Создает символическую ссылку на папку/файл
|
||
* @param dst Имя папки
|
||
*/
|
||
public function makeLink(array $attributes)
|
||
{
|
||
if (function_exists('symlink')) {
|
||
symlink($attributes['target'], $attributes['link']);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Подключение файла установки
|
||
* @param file Имя подключаемого файла
|
||
*/
|
||
public function includeFile(array $attributes)
|
||
{
|
||
$file = basename($this->file) . "/" . $attributes['file'];
|
||
|
||
$setup = new Setup($file);
|
||
$setup->context = $this->context;
|
||
$setup->executeActions();
|
||
}
|
||
|
||
function targetPath($s) {
|
||
return $this->target . '/' . $s;
|
||
}
|
||
|
||
/**
|
||
* Создает новую папку
|
||
* @param dst Имя папки
|
||
*/
|
||
public function makeDirectory(array $attributes)
|
||
{
|
||
$path = $this->targetPath($attributes['dst']);
|
||
if (!file_exists($path)) {
|
||
mkdir($path);
|
||
}
|
||
}
|
||
|
||
function testWhen(array $attributes)
|
||
{
|
||
if (!isset($attributes['test']) || $attributes['test'] == $this->action) {
|
||
$this->executeActions($this->action);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Выполнение Списка SQL команд
|
||
*/
|
||
function batchSQLZip(/*.Database.*/ $conn, $file)
|
||
{
|
||
$stmtList = SQLStatementExtractor::extract($this->zip->getFromName($file));
|
||
foreach ($stmtList as $stmt) {
|
||
$conn->executeQuery ($stmt);
|
||
}
|
||
}
|
||
|
||
static function batchSQL(/*.Database.*/ $conn, $file)
|
||
{
|
||
$stmtList = SQLStatementExtractor::extractFile($file);
|
||
foreach ($stmtList as $stmt) {
|
||
$conn->executeQuery ($stmt);
|
||
}
|
||
}
|
||
}
|
||
|