/** * Конструктор * @param array $info Атрибуты объекта и свойства */ function __construct($info = []) { if ((!isset($info['parent']) || !isset($info['name'])) && isset($info['uri'])) { $names = F::splitRight('/', $info['uri'], true); $info['name'] = $names[1]; if (!isset($info['parent'])) { $info['parent'] = $names[0]; } } if (isset($info['properties'])) { foreach ($info['properties'] as $name => $child) { if (is_scalar($child)) { $child = ['value' => $child]; } $child['name'] = $name; $child['is_property'] = true; // if (!isset($child['is_default_logic'])) $child['is_default_logic'] = true; if (!isset($child['created']) && isset($info['created'])) { $child['created'] = $info['created']; } if (!isset($child['updated']) && isset($info['updated'])) { $child['updated'] = $info['updated']; } $child['is_exists'] = $info['is_exists']; if (isset($info['uri'])) { $child['uri'] = $info['uri'] . '/' . $name; } else { if (isset($this->_attributes['uri'])) { $child['uri'] = $this->_attributes['uri'] . '/' . $name; } } // Если у свойства нет прототипа, то определение прототипа через прототипы родителей if (!isset($child['proto']) && isset($info['proto'])) { $p = Data::read($info['proto']); do { $property = $p->{$name}; } while (!$property && ($p = $p->proto(null, true))); if ($property) { $child['proto'] = $property->uri(); } } $this->_children[$name] = Data::entity($child); $this->_children[$name]->_parent = $this; } unset($info['children']); } $this->_attributes = array_replace($this->_attributes, $info); }
function work(Request $request) { $out = $request['REQUEST']['handler']->start($request); if ($redirect = $request->getCommands('redirect')) { header("HTTP/1.1 303 See Other"); header('Location: ' . $redirect[0][0]); } else { if ($out != false) { if (is_array($out)) { header('Content-Type: application/json'); echo F::toJSON($out, false); } else { echo $out; } } else { header('Location: ' . Request::url()); //текущий адрес без аргументов } } }
/** * Активация модуля * Создание общего контейнера входящих данных */ static function activate() { if (get_magic_quotes_gpc()) { $process = array(&$_GET, &$_POST, &$_COOKIE, &$_REQUEST); while (list($key, $val) = each($process)) { foreach ($val as $k => $v) { unset($process[$key][$k]); if (is_array($v)) { $process[$key][stripslashes($k)] = $v; $process[] =& $process[$key][stripslashes($k)]; } else { $process[$key][stripslashes($k)] = stripslashes($v); } } } unset($process); } // Нормализация массива $_FILES в соответствии с именованием полей формы if (isset($_FILES)) { // Перегруппировка элементов массива $_FILES $rec_to_array = function ($array, $name) use(&$rec_to_array) { $result = []; foreach ($array as $key => $value) { if (is_array($value)) { $result[$key] = $rec_to_array($value, $name); } else { $result[$key][$name] = $value; } } return $result; }; $files = []; foreach ($_FILES as $field => $data) { $files[$field] = []; foreach ($data as $name => $value) { if (is_array($value)) { $files[$field] = F::arrayMergeRecursive($files[$field], $rec_to_array($value, $name)); } else { $files[$field][$name] = $value; } } } } else { $files = []; } self::$source = array('REQUEST' => [], 'FILES' => $files, 'COOKIE' => isset($_COOKIE) ? $_COOKIE : [], 'RAW' => file_get_contents("php://input"), 'SERVER' => $_SERVER); if (isset($_SERVER['REQUEST_URI'])) { $_SERVER['REQUEST_URI'] = preg_replace('#\\?{1}#u', '&', $_SERVER['REQUEST_URI'], 1); // $request_uri = preg_replace('#^'.preg_quote(DIR_WEB).'#u', '/', $_SERVER['REQUEST_URI'], 1); parse_str('path=' . $_SERVER['REQUEST_URI'], self::$source['REQUEST']); self::$source['SERVER']['argv'] = self::$source['REQUEST']; self::$source['SERVER']['argc'] = sizeof(self::$source['REQUEST']); } // Элементы пути URI if (isset(self::$source['REQUEST']['path']) && (self::$source['REQUEST']['path'] = rtrim(self::$source['REQUEST']['path'], '/ '))) { self::$source['PATH'] = explode('/', trim(self::$source['REQUEST']['path'], ' /')); } else { self::$source['PATH'] = []; } if (isset($_POST)) { self::$source['REQUEST'] = array_replace_recursive(self::$source['REQUEST'], $_POST); } // Аргументы из консоли (режим CLI) if (php_sapi_name() == 'cli' && isset($_SERVER['argv'])) { self::$source['REQUEST']['method'] = 'CLI'; self::$source['SERVER']['argv'] = $_SERVER['argv']; self::$source['SERVER']['argc'] = $_SERVER['argc']; } self::$source['ARG'] = self::$source['SERVER']['argv']; // Метод запроса if (isset(self::$source['SERVER']['REQUEST_METHOD']) && !isset(self::$source['REQUEST']['method'])) { self::$source['REQUEST']['method'] = self::$source['SERVER']['REQUEST_METHOD']; } }
/** * Сохранение сущности * @param Entity $entity * @throws Error */ function write($entity) { // Если объект свойство, то сохранять родительский объект?? if ($entity->is_property()) { if ($parent = $entity->parent(null, true)) { $parent->__set($entity->name(), $entity); Data::write($parent); } } else { // Текущие сведения об объекте $info = []; if ($entity->is_exists()) { // Текущие сведения об объекта $uri = $entity->is_changed('uri') ? $entity->changes('uri') : $entity->uri(); if ($uri === '') { $file = DIR . 'project.info'; } else { $file = DIR . trim($uri, '/') . '/' . File::fileName($uri) . '.info'; } if (is_file($file)) { $info = file_get_contents($file); $info = json_decode($info, true); } } // Подбор уникального имени // @todo Перенос php файлов влечет за собой фатальные ошибки!!!! так как меняется namespace и class name if ($entity->is_changed('uri') || !$entity->is_exists()) { // Проверка уникальности нового имени путём создания папки // Если подбор уникального имени, то создавать пока не создаться (попробовать постфикс) $path = dirname($entity->dir(true)) . '/'; $name = $entity->name(); if ($new_path = File::makeUniqueDir($path, $name, 1, $entity->is_auto_namig())) { $entity->name(basename($new_path)); $info['name'] = $entity->name(); } else { $entity->errors()->_attributes->name->add(new Error('Не уникальное', 'unique')); throw $entity->errors(); } // Перемещение старой папки в новую if ($entity->is_exists()) { File::rename($entity->dir(true, true), $entity->dir(true, false)); } if ($entity->is_changed('name') && $entity->is_exists()) { // @todo Переименовать .info, .php и, возможно, привязанный файл. } // Обновить URI подчиненных объектов не фиксируя изменения $entity->updateChildrenUri(); } // Новые сведения об объекте $info_new = $this->export($entity, isset($info['properties']) ? $info['properties'] : [], function (Entity $entity, $file) { return Data::save_file($entity, $file); }); // Порядковый номер // 1. Подбор максимального среди существующих // 2. Смещение порядка у последующих объектов // Сохранить объект с свлйствами JSON $uri = $entity->uri(); if ($uri === '') { $file = DIR . 'project.info'; } else { $file = DIR . trim($uri, '/') . '/' . File::fileName($uri) . '.info'; } File::create(F::toJSON($info_new, true), $file); } // Сохранить подчиненные foreach ($entity->children() as $child) { /** @var Entity $child */ if (!$child->is_property()) { Data::write($child); } } }
/** * Создание идентификатора для указанного URI. * Если объект с указанным URI существует, то будет возвращен его идентификатор * @param string $uri URI для которого нужно получить идентификатор * @param bool $create Создать идентификатор, если отсутствует? * @param bool $is_new Возвращаемый прзнак, был ли создан новый идентификатор? * @return int|null */ function localId($uri, $create = true, &$is_new = false) { $is_new = false; if (!is_string($uri)) { return 0; } // Из кэша if (!isset($this->_local_ids)) { // if ($local_ids = Cache::get('mysqlstore/localids')){ // $this->_local_ids = json_decode($local_ids, true); // }else{ $this->_local_ids = array(); // } } if (isset($this->_local_ids[$uri])) { return $this->_local_ids[$uri]; } // Поиск идентифкатора URI $q = $this->db->prepare('SELECT id FROM {ids} WHERE `uri`=? LIMIT 0,1 FOR UPDATE'); $q->execute(array($uri)); if ($row = $q->fetch(DB::FETCH_ASSOC)) { $id = $row['id']; $is_new = false; $this->_local_ids[$uri] = $id; $this->_global_ids[$id] = $uri; // Отношение с родителями $q = $this->db->prepare('SELECT * FROM {parents1} WHERE `id`=? LIMIT 0,1'); $q->execute(array($id)); if ($row = $q->fetch(DB::FETCH_ASSOC)) { $this->_parents_ids[$id] = F::array_clear($row); } // Отношение с прототипами $q = $this->db->prepare('SELECT * FROM {protos1} WHERE `id`=? LIMIT 0,1'); $q->execute(array($id)); if ($row = $q->fetch(DB::FETCH_ASSOC)) { $this->_protos_ids[$id] = F::array_clear($row); } } else { if ($create) { // Создание идентификатора для URI $q = $this->db->prepare('INSERT INTO {ids} (`id`, `uri`) VALUES (null, ?)'); $q->execute([$uri]); $id = $this->db->lastInsertId('id'); $is_new = true; $obj = Data::read($uri); // Отношения с родителями $this->makeParents($id, $this->localId($obj->parent())); // Отношения с прототипами $this->makeProtos($id, $this->localId($obj->proto())); } else { return 0; } } unset($q); return intval($id); }
/** * Преобразование условия поиска из массива или строки в url формат * @param string|array $cond Исходное условие поиска * @return string Преобразованное в URL условие */ static function condToUrl($cond) { $cond = self::normalizeCond($cond, [], true); if (is_array($cond['from'])) { $info = parse_url(reset($cond['from'])); $base_url = ''; if (isset($info['scheme'])) { $base_url .= $info['scheme'] . '://'; } if (isset($info['host'])) { $base_url .= $info['host']; } if ($base_url_length = mb_strlen($base_url)) { foreach ($cond['from'] as $i => $from) { if (mb_substr($from, 0, $base_url_length) == $base_url) { $cond['from'][$i] = mb_substr($from, $base_url_length); } } } } //if (sizeof($cond['select']) == 1) $cond['select'] = $cond['select'][0]; if ($cond['select'] == 'self') { unset($cond['select'], $cond['depth']); } unset($cond['correct']); foreach ($cond as $key => $c) { if (empty($c)) { unset($cond[$key]); } } $url = F::toJSON($cond, false); $url = mb_substr($url, 1, mb_strlen($url) - 2, 'UTF-8'); $url = strtr($url, ['[' => '(', ']' => ')', ',""]' => ',)', '"="' => '"eq"', '"!="' => '"ne"', '">"' => '"gt"', '">="' => '"gte"', '"<"' => '"lt"', '"<="' => '"lte"']); $url = preg_replace_callback('/"([^"]*)"/ui', function ($m) { $replacements = array("\\", "/", "\"", "\n", "\r", "\t", "", "\f"); $escapers = array("\\\\", "\\/", "\\\"", "\\n", "\\r", "\\t", "\\f", "\\b"); return urlencode(str_replace($escapers, $replacements, $m[1])); }, $url); $url = preg_replace('/,([a-z_]+):/ui', '&$1=', $url); $url = preg_replace('/\\(([a-z_]+),/ui', '$1(', $url); $url = preg_replace('/\\),/ui', ')$1', $url); $url = mb_substr($url, 5, mb_strlen($url) - 5); if (isset($base_url)) { $url = $base_url . '?from=' . $url; } else { $info = explode('&', $url, 2); if (!empty($info)) { $url = urldecode($info[0]) . '?' . $info[1]; } } return $url; }
/** * Генератор содержимого файла конфигурации * @param array $config * @param string $comment * @param bool $pretty * @return string */ static function generate(array $config, $comment = '', $pretty = true) { $arraySyntax = ['open' => self::$bracket_syntax ? '[' : 'array(', 'close' => self::$bracket_syntax ? ']' : ')']; $code = "<?php\n"; if ($comment) { $comment = explode("\n", $comment); $code .= "/**\n"; foreach ($comment as $line) { $code .= ' * ' . $line . "\n"; } $code .= " */\n"; } return $code . "return " . $arraySyntax['open'] . "\n" . ($pretty ? F::arrayToCode($config, $arraySyntax) : var_export($config, true)) . $arraySyntax['close'] . ";\n"; }
function work(Request $request) { $uri = ''; // $s = C::read(); // C::writeln(mb_detect_encoding($s,['utf-8','cp866'])); do { try { C::write(C::style($uri, [C::COLOR_GRAY_DARK]) . '> '); $commands = preg_split('/\\s/ui', trim(C::read())); $cmd_count = count($commands); if ($commands[0] == 'show') { $new_uri = !empty($commands[1]) ? $uri . '/' . trim($commands[1], ' \\/') : $uri; $obj = Data::read($new_uri); C::writeln(C::style(Trace::format($obj, false))); } else { if (mb_strlen($commands[0]) > 1 && ($commands[0][0] == '/' || mb_substr($commands[0], 0, 2) == '..')) { $new_uri = !empty($commands[0]) ? $uri . '/' . trim($commands[0], ' \\/') : $uri; $obj = Data::read($new_uri, false, true); if ($obj && $obj->is_exists()) { $uri = $obj->uri(); } else { C::writeln(C::style('Object does not exist', C::COLOR_RED)); } } else { if ($commands[0] == 'ls' || $commands[0] == 'children') { $list = Data::find(['from' => $uri, 'select' => empty($commands[1]) || $commands[1] != '-p' ? 'children' : 'properties', 'struct' => 'list', 'limit' => [0, 50]]); foreach ($list as $obj) { C::writeln(C::style($obj->name(), C::COLOR_BLUE)); } } else { if (preg_match('/^\\s*select(\\(|=)/ui', $commands[0])) { $cond = Data::normalizeCond($commands[0], false); if (!isset($cond['from'])) { $cond['from'] = $uri; } $result = Data::find($cond); C::writeln(C::style(Trace::format($result, false))); } else { if ($commands[0] == 'color') { if (!empty($commands[1])) { C::use_style($commands[1] == 'off' ? false : null); } else { C::use_style(true); } } else { if ($cmd_count > 1 && $commands[0] == 'attr') { $obj = Data::read($uri); $attr = $commands[1]; if ($obj instanceof Entity && $obj->is_exists() && $obj->is_attr($attr)) { if ($cmd_count > 2) { if ($commands[2] === "null") { $commands[2] = null; } else { if ($commands[2] === "false") { $commands[2] = false; } else { $commands[2] = trim(trim($commands[2], '"')); } } $obj->{$attr}($commands[2]); Data::write($obj); C::writeln(Trace::format($obj, false)); } else { C::writeln(C::style($obj->attr($attr)), C::COLOR_PURPLE); } } } else { if ($cmd_count > 2 && $commands[0] == 'new') { $new_uri = !empty($commands[1]) ? $uri . '/' . trim($commands[1], ' \\/') : $uri; list($parent, $name) = F::splitRight('/', $new_uri); if (!$parent) { $parent = ''; } $proto = $commands[2]; $obj = Data::create($proto, $parent, ['name' => $name]); $signs = array_flip($commands); if (isset($signs['-m'])) { $obj->is_mandatory(true); } if (isset($signs['-p'])) { $obj->is_property(true); } if (isset($signs['-d'])) { $obj->is_draft(true); } if (isset($signs['-h'])) { $obj->is_hidden(true); } if (isset($signs['-l'])) { $obj->is_link(true); } if (isset($signs['-r'])) { $obj->is_relative(true); } $obj->complete(); Data::write($obj); C::writeln(Trace::format($obj, false)); } else { if ($commands[0] == 'complete') { $obj = Data::read($uri); $signs = array_flip($commands); $only_mandatory = !isset($signs['-all']) && !isset($signs['-not-mandatory']); $only_property = !isset($signs['-all']) && !isset($signs['-not-property']); $obj->complete($only_mandatory, $only_property); Data::write($obj); C::writeln(Trace::format($obj, false)); } else { C::writeln(C::style('Unknown command', C::COLOR_RED)); } } } } } } } } } catch (Error $e) { C::writeln(C::style($e->getMessage(), C::COLOR_RED)); } catch (\Exception $e) { C::writeln(C::style((string) $e, C::COLOR_RED)); } Buffer::clear(); } while ($commands[0] !== 'exit'); C::writeln("\nby!"); // if (!empty($request['ARG'][2])) { // if ($request['ARG'][2] == 'read') { // $uri = empty($request['ARG'][3]) ? '' : '/' . trim($request['ARG'][3], '/'); // $obj = Data::read($uri); // C::writeln(C::style(Trace::style($obj, false))); // } else // if ($request['ARG'][2] == 'find') { // $cond = empty($request['ARG'][3]) ? '' : trim($request['ARG'][3], '/'); // $result = Data::find($cond); // C::write(C::style(Trace::style($result, false))); // } else // if ($request['ARG'][2] == 'edit') { // $object = Data::read(empty($request['ARG'][3]) ? '' : '/'.trim($request['ARG'][3], '/')); // $attr = empty($request['ARG'][4]) ? null : $request['ARG'][4]; // $value = empty($request['ARG'][5]) ? null : $request['ARG'][5]; // if ($object instanceof Entity && $object->is_exists() && $attr){ // $object->{$attr}($value); // Data::write($object); // C::write(C::style(Trace::style($object, false))); // } // }else // { //// phpinfo(); //// C::writeln(Trace::style($_ENV, false)); //// C::writeln(getenv('ANSICON')); // C::writeln( // C::style(json_encode($request['ARG']), [C::STYLE_BOLD, C::STYLE_UNDERLINE, C::COLOR_BLUE])); // //$a = C::read(); // //C::writeln($a); // //// fwrite(STDOUT, $colors->getColoredString("Testing Colors class, this is purple string on yellow background.", "purple", "yellow") . "\n"); //// $line = fgets(STDIN); //// if(trim($line) != 'yes'){ //// echo "ABORTING!\n"; //// exit; //// } //// echo "\n"; //// echo "Thank you, continuing...\n"; //// return true; // } // } }
/** * Создание виртуального диска в Windows, для увеличения лимита на длину пути к файлам * @param $dir * @param bool $mkdir * @return mixed|string */ static function makeVirtualDir($dir, $mkdir = true) { if (self::$IS_WIN && mb_strlen($dir) > 248) { $dir = preg_replace('/\\\\/u', '/', $dir); $vdir = mb_substr($dir, 0, 248); $vdir = F::splitRight('/', $vdir); if ($vdir[0]) { $vdir = $vdir[0]; if (!is_dir($vdir)) { if ($mkdir) { mkdir($vdir, 0775, true); } else { return $dir; } } $dir = self::VIRT_DISK . ':/' . mb_substr($dir, mb_strlen($vdir) + 1); system('subst ' . self::VIRT_DISK . ': ' . $vdir); } } return $dir; }