Список столбцов в таблице
762714
protected function getActualColumns($refresh = false)
  {
    if (is_null($this->actual_columns) || $refresh) {
      $m = $this->getManager();

      $q = 'SHOW COLUMNS FROM `' . $m->getPrefix() . $this->getTable() . '`';

      $this->actual_columns = false;

      if ($res = $m->query($q)->fetchAll(\PDO::FETCH_ASSOC)) {
        foreach ($res as $row) {
          $this->actual_columns[] = $row['Field'];
        }
      }
    }

    return $this->actual_columns;
  }
1156959
function () {
            // все аргументы, кроме последнего считаются необходимыми зависимостями
            var depsList = franky.toArray(arguments).slice(0, arguments.length - 1),
            // последний аргумент - функция в которую уйдут удовлетворенные зависимости
                callback = arguments[arguments.length - 1];
            // обработка зависимостей
            depsList = franky.map(depsList, function (depsItem) {
                if (!libs[depsItem]) {
                    throw new Error('Unmet dependency:' + depsItem);
                }
                // если модуль представляет из себя синглтон - кешируем его
                if (cached[depsItem]) {
                    libs[depsItem] = franky.isFunction(libs[depsItem]) ? libs[depsItem]() : libs[depsItem];
                    return libs[depsItem];
                } else {
                    return libs[depsItem]();
                }
            });

            // пробрасываем удовлетворенные зависимости
            callback.apply(this, depsList);

            return this;
        }
497836
private function adminRenderImagesList()
    {
        // Определяем текущую страницу списка
        $pg = arg('pg') ? arg('pg', 'int') : 1;

        $section = arg('section', 'int');

        $maxCount = $this->settings['useGroups'] ?
            $this->settings['groupsPerPage'] :
            $this->settings['itemsPerPage'];

        $startFrom = ($pg - 1) * $maxCount;

        /* @var Gallery_Entity_Table_AbstractContent $table */
        if ($this->settings['useGroups'])
        {
            $table = ORM::getTable($this, 'Group');
        }
        else
        {
            $table = ORM::getTable($this, 'Image');
        }

        $items = $table->findInSection($section, $maxCount, $startFrom, false);

        // Данные для подстановки в шаблон
        $vars = array();
        $vars['this'] = $this;
        $vars['page'] = Eresus_Kernel::app()->getPage();
        $vars['Eresus'] = Eresus_CMS::getLegacyKernel();
        $vars['sectionId'] = arg('section', 'int');
        $vars['items'] = $items;

        /* Шаблоны адресов действий */
        $vars['urlEdit'] = str_replace('&', '&amp;',
            Eresus_Kernel::app()->getPage()->url(array('id' => '%s')));
        $vars['urlToggle'] = str_replace('&', '&amp;',
            Eresus_Kernel::app()->getPage()->url(array('toggle' => '%s')));
        $vars['urlCover'] = str_replace('&', '&amp;',
            Eresus_Kernel::app()->getPage()->url(array('cover' => '%s')));
        $vars['urlUp'] = str_replace('&', '&amp;',
            Eresus_Kernel::app()->getPage()->url(array('up' => '%s')));
        $vars['urlDown'] = str_replace('&', '&amp;',
            Eresus_Kernel::app()->getPage()->url(array('down' => '%s')));
        $vars['urlDelete'] = str_replace('&', '&amp;',
            Eresus_Kernel::app()->getPage()->url(array('delete' => '%s')));

        $totalPages = ceil($table->countInSection($section) / $maxCount);

        if ($totalPages > 1)
        {
            $pager = new PaginationHelper($totalPages, $pg,
                Eresus_Kernel::app()->getPage()->url(array('pg' => '%s')));
            $vars['pager'] = $pager->render();
        }
        else
        {
            $vars['pager'] = '';
        }

        /* Создаём экземпляр шаблона */
        if ($this->settings['useGroups'])
        {
            $tmpl = $this->templates()->admin('image-grouped-list.html');
            // Изображения вне групп
            $table = ORM::getTable($this, 'Album');
            /* @var Gallery_Entity_Album $album */
            $album = $table->find($section);
            $vars['orphans'] = $album->getOrphans();
        }
        else
        {
            $tmpl = $this->templates()->admin('image-list.html');
        }

        // Компилируем шаблон и данные
        $html = $tmpl->compile($vars);

        return $html;
    }
