Exemple #1
0
 public function all()
 {
     $field = array('type' => 'list', 'filter' => true);
     $field['labels'] = array('date' => fx::alang('Date', 'system'), 'request' => fx::alang('Request', 'system'), 'time' => fx::alang('Time', 'system'), 'entries' => fx::alang('Entries', 'system'));
     $field['values'] = array();
     $logger = fx::debug();
     $index = $logger->getIndex();
     $lost = $logger->getLost($index);
     $index = fx::collection($index)->concat($lost);
     foreach ($index as $item) {
         $url = preg_replace("~^http://[^/]+~", '', $item['url']);
         $day_part = date('d.m.Y ', $item['start']);
         if ($day_part == date('d.m.Y ')) {
             $day_part = '';
         }
         $r = array('id' => $item['id'], 'date' => array('name' => $day_part . date('H:i:s', floor($item['start'])) . ':' . round($item['start'] - floor($item['start']), 3) * 1000, 'url' => '#admin.log.show(' . $item['id'] . ')'), 'request' => '[' . $item['method'] . '] ' . $item['host'] . $url, 'time' => sprintf('%.5f', $item['time']), 'entries' => $item['count_entries']);
         $field['values'][] = $r;
     }
     $this->response->breadcrumb->addItem(fx::alang('Logs'), '#admin.log.all');
     $this->response->submenu->setMenu('log');
     $fields = array();
     if (count($field['values']) > 0) {
         $fields[] = array('type' => 'button', 'label' => fx::alang('Delete all', 'system'), 'options' => array('action' => 'drop_all', 'entity' => 'log', 'fx_admin' => 'true'));
     }
     $fields[] = $field;
     return array('fields' => $fields);
 }
Exemple #2
0
 public function generate($params = array())
 {
     $form = $this->create($params);
     $form->is_generated = true;
     $form['fields'] = fx::collection();
     return $form;
 }
Exemple #3
0
 /**
  * Get infoblocks where content can be placed and displayed
  * 
  * @param type $content
  */
 public function getForContent($content)
 {
     if (!$content['type']) {
         return fx::collection();
     }
     $this->whereContent($content['type']);
     if (!$content['parent_id']) {
         $site_id = $content['site_id'] ? $content['site_id'] : fx::env('site_id');
         return $this->where('site_id', $site_id)->all();
     }
     return $this->getForPage($content['parent']);
 }
Exemple #4
0
 /**
  * find file paths inside params collection and drop them
  */
 public function getFileParams(System\Collection $params = null)
 {
     if (!$params) {
         $params = fx::collection($this['template_visual'])->concat($this['wrapper_visual']);
     }
     $res = array();
     foreach ($params as $p) {
         if (self::checkValueIsFile($p)) {
             $res[] = $p;
         }
     }
     return $res;
 }
Exemple #5
0
 public function contentExists()
 {
     static $content_by_type = null;
     if (is_null($content_by_type)) {
         $res = fx::db()->getResults('select `type`, count(*) as cnt ' . 'from {{floxim_main_content}} ' . 'where site_id = "' . fx::env('site_id') . '" ' . 'group by `type`');
         $content_by_type = fx::collection($res)->getValues('cnt', 'type');
     }
     $com = $this->getComponent();
     if (isset($content_by_type[$com['keyword']])) {
         return true;
     }
     foreach ($com->getAllChildren() as $child) {
         if (isset($content_by_type[$child['keyword']])) {
             return true;
         }
     }
     return false;
 }
Exemple #6
0
 protected function getFakeItems($count = 4)
 {
     $items = parent::getFakeItems(4);
     $items[1]['is_active'] = true;
     $submenu = $this->getParam('submenu');
     if ($submenu === 'none') {
         return $items;
     }
     if ($submenu === 'active') {
         $items[1]['submenu'] = parent::getFakeItems(rand(2, 4));
         return $items;
     }
     if ($submenu === 'all') {
         foreach ($items as $i) {
             $count = rand(0, 4);
             $i['submenu'] = $count === 0 ? fx::collection() : parent::getFakeItems($count);
         }
         return $items;
     }
 }
