public function getAvailableTemplates($layout_name = null, $area_meta = null) { $area_size = Template\Suitable::getSize($area_meta['size']); $layout_defined = !is_null($layout_name); if (is_numeric($layout_name)) { $layout_names = array(fx::data('layout', $layout_name)->get('keyword')); } elseif (is_null($layout_name)) { $layout_names = fx::data('layout')->all()->getValues('keyword'); } elseif (is_string($layout_name)) { $layout_names = array($layout_name); } elseif (is_array($layout_name)) { $layout_names = $layout_name; } // get acceptable controller $controller_variants = $this->getControllerVariants(); foreach ($controller_variants as $controller_variant) { fx::template()->import($controller_variant); } // this will be used to restrict allowed templates by config 'ignore' directive $theme_template = null; $layout_classes = array(); foreach ($layout_names as $layout_name) { $layout_classes[] = fx::template()->import('theme.' . $layout_name); } if (count($layout_names) === 1) { $theme_template = fx::template('theme.' . end($layout_names)); } $imported_classes = fx::template()->getImportedClasses(); $template_variants = array(); foreach ($imported_classes as $class) { if (!$class) { continue; } // ignore templates from layouts not listed in arg if (preg_match("~^fx_template_theme~", $class) && !in_array($class, $layout_classes)) { continue; } $template_variants = array_merge($template_variants, call_user_func(array($class, 'getTemplateVariants'))); } // now - filtered $result = array(); $replace = array(); foreach ($template_variants as $k => $tplv) { if (isset($tplv['is_abstract'])) { continue; } if (!isset($tplv['of']) || !is_array($tplv['of'])) { continue; } foreach ($tplv['of'] as $tpl_of => $tpl_of_priority) { $of_parts = explode(":", $tpl_of); if (count($of_parts) != 2) { continue; } list($tpl_of_controller, $tpl_of_action) = $of_parts; $tpl_of_action = fx::util()->underscoreToCamel($tpl_of_action, false); if (!in_array($tpl_of_controller, $controller_variants)) { continue; } // the first controller variant is the most precious if (strpos($this->action, $tpl_of_action) !== 0) { continue; } // if template action exactly matches current controller action $tplv['action_match_rate'] = $this->action == $tpl_of_action ? 1 : 0; if (isset($tplv['suit']) && $area_meta) { $tplv_areas = explode(",", preg_replace("~\\s+~", '', $tplv['suit'])); if (in_array('local', $tplv_areas)) { $tplv_areas[] = $tplv['area']; } if (!in_array($area_meta['id'], $tplv_areas)) { continue; } } // if current layout is defined, we should rate layout templates greater than standard ones $tplv['layout_match_rate'] = $layout_defined && preg_match("~^theme\\.~", $tplv['full_id']) ? 1 : 0; if ($area_size && isset($tplv['size'])) { $size = Template\Suitable::getSize($tplv['size']); $size_rate = Template\Suitable::checkSizes($size, $area_size); if (!$size_rate) { continue; } $tplv['size_rate'] = $size_rate; } if ($theme_template && !$theme_template->isTemplateAllowed($tplv['full_id'])) { continue; } if (!isset($tplv['of_priority']) || $tplv['of_priority'] < $tpl_of_priority) { $tplv['of_priority'] = $tpl_of_priority; } $result[$tplv['full_id']] = $tplv; if ($tplv['is_preset_of'] && $tplv['replace_original']) { $replace[] = $tplv['is_preset_of']; } } } foreach ($replace as $rep_id) { unset($result[$rep_id]); } usort($result, function ($a, $b) { $action_diff = $b['action_match_rate'] - $a['action_match_rate']; if ($action_diff != 0) { return $action_diff; } $prior_diff = $b['of_priority'] - $a['of_priority']; if ($prior_diff !== 0) { return $prior_diff; } $layout_diff = $b['layout_match_rate'] - $a['layout_match_rate']; if ($layout_diff != 0) { return $layout_diff; } return 0; }); return $result; }
public function getLayoutInfoblock($page) { if (!is_object($page)) { fx::log(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS)); } $path = $page->getPath()->copy()->reverse(); foreach ($path as $c_page) { if (method_exists($c_page, 'getLayoutInfoblock')) { $layout_ib = $c_page->getLayoutInfoblock(); break; } } if ($layout_ib->getVisual()->get('is_stub') || !$layout_ib->getTemplate()) { $suitable = new Template\Suitable(); //$infoblocks = $page->getPageInfoblocks(); $infoblocks = fx::data('infoblock')->getForPage($page); // delete all parent layouts from collection $infoblocks->findRemove(function ($ib) use($layout_ib) { return $ib->isLayout() && $ib['id'] !== $layout_ib['id']; }); $suitable->suit($infoblocks, fx::env('layout_id')); return $infoblocks->findOne(function ($ib) { return $ib->isLayout(); }); } return $layout_ib; }
protected function getFormatFields(CompInfoblock\Entity $infoblock, $area_meta = null) { $i2l = $infoblock->getVisual(); $fields = array(array('label' => "Area", 'name' => 'area', 'value' => $i2l['area'], 'type' => 'hidden')); $layout_name = fx::data('layout', $i2l['layout_id'])->get('keyword'); $controller_name = $infoblock->getPropInherited('controller'); $action_name = $infoblock->getPropInherited('action'); $area_suit = Template\Suitable::parseAreaSuitProp(isset($area_meta['suit']) ? $area_meta['suit'] : ''); $force_wrapper = $area_suit['force_wrapper']; $default_wrapper = $area_suit['default_wrapper']; $wrappers = array(); $c_wrapper = ''; if (!$force_wrapper) { $wrappers[''] = fx::alang('With no wrapper', 'system'); if ($i2l['id'] || !$default_wrapper) { $c_wrapper = $i2l['wrapper']; } else { $c_wrapper = $default_wrapper[0]; } } // Collect available wrappers $layout_tpl = fx::template('theme.' . $layout_name); if ($layout_tpl) { $avail_wrappers = \Floxim\Floxim\Template\Suitable::getAvailableWrappers($layout_tpl, $area_meta); foreach ($avail_wrappers as $avail_wrapper) { $wrappers[$avail_wrapper['full_id']] = $avail_wrapper['name']; } //$wrappers = array_merge($wrappers, $avail_wrappers); } // Collect the available templates $controller = fx::controller($controller_name . ':' . $action_name); $tmps = $controller->getAvailableTemplates($layout_name, $area_meta); if (!empty($tmps)) { foreach ($tmps as $template) { $templates[] = array($template['full_id'], $template['name']); } } if (count($templates) == 1) { $fields[] = array('name' => 'template', 'type' => 'hidden', 'value' => $templates[0][0]); } else { $fields[] = array('label' => fx::alang('Template', 'system'), 'name' => 'template', 'type' => 'select', 'values' => $templates, 'value' => $i2l['template']); } if ($controller_name != 'layout' && (count($wrappers) > 1 || !isset($wrappers['']))) { $fields[] = array('label' => fx::alang('Wrapper', 'system'), 'name' => 'wrapper', 'type' => 'select', 'values' => $wrappers, 'value' => $c_wrapper); } return $fields; }
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(); } }
protected function tokenAreaToCode($token) { //$token_props = var_export($token->get_all_props(),1); $token_props_parts = array(); $local_templates = self::getAreaLocalTemplates($token); $parsed_props = array(); foreach ($token->getAllProps() as $tp => $tpval) { $c_part = "'" . $tp . "' => "; if ($tp === 'suit') { $res_suit = Suitable::compileAreaSuitProp($tpval, $local_templates, $this->template_set_name); $c_val = "'" . $res_suit . "'"; } elseif (preg_match("~^`.+`\$~s", $tpval)) { $c_val = trim($tpval, '`'); } elseif (preg_match('~\\$~', $tpval)) { $c_val = $this->parseExpression($tpval); } else { $c_val = "'" . addslashes($tpval) . "'"; } $parsed_props[$tp] = $c_val; $token_props_parts[] = $c_part . $c_val; } $token_props = 'array(' . join(", ", $token_props_parts) . ')'; $res = ''; $res = '<?php $context->push(array("area_infoblocks" => fx::page()->getAreaInfoblocks(' . $parsed_props['id'] . ")));\n?>"; $render_called = false; foreach ($token->getChildren() as $child_num => $child) { if ($child->name == 'template') { $child->setProp('area', $token->getProp('id')); if (!$render_called) { if ($child_num > 0) { $res = "<?php\n" . 'if ($_is_admin) {' . "\n" . 'echo self::renderArea(' . $token_props . ', $context, \'marker\');' . "\n" . '}' . "\n?>\n" . $res . '<?php echo self::renderArea(' . $token_props . ', $context, \'data\');?>'; } else { $res .= '<?php echo self::renderArea(' . $token_props . ', $context);?>'; } $render_called = true; } $this->registerTemplate($child); } else { $res .= $this->getTokenCode($child, $token); } } if (!$render_called) { $res = '<?php echo self::renderArea(' . $token_props . ', $context);?>' . $res; } $res .= "<?php \$context->pop();\n?>"; return $res; }