427701
protected static function remind()
    {
        self::$user = null;
        if (!empty(self::$input['COOKIE']['ID'])){
            $ID = explode('|', self::$input['COOKIE']['ID']);
        }else{
            $ID = '';
        }
        // Период запоминания пользователя
        $duration = empty($ID[0])? 0 : $ID[0]; // не больше месяца (примерно)
        // Хэш пользователя для поиска (авторизации)
        $hash = empty($ID[1]) ? '' : $ID[1];
        // Если есть кука, то ищем пользователя в БД
        if ($hash){
            $result = Data::find(array(
                'from' => self::$config['users-list'],
                'select' => 'children',
                'depth' => 'max',
                'where' => array(
                    array('value', '=', $hash),
//                    array('not','is_link')
                ),
                'key' => false,
                'limit' => array(0, 1),
                'comment' => 'auth user by cookie',
            ), false);
            // Пользователь найден и не истекло время его запоминания
            if (!empty($result)){
                self::$user = $result[0];
            }
        }else{
            $hash = self::get_unique_hash();
        }
        // Новый гость
        if (!self::$user){
            self::$user = Data::create(self::$config['user'], self::$config['users-list']);
            self::$user->value($hash);
            $duration = 0;
        }
        self::remember($duration);
    }
1132571
public function adminRenderContent()
    {
        if (arg('action') == 'update')
        {
            $this->adminUpdate();
        }

        $item = Eresus_CMS::getLegacyKernel()->sections->get(Eresus_Kernel::app()->getPage()->id);
        $section = new Html_SiteSection($item);
        $form = array(
            'name' => 'contentEditor',
            'caption' => Eresus_Kernel::app()->getPage()->title,
            'width' => '100%',
            'fields' => array(array('type' => 'hidden', 'name' => 'action', 'value' => 'update')),
            'buttons' => array('apply', 'reset'),
        );

        /** @var TAdminUI $page */
        $page = Eresus_Kernel::app()->getPage();

        if ($this->settings['notes'])
        {
            $form['fields'] []= array('type' => 'memo', 'name' => 'notes', 'height' => '5',
                'value' => $section->getNotes(), 'style' => 'display: none',
                'extra' => 'id="notes-input"', 'disabled' => true);

            // TODO Переделать весь этот ужас при переходе на Eresus 3.01
            $script = <<<END
function _html_show_notes()
{
    document.getElementById('notes-button').remove();
    var n=document.getElementById('notes-input');
    n.style.display='block';
    n.removeAttribute('disabled');
}
END;
            $page->addScripts($script);

            $notes = $section->getNotes();
            if ($notes)
            {
                $form['fields'] []= array('type' => 'text', 'value' => InfoBox(nl2br($notes), ''));
                $label = 'Изменить заметку';
            }
            else
            {
                $label = 'Добавить заметку';
            }
            $form['fields'] []= array('type' => 'text',
                'value' => '<a href="javascript:_html_show_notes();" id="notes-button">' . $label . '</a>');
        }
        $form['fields'] []= array('type' => 'html', 'name' => 'content', 'height' => '400px',
                    'value' => $section->getContent());
        $form['fields'] []= array('type' => 'text', 'value' => 'Адрес страницы: <a href="'
                . $section->getClientUrl() . '">' . $section->getClientUrl() . '</a>');
        $form['fields'] []= array('type' => 'checkbox', 'name' => 'allowGET',
                    'label' => 'Разрешить передавать аргументы методом GET',
                    'value' => !$section->getOption('disallowGET', true));
        $form['fields'] []= array('type' => 'checkbox', 'name' => 'allowPOST',
                    'label' => 'Разрешить передавать аргументы методом POST',
                    'value' => !$section->getOption('disallowPOST', true));
        $form['fields'] []= array('type' => 'checkbox', 'name' => 'canonical',
                    'label' => 'Добвлять к странице мета-тег «rel="canonical"»',
                    'value' => $section->getOption('html.rel_canonical', true));

        $result = $page->renderForm($form, $item);
        return $result;
    }