Exemple #7
0
 public function getPageInfoblocks($page_id, $layout_id = null)
 {
     if (is_null($layout_id)) {
         $layout_id = fx::env('layout');
     }
     $cache_key = $page_id . '.' . $layout_id;
     if (isset($this->_ib_cache[$cache_key])) {
         return $this->_ib_cache[$cache_key];
     }
     $c_page = $page_id === fx::env('page_id') ? fx::env('page') : fx::data('page', $page_id);
     $infoblocks = fx::data('infoblock')->getForPage($c_page)->find(function ($ib) {
         return !$ib->isLayout();
     });
     $areas = fx::collection();
     $visual = fx::data('infoblock_visual')->where('infoblock_id', $infoblocks->getValues('id'))->where('layout_id', $layout_id)->all();
     foreach ($infoblocks as $ib) {
         if (!$ib->isAvailableForUser()) {
             continue;
         }
         if ($c_visual = $visual->findOne('infoblock_id', $ib['id'])) {
             $ib->setVisual($c_visual);
         } elseif ($ib->getVisual()->get('is_stub')) {
             $suitable = new Template\Suitable();
             $suitable->suit($infoblocks, $layout_id);
         }
         if ($visual_area = $ib->getPropInherited('visual.area')) {
             $c_area = $visual_area;
         } else {
             $c_area = 'unknown';
         }
         if (!isset($areas[$c_area])) {
             $areas[$c_area] = fx::collection();
         }
         $areas[$c_area][] = $ib;
     }
     $this->_ib_cache[$cache_key] = $areas;
     return $areas;
 }
Exemple #8
0
 public function addEdit($input)
 {
     if (!isset($input['content_type'])) {
         return false;
     }
     $content_type = $input['content_type'];
     $linker = null;
     $linker_field = null;
     if (is_string($input['placeholder_linker'])) {
         $input['placeholder_linker'] = unserialize($input['placeholder_linker']);
     }
     // get the edited object
     if (isset($input['content_id']) && $input['content_id']) {
         $content = fx::data($content_type, $input['content_id']);
     } else {
         $content_type = $input['content_type'];
         $parent_page = fx::data('page', $input['parent_id']);
         $content = fx::data($content_type)->create(array('parent_id' => $input['parent_id'], 'infoblock_id' => $input['infoblock_id'], 'site_id' => $parent_page['site_id']));
         if (isset($input['placeholder_linker']) && is_array($input['placeholder_linker'])) {
             $linker = fx::data($input['placeholder_linker']['type'])->create($input['placeholder_linker']);
             $linker_field = $input['placeholder_linker']['_link_field'];
         }
     }
     $fields = array($this->ui->hidden('content_type', $content_type), $this->ui->hidden('parent_id', $content['parent_id']), $this->ui->hidden('entity', 'content'), $this->ui->hidden('action', 'add_edit'), $this->ui->hidden('data_sent', true), $this->ui->hidden('fx_admin', true));
     if ($linker) {
         $fields[] = $this->ui->hidden('placeholder_linker', serialize($input['placeholder_linker']));
     }
     $move_meta = null;
     $move_variants = array('__move_before', '__move_after');
     foreach ($move_variants as $rel_prop) {
         if (isset($input[$rel_prop]) && $input[$rel_prop]) {
             $rel_item = fx::content($input[$rel_prop]);
             if ($rel_item) {
                 $fields[] = $this->ui->hidden($rel_prop, $input[$rel_prop]);
                 $move_meta = array('item' => $rel_item, 'type' => preg_replace("~^__move_~", '', $rel_prop));
             }
             break;
         }
     }
     if (isset($input['entity_values'])) {
         $content->setFieldValues($input['entity_values'], array_keys($input['entity_values']));
     }
     if (isset($input['content_id'])) {
         $fields[] = $this->ui->hidden('content_id', $input['content_id']);
     } else {
         $fields[] = $this->ui->hidden('infoblock_id', $input['infoblock_id']);
     }
     $this->response->addFields($fields);
     if ($content->isInstanceOf('floxim.main.content')) {
         $this->response->addFields($content->getStructureFields(), '', 'content');
     }
     $content_fields = fx::collection($content->getFormFields());
     $this->response->addFields($content_fields, '', 'content');
     $is_backoffice = isset($input['mode']) && $input['mode'] == 'backoffice';
     if ($is_backoffice) {
         $this->response->addFields(array($this->ui->hidden('mode', 'backoffice'), $this->ui->hidden('reload_url', $input['reload_url'])));
     }
     $res = array('status' => 'ok');
     if (isset($input['data_sent']) && $input['data_sent']) {
         $res['is_new'] = !$content['id'];
         $set_res = $content->setFieldValues($input['content']);
         if (is_array($set_res) && isset($set_res['status']) && $set_res['status'] === 'error') {
             $res['status'] = 'error';
             $res['errors'] = $set_res['errors'];
         } else {
             foreach ($move_variants as $rel_prop) {
                 if (isset($input[$rel_prop])) {
                     $moved_entity = $linker ? $linker : $content;
                     $moved_entity[$rel_prop] = $input[$rel_prop];
                 }
             }
             try {
                 $content->save();
                 $res['saved_id'] = $content['id'];
                 if ($is_backoffice) {
                     $res['reload'] = str_replace("%d", $content['id'], $input['reload_url']);
                 }
                 if ($linker) {
                     $linker[$linker_field] = $content['id'];
                     $linker->save();
                 }
             } catch (\Exception $e) {
                 $res['status'] = 'error';
                 if ($e instanceof \Floxim\Floxim\System\Exception\EntityValidation) {
                     $res['errors'] = $e->toResponse();
                 }
             }
         }
     }
     $com_item_name = fx::data('component', $content_type)->getItemName('add');
     if (isset($input['content_id']) && $input['content_id']) {
         $res['header'] = fx::alang('Editing ', 'system') . ' <span title="#' . $input['content_id'] . '">' . $com_item_name . '</span>';
     } else {
         $res['header'] = fx::alang('Adding new ', 'system') . ' ' . $com_item_name;
         if ($move_meta) {
             //$res['header'] .= ' <span class="fx_header_notice">' . fx::alang($move_meta['type']) . ' ' . $move_meta['item']['name'] . '</span>';
         }
     }
     //$res['view'] = 'cols';
     $this->response->addFormButton('save');
     return $res;
 }
