示例#1
0
 /**
  * @param $uri
  * @return Entity|null
  */
 function read($uri)
 {
     if (!($entity = Buffer::get_entity($uri))) {
         // Экземпляра объекта в буфере нет, проверяем массив его атрибутов в буфере
         $info = Buffer::get_info($uri);
         if (empty($info)) {
             try {
                 // выбор по uri
                 $q = $this->db->prepare('
                     SELECT o.* FROM {ids} as i , {objects} as o
                     WHERE i.id = o.id AND i.uri = :uri
                     LIMIT 0,1
                 ');
                 $q->execute(['uri' => $uri]);
                 if ($info = $q->fetch(DB::FETCH_ASSOC)) {
                     $info['is_exists'] = true;
                     $this->_local_ids[$uri] = intval($info['id']);
                     $this->_global_ids[$info['id']] = $uri;
                     if (!empty($info['file'])) {
                         $info['is_default_file'] = false;
                     }
                     // Выборка текста
                     if (!empty($info['is_text'])) {
                         $q = $this->db->query('SELECT `value` FROM {text} WHERE id = ' . intval($info['id']));
                         if ($row = $q->fetch(DB::FETCH_ASSOC)) {
                             $info['value'] = $row['value'];
                         }
                     }
                     // вместо parent, proto, author их uri
                     $info['parent'] = $this->globalId($info['parent']);
                     $info['proto'] = $this->globalId($info['proto']);
                     $info['author'] = $this->globalId($info['author']);
                     unset($info['id'], $info['is_text']);
                 }
                 $info['uri'] = $uri;
                 // Инфо о свойствах в буфер
                 $info = Buffer::set_info($info);
             } catch (\Exception $e) {
                 return null;
             }
         }
         // Создать экземпляр без свойств
         $entity = Data::entity($info);
     }
     return $entity;
 }
示例#2
0
 /**
  * @param $cond
  * <code>
  * [
  *      'select' => 'children', //self, children, parents, heirs, protos, child, link
  *      'calc' => 'count', // false, exists, count, [sum, attr], [max, attr], [min, attr], [avg, attr]
  *      'from' => '/contents',
  *      'depth' => 1, // maximum depth
  *      'struct' => 'array', // value, object, array, tree
  *      'where' => [], //filter condition
  *      'order' => [['name', 'asc'], ['value','desc']],
  *      'limit' => [0,100],
  *      'key' => 'name', // attribute name
  *      'access' => true // check read access
  * ];
  * </code>
  * @return array
  */
 function find($cond)
 {
     // select, from, depth
     $dir = $cond['from'] === '' ? DIR : DIR . trim($cond['from'], '/') . '/';
     $objects = [];
     try {
         if ($cond['depth'] > 0) {
             if ($cond['select'] == 'properties') {
                 // Читаем, чтобы инфо о свойства попало в буфер
                 $from = $this->read($cond['from']);
                 // need for Buffer::get_props
                 if ($prop_names = Buffer::get_props($cond['from'])) {
                     foreach ($prop_names as $prop_uri) {
                         // Проверка объекта на соответствие услвоию [where]
                         if ($obj = $this->read($prop_uri)) {
                             if (!$cond['where'] || $obj->verify($cond['where'])) {
                                 $objects[] = $obj;
                                 if ($cond['calc'] == 'exists') {
                                     break;
                                 }
                             }
                         }
                     }
                 }
             } else {
                 if ($cond['select'] == 'children') {
                     // Игнорируемые директории/файлы
                     $ignore = array_flip(['.', '..', '.git']);
                     // Перебор директории в глубь. (Рекурсия на циклах)
                     if ($dh = new \DirectoryIterator($dir)) {
                         $stack = [['name' => '', 'dh' => $dh, 'depth' => $cond['depth'], 'parent' => $cond['from']]];
                         do {
                             $curr = end($stack);
                             while ($curr['dh']->valid()) {
                                 /** @var \DirectoryIterator $file */
                                 $file = $curr['dh']->current();
                                 $cur_dh = $curr['dh'];
                                 if (($name = $file->getFilename()) !== '') {
                                     if (!isset($ignore[$name])) {
                                         $uri = $curr['name'] === '' ? $curr['parent'] : $curr['parent'] . '/' . $curr['name'];
                                         if ($name == $curr['name'] . '.info') {
                                             if (!($obj = Buffer::get_entity($uri))) {
                                                 if (!($info = Buffer::get_info($uri))) {
                                                     // Все сведения об объекте в формате json (если нет класса объекта)
                                                     $f = file_get_contents($file->getPathname());
                                                     $info = json_decode($f, true);
                                                     $error = json_last_error();
                                                     if ($error != JSON_ERROR_NONE) {
                                                         $info = [];
                                                         //                                                        throw new \Exception('Ошибка в "' . $curr['dir'] . $name . '"');
                                                     }
                                                     $info['uri'] = $uri;
                                                     if (!empty($info['file'])) {
                                                         $info['is_default_file'] = false;
                                                         //                                                    $info['is_file'] = true;
                                                         //                                                    $info['value'] = $info['file'];
                                                     }
                                                     if (!empty($info['logic'])) {
                                                         $info['is_default_logic'] = false;
                                                     }
                                                     if (!isset($info['is_default_logic'])) {
                                                         $info['is_default_logic'] = true;
                                                     }
                                                     $info['is_exists'] = true;
                                                 }
                                                 if ($info && empty($info['is_property'])) {
                                                     $info = Buffer::set_info($info);
                                                     $obj = Data::entity($info);
                                                 }
                                             }
                                             // Проверка объекта на соответствие услвоию [where]
                                             if ($obj && !$obj->is_property()) {
                                                 if (!$cond['where'] || $obj->verify($cond['where'])) {
                                                     $objects[] = $obj;
                                                     if ($cond['calc'] == 'exists') {
                                                         break;
                                                     }
                                                 }
                                             }
                                         } else {
                                             if ($curr['depth'] && $file->isDir()) {
                                                 if ($dh = new \DirectoryIterator($file->getPathname())) {
                                                     $stack[] = ['name' => $name, 'dh' => $dh, 'depth' => $curr['depth'] - 1, 'parent' => $uri];
                                                     $curr = end($stack);
                                                 }
                                             }
                                         }
                                     }
                                 }
                                 $cur_dh->next();
                             }
                             array_pop($stack);
                         } while ($stack);
                     }
                 }
             }
         }
     } catch (\Exception $e) {
     }
     // access
     // calc
     if ($cond['calc']) {
         $calc = null;
         if ($cond['calc'] == 'exists') {
             $calc = !empty($objects);
         } else {
             if ($cond['calc'] == 'count') {
                 $calc = count($objects);
             } else {
                 if (is_array($cond['calc']) && count($cond['calc']) == 2) {
                     $attr = $cond['calc'][1];
                     foreach ($objects as $o) {
                         switch ($cond['calc'][0]) {
                             case 'min':
                                 $calc = $calc === null ? $o->attr($attr) : min($o->attr($attr), $calc);
                                 break;
                             case 'max':
                                 $calc = $calc === null ? $o->attr($attr) : max($o->attr($attr), $calc);
                                 break;
                             case 'sum':
                             case 'avg':
                             default:
                                 $calc += $o->attr($attr);
                                 break;
                         }
                     }
                     if ($objects && $cond['calc'][0] == 'avg') {
                         $calc = $calc / count($objects);
                     }
                 }
             }
         }
         return $calc;
     }
     // order
     if ($order = $cond['order']) {
         $order_cnt = count($order);
         usort($objects, function ($a, $b) use($order, $order_cnt) {
             /** @var $a Entity */
             /** @var $b Entity */
             $i = 0;
             do {
                 if (count($order[$i]) == 3) {
                     $a = $a->{$order[$i][0]};
                     $b = $b->{$order[$i][0]};
                     array_shift($order[$i]);
                 }
                 $a = $a ? $a->{$order}[$i][0]() : null;
                 $b = $b ? $b->{$order}[$i][0]() : null;
                 if ($a == $b) {
                     $comp = 0;
                 } else {
                     $comp = $a > $b || $a === null ? 1 : -1;
                     if ($order[$i][1] == 'desc') {
                         $comp = -$comp;
                     }
                 }
                 $i++;
             } while ($comp == 0 && $i < $order_cnt);
             return $comp;
         });
     }
     // limit (not for value and object)
     if ($cond['limit']) {
         $objects = array_slice($objects, $cond['limit'][0], $cond['limit'][1]);
     }
     // struct, key
     if ($cond['struct'] == 'tree') {
         $first_level = mb_substr_count($cond['from'], '/') + 1;
         $tree = [];
         $result = [];
         foreach ($objects as $obj) {
             $tree[$obj->uri()] = ['object' => $obj, 'sub' => []];
             if ($obj->depth() == $first_level) {
                 $key = $cond['key'] ? $obj->attr($cond['key']) : null;
                 if ($key) {
                     $result[$key] =& $tree[$obj->uri()];
                 } else {
                     $result[] =& $tree[$obj->uri()];
                 }
             }
         }
         foreach ($tree as $uri => $obj) {
             $key = $cond['key'] ? $obj['object']->attr($cond['key']) : null;
             $p = $obj['object']->attr('parent');
             if (isset($tree[$p])) {
                 if ($key) {
                     $tree[$p]['sub'][$key] =& $tree[$uri];
                 } else {
                     $tree[$p]['sub'][] =& $tree[$uri];
                 }
             }
         }
         return $result;
     } else {
         if ($cond['struct'] == 'array' && $cond['key']) {
             $result = [];
             /** @var Entity $item */
             foreach ($objects as $item) {
                 $result[$item->attr($cond['key'])] = $item;
             }
             return $result;
         }
     }
     return $objects;
 }
示例#3
0
文件: Entity.php 项目: boolive/core
 /**
  * Конструктор
  * @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);
 }