62599
public function editAction()
    {
        /** @var Menus_Entity_Table_Menu $table */
        $table = ORM::getTable($this->plugin, 'Menu');
        /** @var Menus_Entity_Menu $menu */
        $menu = $table->find(arg('id', 'int'));

        if (is_null($menu))
        {
            return 'Такое меню не найдено.';
        }

        $req = Eresus_CMS::getLegacyKernel()->request;

        if ('POST' == $req['method'])
        {
            $menu->name = arg('name', 'word');
            $menu->caption = arg('caption', 'dbsafe');
            $menu->active = true;
            $menu->root = arg('root', 'int');
            $menu->rootLevel = arg('rootLevel', 'int');
            $menu->invisible = arg('invisible', 'int');
            $menu->expandLevelAuto = arg('expandLevelAuto', 'int');
            $menu->expandLevelMax = arg('expandLevelMax', 'int');
            $menu->dropDown = arg('dropDown', 'int');
            $menu->template = arg('template', 'dbsafe');

            $test = $table->findByName($menu->name);
            if (is_null($test) || $test->id == $menu->id)
            {
                $table->update($menu);
                HTTP::redirect('admin.php?mod=ext-menus&id=' . $menu->id);
            }
            else
            {
                ErrorMessage('Меню с таким именем уже есть');
            }
        }

        $form = new EresusForm($this->plugin->templates()->adminPath('form.html', false));
        $form->setValue('sections', $this->adminSectionBranch());
        $form->setValue('action', 'edit');
        $form->setValue('menu', $menu);
        $html = $form->compile();

        return $html;
    }
760320
public static function init()
    {
        /* Разрешаем только однократный вызов этого метода */
        if (self::$inited)
        {
            return;
        }

        // Устанавливаем кодировку по умолчанию для операций mb_*
        mb_internal_encoding('utf-8');

        /* Предотвращает появление ошибок, связанных с неустановленной временной зоной */
        @$timezone = date_default_timezone_get();
        date_default_timezone_set($timezone);

        self::initExceptionHandling();

        self::$inited = true;
    }
552606
public function validate()
    {
        $registers = $this->getRegisters();
        $triggerFunctions = $this->getTriggerFunctions();
        $globalActions = $this->getGlobalActions();
        $initialActions = $this->getInitialActions();
        $commonActions = $this->getCommonActions();
        $steps = $this->getSteps();
        $splits = $this->getSplits();
        $joins = $this->getJoins();


        ValidationHelper::validate($registers);
        ValidationHelper::validate($triggerFunctions);
        ValidationHelper::validate($globalActions);
        ValidationHelper::validate($initialActions);
        ValidationHelper::validate($commonActions);
        ValidationHelper::validate($steps);
        ValidationHelper::validate($splits);
        ValidationHelper::validate($joins);


        $actions = [];

        foreach ($globalActions as $action) {
            $actionId = $action->getId();
            if (array_key_exists($actionId, $actions)) {
                $errMsg = sprintf(
                    'Ошибка валидация. Действие с id %s уже существует',
                    $actionId
                );
                throw new InvalidWorkflowDescriptorException($errMsg);
            }
            $actions[$actionId] = $actionId;
        }

        foreach ($steps as $step) {
            $j = $step->getActions();

            foreach ($j as $action) {
                if (!$action->isCommon()) {
                    $actionId = $action->getId();
                    if (array_key_exists($actionId, $actions)) {
                        $errMsg = sprintf(
                            'Действие с id %s найденное у шага %s является дубликатом',
                            $actionId,
                            $step->getId()
                        );
                        throw new InvalidWorkflowDescriptorException($errMsg);
                    }
                    $actions[$actionId] = $actionId;
                }
            }
        }


        foreach ($commonActions as $action) {
            $actionId = $action->getId();
            if (array_key_exists($actionId, $actions)) {
                $errMsg = sprintf(
                    'common-action  с id %s является дубликатом',
                    $actionId
                );
                throw new InvalidWorkflowDescriptorException($errMsg);
            }
        }


        $this->validateDtd();
    }