Exemple #9
0
 protected function appendHasMany($content)
 {
     // end type (for fields lot)
     $linked_type = $this->getRelatedComponent()->get('keyword');
     $new_value = fx::collection();
     foreach ($this->value as $item_id => $item_props) {
         $linked_finder = fx::data($linked_type);
         $linked_item = null;
         if (is_numeric($item_id)) {
             $linked_item = $linked_finder->where('id', $item_id)->one();
         } else {
             $is_empty = true;
             foreach ($item_props as $item_prop_val) {
                 if (!empty($item_prop_val)) {
                     $is_empty = false;
                     break;
                 }
             }
             // if all props are empty, skip this row and do nothing
             if ($is_empty) {
                 continue;
             }
             $linked_item = $linked_finder->create();
             // @todo: need more accurate check
             $content_ib = fx::data('infoblock')->where('site_id', $content['site_id'])->getContentInfoblocks($linked_item['type']);
             if (count($content_ib) > 0) {
                 $linked_item['infoblock_id'] = $content_ib->first()->get('id');
             }
         }
         $linked_item->setFieldValues($item_props);
         $new_value[] = $linked_item;
     }
     return $new_value;
 }
Exemple #10
0
 public function saveVar($input)
 {
     $result = array();
     if (isset($input['page_id'])) {
         fx::env('page_id', $input['page_id']);
     }
     $ib = fx::data('infoblock', $input['infoblock']['id']);
     if ($ib->isLayout()) {
         $root_ib = $ib->getRootInfoblock();
         $ib_visual = $root_ib->getVisual();
     } elseif ($visual_id = fx::dig($input, 'infoblock.visual_id')) {
         $ib_visual = fx::data('infoblock_visual', $visual_id);
     } else {
         $ib_visual = $ib->getVisual();
     }
     // group vars by type to process content vars first
     // because we need content id for 'content-visual' vars on adding a new entity
     $vars = fx::collection($input['vars'])->apply(function ($v) {
         if ($v['var']['type'] == 'livesearch' && !$v['value']) {
             $v['value'] = array();
         }
     })->group(function ($v) {
         return $v['var']['var_type'];
     });
     $contents = fx::collection();
     $new_entity = null;
     if (isset($input['new_entity_props'])) {
         $new_props = $input['new_entity_props'];
         $new_com = fx::component($new_props['type']);
         $new_entity = fx::content($new_props['type'])->create($new_props);
         $contents['new@' . $new_com['id']] = $new_entity;
         // we are working with linker and user pressed "add new" button to create linked entity
         if (isset($input['create_linked_entity'])) {
             $linked_entity_com = fx::component($input['create_linked_entity']);
             $linked_entity = fx::content($linked_entity_com['keyword'])->create();
             $contents['new@' . $linked_entity_com['id']] = $linked_entity;
             // bind the new entity to the linker prop
             if (isset($new_props['_link_field'])) {
                 $link_field = $new_com->getFieldByKeyword($new_props['_link_field'], true);
                 $target_prop = $link_field['format']['prop_name'];
                 $new_entity[$target_prop] = $linked_entity;
             }
         }
     }
     if (isset($vars['content'])) {
         $content_groups = $vars['content']->group(function ($v) {
             $vid = $v['var']['content_id'];
             if (!$vid) {
                 $vid = 'new';
             }
             return $vid . '@' . $v['var']['content_type_id'];
         });
         foreach ($content_groups as $content_id_and_type => $content_vars) {
             list($content_id, $content_type_id) = explode("@", $content_id_and_type);
             if ($content_id !== 'new') {
                 $c_content = fx::content($content_type_id, $content_id);
                 if (!$c_content) {
                     continue;
                 }
                 $contents[$content_id_and_type] = $c_content;
             }
             $vals = array();
             foreach ($content_vars as $var) {
                 $vals[$var['var']['name']] = $var['value'];
             }
             if (isset($contents[$content_id_and_type])) {
                 $contents[$content_id_and_type]->setFieldValues($vals, array_keys($vals));
             } else {
                 fx::log('Content not found in group', $contents, $content_id, $vals);
             }
         }
     }
     $new_id = false;
     $result['saved_entities'] = array();
     foreach ($contents as $cid => $c) {
         try {
             $c->save();
             $result['saved_entities'][] = $c->get();
             if ($cid == 'new') {
                 $new_id = $c['id'];
             }
         } catch (\Exception $e) {
             $result['status'] = 'error';
             if ($e instanceof \Floxim\Floxim\System\Exception\EntityValidation) {
                 $result['errors'] = $e->toResponse();
             }
             break;
         }
     }
     if (isset($vars['visual'])) {
         foreach ($vars['visual'] as $c_var) {
             $var = $c_var['var'];
             $value = $c_var['value'];
             $var['id'] = preg_replace("~\\#new_id\\#\$~", $new_id, $var['id']);
             $visual_set = $var['template_is_wrapper'] ? 'wrapper_visual' : 'template_visual';
             if ($value == 'null') {
                 $value = null;
             }
             $c_visual = $ib_visual[$visual_set];
             if (!is_array($c_visual)) {
                 $c_visual = array();
             }
             if ($value == 'null') {
                 unset($c_visual[$var['id']]);
             } else {
                 $c_visual[$var['id']] = $value;
             }
             $ib_visual[$visual_set] = $c_visual;
         }
         $ib_visual->save();
     }
     if (isset($vars['ib_param'])) {
         $modified_params = array();
         foreach ($vars['ib_param'] as $c_var) {
             $var = $c_var['var'];
             $value = $c_var['value'];
             if (!isset($var['stored']) || $var['stored'] && $var['stored'] != 'false') {
                 $ib->digSet('params.' . $var['name'], $value);
             }
             $modified_params[$var['name']] = $value;
         }
         if (count($modified_params) > 0) {
             $controller = $ib->initController();
             $ib->save();
             $controller->handleInfoblock('save', $ib, array('params' => $modified_params));
         }
     }
     return $result;
 }
