* $setup = new Setup('test.xml'); * $setup->set('target', 'dst'); * $setup->executeActions('install'); * */ class Setup { protected $actions = array(); public $context = array(); protected $file; protected $action; protected $node; protected $stack = array(); public $zip; public $target; public function __construct($file) { $this->file = $file; $this->node = simplexml_load_file($file); $this->target = ''; $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 = Tools_SQLStatementExtractor::extract($this->zip->getFromName($file)); foreach ($stmtList as $stmt) { $conn->executeQuery ($stmt); } } static function batchSQL(/*.Database.*/ $conn, $file) { $stmtList = Utils_SQLStatementExtractor::extractFile($file); foreach ($stmtList as $stmt) { $conn->executeQuery ($stmt); } } }