273618
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'];
        }
    }
113338
public function postCancelBill()
	{
		$bill_id = Input::get('transaction');
		$provider_id = Input::get('shop');
		$bill = Bill::getBill($bill_id, $provider_id);

		//предполагаем ошибку
		$error = 'Счёт не найден';

		if ($bill) {
			//Если счёт отмеён, то кидаем callback и отдаём успех
			if ($bill->doCancel($bill_id)) {
				$this->sendCallback($bill_id);

				return array(
					'message' => 'Счёт отменён',
				);
			}
			$error = 'Счёт не отменён. Проверьте статус.';
		}

		//Отдаём ошибку
		return array(
			'error'   => true,
			'message' => $error,
		);
	}
1142637
function field_prep(&$item)
    {
        $item['type'] = strtolower($item['type']);
        # Метка
        if (!isset($item['label'])) $item['label'] = '';
        # Подсказка
        if (isset($item['hint'])) $item['label'] = '<span class="hint" title="'.$item['hint'].'">'.$item['label'].'</span>';
        # Маска значения
        if (isset($item['pattern']) && isset($item['name']))
            $this->validator .= "
				if (!form.".$item['name'].".value.match(".$item['pattern'].")) {
					alert('".(isset($item['errormsg'])?$item['errormsg']:sprintf(errFormPatternError, $item['name'], $item['pattern']))."');
					result = false;
					form.".$item['name'].".select();
				} else ";
        # Значение
        $item['value'] = isset($item['value']) ? $item['value']
            : (isset($item['name']) && isset($this->values[$item['name']]) ? $this->values[$item['name']]
                : (isset($item['default']) ? $item['default']
                    : '' )
            );
        # ID
        if (!isset($item['id'])) $item['id'] = '';
        # Элемент отключен
        if (!isset($item['disabled'])) $item['disabled'] = '';
        # Комментарий
        $item['comment'] = isset($item['comment']) ? ' '.$item['comment'] : '';
        # Стили
        $item['style'] = isset($item['style']) ? explode(';', $item['style']) : array();
        # Классы
        $item['class'] = isset($item['class']) ? explode(' ', $item['class']) : array();
        # Дополнительно
        if (!isset($item['extra'])) $item['extra'] = '';
    }
932034
protected function untemp()
    {
        //if ($this->is_temp){
            $this->is_temp = false;
            if (isset($this->parent)){
                if (isset($this->parent->temps[$this->code])){
                    // В родитле пермещаем себя в основной список
                    $this->parent->children[$this->code] = $this;
                    unset($this->parent->temps[$this->code]);
                }
                // Возможно, родитель тоже временный
                $this->parent->untemp();
            }
        //}
    }