Exemple #11
0
 /**
  * Get collection of all component's descendants and the component itself
  * @return \Floxim\Floxim\System\Collection
  */
 public function getAllVariants()
 {
     $res = fx::collection($this);
     $res->concat($this->getAllChildren());
     return $res;
 }
Exemple #12
0
 /**
  * Get list of infoblocks bound to this page or one of it's descendants
  * @param bool $with_own include page's own infoblocks
  * @return fx_collection Found infoblocks
  */
 public function getNestedInfoblocks($with_own = true)
 {
     $q = fx::data('floxim.main.page')->descendantsOf($this, false);
     $q->join('{{infoblock}}', '{{infoblock}}.page_id = {{floxim_main_content}}.id');
     $page_ids = $q->all()->getValues('id');
     if ($with_own) {
         $page_ids[] = $this['id'];
     }
     if (count($page_ids) === 0) {
         return fx::collection();
     }
     $infoblocks = fx::data('infoblock')->where('page_id', $page_ids)->all();
     return $infoblocks;
 }
Exemple #13
0
 /**
  * Force "virtual" path for the entity
  * @param array $path
  */
 public function setVirtualPath($path)
 {
     $this->path = fx::collection($path);
     $this->has_virtual_path = true;
 }
Exemple #14
0
 public function doLivesearch()
 {
     $input = $_POST;
     $params = isset($input['params']) ? (array) $input['params'] : array();
     $id_field = isset($params['id_field']) ? $params['id_field'] : 'id';
     if (isset($params['relation_field_id'])) {
         $entity_data = array();
         $field = fx::data('field')->getById((int) $params['relation_field_id']);
         if (isset($input['form_data'])) {
             $form_data = (array) $input['form_data'];
             $entity_data = isset($form_data['content']) ? $form_data['content'] : array();
             $entity_type = isset($form_data['content_type']) ? $form_data['content_type'] : null;
         }
         if (!$entity_type) {
             $entity_type = isset($params['linking_entity_type']) ? $params['linking_entity_type'] : $field['component']['keyword'];
         }
         $entity_finder = fx::data($entity_type);
         $entity_id = isset($params['entity_id']) && $params['entity_id'] ? (int) $params['entity_id'] : null;
         if ($entity_id) {
             $entity = $entity_finder->getById($entity_id);
         } else {
             $entity = $entity_finder->create();
         }
         $entity->setFieldValues($entity_data);
         $finder = $field->getTargetFinder($entity);
         if (isset($params['content_type'])) {
             $finder->hasType($params['content_type']);
         }
     } else {
         if (!isset($input['content_type'])) {
             return;
         }
         $content_type = $input['content_type'];
         $finder = fx::data($content_type);
         if ($finder instanceof \Floxim\Main\Content\Finder and $content_type != 'user') {
             $finder->where('site_id', fx::env('site')->get('id'));
         }
     }
     if (isset($input['skip_ids']) && is_array($input['skip_ids'])) {
         $finder->where($id_field, $input['skip_ids'], 'NOT IN');
     }
     if (isset($input['ids'])) {
         $finder->where($id_field, $input['ids']);
     }
     if (isset($input['conditions'])) {
         $finder->livesearchApplyConditions($input['conditions']);
     }
     $term = isset($input['term']) ? $input['term'] : '';
     $limit = isset($input['limit']) ? $input['limit'] : 20;
     $res = $finder->livesearch($term, $limit, $id_field);
     // sort items in the original way
     if (isset($input['ids'])) {
         $results = fx::collection($res['results']);
         $res['results'] = array();
         foreach ($input['ids'] as $id) {
             $item = $results->findOne($id_field, $id);
             if ($item) {
                 $res['results'][] = $item;
             }
         }
     }
     fx::complete($res);
 }
Exemple #15
0
 public function __construct($data = array(), $component_id = null)
 {
     parent::__construct($data, $component_id);
     $this['errors'] = fx::collection();
 }
Exemple #16
0
 public function getFields()
 {
     $com_id = $this->component_id;
     if (!isset(self::$content_fields_by_component[$com_id])) {
         $fields = array();
         foreach ($this->getComponent()->getAllFields() as $f) {
             $fields[$f['keyword']] = $f;
         }
         self::$content_fields_by_component[$com_id] = fx::collection($fields);
     }
     return self::$content_fields_by_component[$com_id];
 }
Exemple #17
0
 public function getFormFields()
 {
     $fields = fx::collection(parent::getFormFields());
     $pass_field = $fields->findOne('name', 'password');
     $fields->remove($pass_field);
     $fields[] = array('name' => 'password', 'type' => 'password', 'label' => $pass_field['label']);
     $fields[] = array('name' => 'confirm_password', 'type' => 'password', 'label' => fx::alang('Confirm') . ' ' . $pass_field['label']);
     return $fields;
 }
Exemple #18
0
 protected function getComponentTemplates($ctr_entity)
 {
     $controller_name = $ctr_entity['keyword'];
     $controller = fx::controller($controller_name);
     $actions = $controller->getActions();
     $templates = array();
     foreach (array_keys($actions) as $action_code) {
         $action_controller = fx::controller($controller_name . ':' . $action_code);
         $action_templates = $action_controller->getAvailableTemplates();
         foreach ($action_templates as $atpl) {
             $templates[$atpl['full_id']] = $atpl;
         }
     }
     return fx::collection($templates);
 }