950887
function write($entity)
    {

        // @todo
        // Смена родителя/прототипа требует соответсвующие сдвиги в таблице отношений
        // При смене uri нужно обновить uri подчиненных

        $attr = $entity->attributes();
        // Локальные id
        $attr['parent'] = isset($attr['parent']) ? $this->localId($attr['parent']) : 0;
        $attr['proto'] = isset($attr['proto']) ? $this->localId($attr['proto']) : 0;
        $attr['author'] = isset($attr['author']) ? $this->localId($attr['author']) : 0;//$this->localId(Auth::get_user()->uri());

        // Подбор уникального имени, если указана необходимость в этом
        if ($entity->is_changed('uri') || !$entity->is_exists()) {
            $q = $this->db->prepare('SELECT 1 FROM {objects} WHERE parent=? AND `name`=? LIMIT 0,1');
            $q->execute(array($attr['parent'], $attr['name']));
            if ($q->fetch()){
                //Выбор записи по шаблону имени с самым большим префиксом
                $q = $this->db->prepare('SELECT `name` FROM {objects} WHERE parent=? AND `name` REGEXP ? ORDER BY CAST((SUBSTRING_INDEX(`name`, "_", -1)+1) AS SIGNED) DESC LIMIT 0,1');
                $q->execute(array($attr['parent'], '^'.$attr['name'].'(_[0-9]+)?$'));
                if ($row = $q->fetch(DB::FETCH_ASSOC)){
                    preg_match('|^'.preg_quote($attr['name']).'(?:_([0-9]+))?$|u', $row['name'], $match);
                    $attr['name'].= '_'.(isset($match[1]) ? ($match[1]+1) : 1);
                }
            }
            $entity->name($attr['name']);
            $attr['uri'] = $entity->uri();
        }

        Buffer::set_entity($entity);

        // Локальный идентификатор объекта
        $attr['id'] = $this->localId($entity->uri($entity->is_exists()), true, $new_id);

        // Если смена файла, то удалить текущий файл
        if ($entity->is_changed('file')){
            $current_file = $entity->changes('file');
            if (is_string($current_file)) File::delete($entity->dir(true).$current_file);
        }
        // Если привязан файл
        if (!$entity->is_default_file()){
            if ($entity->is_file()){
                $file_attache = $entity->file();
                if (is_array($file_attache)){
                    // Загрузка файла
                    if (!($attr['file'] = Data::save_file($entity, $file_attache))){
                        $attr['file'] = '';
                    }
                }else{
                    $attr['file'] = basename($file_attache);
                }
            }else{
                // файла нет, но нужно отменить наследование файла
                $attr['file'] = '';
            }
        }else{
            $attr['file'] = '';
        }

        // Уникальность order
        // Если изменено на конкретное значение (не максимальное)
        if ($attr['order'] != Entity::MAX_ORDER && (!$entity->is_exists() || $entity->is_changed('order'))){
            // Проверка, занят или нет новый order
            $q = $this->db->prepare('SELECT 1 FROM {objects} WHERE `parent`=? AND `order`=?');
            $q->execute(array($attr['parent'], $attr['order']));
            if ($q->fetch()){
                // Сдвиг order существующих записей, чтоб освободить значение для новой
                $q = $this->db->prepare('
                    UPDATE {objects} SET `order` = `order`+1
                    WHERE `parent`=? AND `order`>=?'
                );
                $q->execute(array($attr['parent'], $attr['order']));
            }
            unset($q);
        }else
        // Новое максимальное значение для order, если объект новый или явно указано order=null
        if (!$entity->is_exists() || $attr['order'] == Entity::MAX_ORDER){
            // Порядковое значение вычисляется от максимального существующего
            $q = $this->db->prepare('SELECT MAX(`order`) m FROM {objects} WHERE parent=?');
            $q->execute(array($attr['parent']));
            if ($row = $q->fetch(DB::FETCH_ASSOC)){
                $attr['order'] = $row['m']+1;
            }
            unset($q);
        }

        $this->db->beginTransaction();

        // Если новое имя или родитель, то обновить свой URI и URI подчиненных
        if ($entity->is_changed('name') || $entity->is_changed('parent')){
            if ($entity->is_exists()){
                $current_uri = $entity->uri(true);
                $current_name = $entity->is_changed('name')? $entity->changes('name') : $attr['name'];
                // Текущий URI
                $names = F::splitRight('/', $current_uri, true);
                $uri = (isset($names[0])?$names[0].'/':'').$current_name;
                // Новый URI
                $names = F::splitRight('/', $attr['uri'], true);
                $uri_new = (isset($names[0])?$names[0].'/':'').$attr['name'];
                $entity->change('uri', $uri_new);

                // @todo Обновление URI подчиенных в базе
                // нужно знать текущий уковень вложенности и локальный id

                //
    //            $q = $this->db->prepare('UPDATE {ids}, {parents} SET {ids}.uri = CONCAT(?, SUBSTRING(uri, ?)) WHERE {parents}.parent_id = ? AND {parents}.object_id = {ids}.id AND {parents}.is_delete=0');
    //            $v = array($uri_new, mb_strlen($uri)+1, $attr['id']);
    //            $q->execute($v);
    //            // Обновление уровней вложенностей в objects
    //            if (!empty($current) && $current['parent']!=$attr['parent']){
    //                $dl = $attr['parent_cnt'] - $current['parent_cnt'];
    //                $q = $this->db->prepare('UPDATE {objects}, {parents} SET parent_cnt = parent_cnt + ? WHERE {parents}.parent_id = ? AND {parents}.object_id = {objects}.id AND {parents}.is_delete=0');
    //                $q->execute(array($dl, $attr['id']));
    //                // Обновление отношений
    //                $this->makeParents($attr['id'], $attr['parent'], $dl, true);
    //            }
                if (!empty($uri) && is_dir(DIR.$uri)){
                    // Переименование/перемещение папки объекта
                    $dir = DIR.$uri_new;
                    File::rename(DIR.$uri, $dir);
                    if ($entity->is_changed('name')){
                        // Переименование файла класса
                        File::rename($dir.'/'.$current_name.'.php', $dir.'/'.$attr['name'].'.php');
                        // Переименование .info файла
                        File::rename($dir.'/'.$current_name.'.info', $dir.'/'.$attr['name'].'.info');
                    }
                }
                unset($q);
            }
            // Обновить URI подчиненных объектов не фиксируя изменения
            $entity->updateChildrenUri();
        }

        // Если значение больше 255
        if (mb_strlen($attr['value']) > 255){
            $q = $this->db->prepare('
                INSERT INTO {text} (`id`, `value`)
                VALUES (:id, :value)
                ON DUPLICATE KEY UPDATE `value` = :value
            ');
            $q->execute(array(':id' => $attr['id'], ':value' => $attr['value']));
            $attr['value'] = mb_substr($attr['value'],0,255);
            $attr['is_text'] = 1;
        }else{
            $attr['is_text'] = 0;
        }

        // Запись
        $attr_names = array(
            'id', 'parent', 'proto', 'author', 'order', 'name', 'value', 'file', 'is_text',
            'is_draft', 'is_hidden', 'is_link', 'is_mandatory', 'is_property', 'is_relative',
            'is_default_value', 'is_default_logic', 'created', 'updated'
        );
        $cnt = sizeof($attr_names);
        // Запись объекта (создание или обновление при наличии)
        // Объект идентифицируется по id
        if (!$entity->is_exists()){
            $q = $this->db->prepare('
                INSERT INTO {objects} (`'.implode('`, `', $attr_names).'`)
                VALUES ('.str_repeat('?,', $cnt-1).'?)
                ON DUPLICATE KEY UPDATE `'.implode('`=?, `', $attr_names).'`=?
            ');
            $i = 0;
            foreach ($attr_names as $name){
                $value = $attr[$name];
                $i++;
                $type = is_int($value)? DB::PARAM_INT : (is_bool($value) ? DB::PARAM_BOOL : (is_null($value)? DB::PARAM_NULL : DB::PARAM_STR));
                $q->bindValue($i, $value, $type);
                $q->bindValue($i+$cnt, $value, $type);
            }
            $q->execute();
        }else{
            $q = $this->db->prepare('
                UPDATE {objects} SET `'.implode('`=?, `', $attr_names).'`=? WHERE id = ?
            ');
            $i = 0;
            foreach ($attr_names as $name){
                $value = $attr[$name];
                $i++;
                $type = is_int($value)? DB::PARAM_INT : (is_bool($value) ? DB::PARAM_BOOL : (is_null($value)? DB::PARAM_NULL : DB::PARAM_STR));
                $q->bindValue($i, $value, $type);
            }
            $q->bindValue(++$i, $attr['id']);
            $q->execute();
        }

        $this->db->commit();

        foreach ($entity->children() as $child){
            Data::write($child);
        }

        return true;
    }
684443
function traitEntity_formBuild() {
        $form_class = $this->getClassForm();
        $form       = new $form_class(static::getEntity());
        $form->setModel($this->model);
        $form->setAction($_SERVER['REQUEST_URI']);
        $form->setAction(\Request::getUri());
        //        dd($form);
        //::factory($this->model)
        //билдим форму, если надо - переопределяем метод "traitEntityFormBuild"
        $this->traitEntity_formAddFields($form);
        $form->addRecursiveFilter('trim');
        //        $form_builder->form->setVendor($this->getVendor())
        //                           ->setEntity($this->getEntity())
        //                           ->setDataId(isset($this->model->id) ? $this->model->id : 0);
        $this->form = $form;
        $this->traitEntity_formBuildAfter();
    }
1016199
function complete($only_mandatory = true, $only_property = true)
    {
        // Выбор подчиненных объектов
        $proto = $this->proto(null, true);
        $cond = [
            'from' => $proto,
            'select' => 'properties',
            'key' => 'name'
        ];
        if ($only_mandatory){
            $cond['where'] = [['is_mandatory','=',true]];
        }
        $props_children = Data::find($cond);
        if (!$only_property){
            // Выбор подчиненных объектов
            $cond['select'] = 'children';
            $props_children = array_merge($props_children, Data::find($cond));
        }
        // Прототипирование отсутствующих подчиненных
        foreach ($props_children as $name => $child){
            $this->{$name}->complete($only_mandatory, $only_property);
            if ($this->{$name}->order() == Entity::MAX_ORDER){
                $this->{$name}->order($props_children[$name]->order());
            }
        }
    }
1141109
function rss_body($foo_object=NULL, $foo_strip=0)
	{
		//TODO: Этот config пока используется только на лентах топиков:
		//TODO: http://www.wrk.ru/society/2014/08/topic-89787-rss.xml
		//TODO: Подумать, как сделать красиво и локально
		if(!\B2\Cfg::get('rss_skip_images') && ($image = object_property($this, 'image')))
 			$image_html = "<p>".$image->thumbnail('300x300')->html_code() . "</p>\n";
		else
			$image_html = '';

		if(($body = $this->description()))
			return $image_html . '<p>'.bors_lcml::bbh($body).'</p>';

//		if(($body = $this->source()))
//			return $image_html . '<p>'.bors_lcml::bbh($body).'</p>';

		return $image_html . '<p>'.$this->body().'</p>';
	}
1225223
static function get_cached($url, $ttl = 86400, $raw = false, $force = false, $max_length = 1000000)
	{
		//FIXME: Придумать более изящный способ
		$cache_status_save = config('cache_disabled');
		config_set('cache_disabled', false);
		debug_count_inc('bors_lib_url: get_cached('.$url.')');
		$cache = new bors_cache();
		if($cache->get('bors_lib_http.get_cached-v2', $url) && !$force)
		{
			debug_count_inc('bors_lib_url: get_cached('.$url.'):found');
			$res = $cache->last();
			config_set('cache_disabled', $cache_status_save);
			return $res;
		}

		$x = self::get_ex($url, array('is_raw' => $raw));
		$content = $x['content'];

		// Запоминаем не более одного мегабайта, а то по max_allowed_packet можно влететь.
		if(strlen($content) > $max_length)
			$content = substr($content, 0, $max_length);

		debug_count_inc('bors_lib_url: get_cached('.$url.'):store');
		$cache->set($content, $ttl);
		config_set('cache_disabled', $cache_status_save);
		return $content;
	}