Exemple #19
0
 public function suit(System\Collection $infoblocks, $layout_id)
 {
     $layout = fx::data('layout', $layout_id);
     $layout_ib = null;
     $stub_ibs = new System\Collection();
     // Collect all Infoblox without the visual part
     // Find the InfoBlock-layout
     foreach ($infoblocks as $ib) {
         if ($ib->getVisual()->get('is_stub')) {
             $stub_ibs[] = $ib;
         }
         if ($ib->isLayout()) {
             $layout_ib = $ib;
         }
     }
     $layout_rate = array();
     $all_visual = fx::data('infoblock_visual')->getForInfoblocks($stub_ibs, false);
     foreach ($all_visual as $c_vis) {
         $c_layout_id = $c_vis['layout_id'];
         $infoblocks->findOne('id', $c_vis['infoblock_id'])->setVisual($c_vis, $c_layout_id);
         if (!isset($layout_rate[$c_layout_id])) {
             $layout_rate[$c_layout_id] = 0;
         }
         // count how many visual blocks are defined for each layout
         // later we should sort this to find correct "original" layout made by human
         $layout_rate[$c_layout_id]++;
     }
     //$source_layout_id = $c_layout_id;
     $avail_layout_ids = array_keys($layout_rate);
     // temp: use first
     // $source_layout_id = $avail_layout_ids[0];
     $source_layout_id = end($avail_layout_ids);
     if (!$layout_ib) {
         $layout_ib = fx::router('front')->getLayoutInfoblock(fx::env('page'));
     }
     $area_map = array();
     if ($layout_ib->getVisual()->get('is_stub') || !$layout_ib->getTemplate()) {
         $this->adjustLayoutVisual($layout_ib, $layout_id, $source_layout_id);
         $layout_visual = $layout_ib->getVisual();
         $area_map = $layout_visual['area_map'];
     } else {
         $layout_visual = $layout_ib->getVisual();
         $old_layout_template = $layout_ib->getPropInherited('visual.template', $source_layout_id);
         if ($old_layout_template) {
             $old_areas = fx::template($old_layout_template)->getAreas();
             $new_areas = fx::template($layout_visual['template'])->getAreas();
             //$tplv['real_areas'] = $test_layout_tpl->getAreas();
             $area_map = $this->mapAreas($old_areas, $new_areas);
             $area_map = $area_map['map'];
         }
     }
     $layout_template_name = $layout_ib->getPropInherited('visual.template');
     $layout_template = fx::template($layout_template_name);
     // seems to be second call of ::getAreas(), can be cached or reused
     $c_areas = $layout_template->getAreas();
     $c_wrappers = array();
     foreach ($infoblocks as $ib) {
         $ib_visual = $ib->getVisual($layout_id);
         if (!$ib_visual['is_stub']) {
             continue;
         }
         $old_area = $ib->getPropInherited('visual.area', $source_layout_id);
         // Suit record infoblock to the area where list infoblock is placed
         if ($ib->getPropInherited('action') == 'record') {
             $content_type = $ib->getPropInherited('controller');
             $content_ibs = fx::data('infoblock')->where('page_id', $ib['page_id'])->getContentInfoblocks($content_type);
             if (count($content_ibs)) {
                 $list_ib = $content_ibs->first();
                 $list_ib_vis = $list_ib->getVisual($layout_id);
                 if ($list_ib_vis && $list_ib_vis['area']) {
                     $ib_visual['area'] = $list_ib_vis['area'];
                 }
             }
         }
         if (!$ib_visual['area']) {
             if ($old_area && isset($area_map[$old_area])) {
                 $ib_visual['area'] = $area_map[$old_area];
                 $ib_visual['priority'] = $ib->getPropInherited('visual.priority', $source_layout_id);
             } elseif (preg_match("~^grid_~", $old_area)) {
                 $ib_visual['area'] = $old_area;
             }
         }
         $ib_controller = fx::controller($ib->getPropInherited('controller'), $ib->getPropInherited('params'), $ib->getPropInherited('action'));
         $area_meta = isset($c_areas[$ib_visual['area']]) ? $c_areas[$ib_visual['area']] : null;
         $controller_templates = $ib_controller->getAvailableTemplates($layout['keyword'], $area_meta);
         $old_template = $ib->getPropInherited('visual.template', $source_layout_id);
         $used_template_props = null;
         foreach ($controller_templates as $c_tpl) {
             if ($c_tpl['full_id'] === $old_template) {
                 $ib_visual['template'] = $c_tpl['full_id'];
                 $used_template_props = $c_tpl;
                 break;
             }
         }
         if (!$ib_visual['template']) {
             $that = $this;
             $old_template_id = preg_replace("~^.*?:~", '', $old_template);
             $controller_templates = fx::collection($controller_templates);
             $controller_templates->sort(function (&$tpl) use($that, $old_template_id) {
                 $res = $that->compareNames($tpl['id'], $old_template_id);
                 $tpl['name_match'] = $res;
                 return 1 / ($res + 1);
             });
             $res_template = $controller_templates->first();
             $ib_visual['template'] = $res_template['full_id'];
             $used_template_props = $res_template;
         }
         if (!$ib_visual['area']) {
             $block_size = self::getSize($used_template_props['size']);
             $c_area = null;
             $c_area_count = 0;
             foreach ($c_areas as $ca) {
                 $area_size = self::getSize($ca['size']);
                 $area_count = self::checkSizes($block_size, $area_size);
                 if ($area_count >= $c_area_count) {
                     $c_area_count = $area_count;
                     $c_area = $ca['id'];
                 }
             }
             $ib_visual['area'] = $c_area;
         }
         $old_wrapper = $ib->getPropInherited('visual.wrapper', $source_layout_id);
         if ($old_wrapper) {
             if (!isset($c_wrappers[$c_area])) {
                 $c_wrappers[$c_area] = self::getAvailableWrappers($layout_template, $area_meta);
             }
             $old_wrapper_id = preg_replace("~^.+\\:~", '', $old_wrapper);
             $avail_wrappers = $c_wrappers[$c_area];
             if (count($avail_wrappers)) {
                 $new_wrapper = fx::collection($avail_wrappers)->sort(function ($w) use($old_wrapper_id) {
                     return 1 / (1 + Suitable::compareNames($w['name'], $old_wrapper_id));
                 })->first();
                 $ib_visual['wrapper'] = $new_wrapper['full_id'];
                 $ib_visual['wrapper_visual'] = $ib->getPropInherited('visual.wrapper_visual', $source_layout_id);
             }
         }
         //if ($old_wrapper && $area_meta) {
         if ($area_meta) {
             $area_suit = self::parseAreaSuitProp(isset($area_meta['suit']) ? $area_meta['suit'] : null);
             if ($area_suit['default_wrapper']) {
                 $ib_visual['wrapper'] = $area_suit['default_wrapper'][0];
                 $ib_visual['wrapper_visual'] = $ib->getPropInherited('visual.wrapper_visual', $source_layout_id);
             }
         }
         unset($ib_visual['is_stub']);
         $ib_visual->save();
     }
 }