public function expandMaterial(Material $material) { $rawBemJson = $material->rawBemJson(); $newMatchers = $this->applyGlobalCustomizations($material, true); /** @var \BEM\Json $expandedJson */ $expandedJson = $this->bh()->processBemJson($rawBemJson); // unload expanded $this->bh()->removeMatcherById($newMatchers); $this->cache()->set($this->cacheKey($material), $expandedJson, $this->expandedBemJsonLifetime); return $expandedJson; }
public function run() { $expandedBemJson = $this->monsterBh->expandedBemJson($this->material); $customizedBhMatchersIds = []; $content = ''; $templateFilename = $this->generateTemplateFilename(); $event = new MaterializeEvent(['material' => $this->material, 'materializeData' => &$this->data, 'uniqueContentId' => $this->uniqueContentId, 'materialIndex' => $this->materialIndex, 'customizedBhMatchersIds' => &$customizedBhMatchersIds, 'content' => &$content, 'templateFilename' => &$templateFilename, 'editMode' => $this->editMode]); if (is_readable($templateFilename) === false) { //! @todo add expire support for the template file into above condition $this->ensureTemplateFolderCreated($templateFilename); $this->trigger(static::EVENT_BEFORE_GLOBAL_CUSTOMIZATION, $event); /** @var Repository $repository */ $newBhMatchers = $this->monsterBh->applyGlobalCustomizations($this->material); $this->trigger(static::EVENT_BEFORE_CONTEXTUAL_CUSTOMIZATION, $event); // Apply edit-mode matcher if ($this->editMode === true) { if ($expandedBemJson->attrs === null) { $expandedBemJson->attrs = []; } $expandedBemJson->attrs['data-is-material'] = 1; $expandedBemJson->attrs['data-material-index'] = $this->materialIndex; $expandedBemJson->attrs['data-material-path'] = $this->material->fullPath; $expandedBemJson->cls .= ' m-monster-material'; } //! @todo Add contextual customization code here(we will need to introduce new param for materialize) $this->trigger(static::EVENT_BEFORE_TEMPLATE_CREATION, $event); Yii::beginProfile('Materialize -> Template creation'); // find editables and add them to js of block if ($this->editMode === true) { $editableKeys = []; $fillEditable = function ($editable, $root = null) use(&$editableKeys) { $editableKey = $editable['key']; $editableType = isset($editable['type']) ? $editable['type'] : 'string'; $target = isset($editable['target']) ? $editable['target'] : null; if ($root !== null && $target === 'item') { if (isset($editableKeys[$root]) === false) { $editableKeys[$root] = []; } $editableKeys[$root][$editableKey] = $editableType; } elseif ($target !== null) { if (isset($editableKeys[$target]) === false) { $editableKeys[$target] = []; } $editableKeys[$target][$editableKey] = $editableType; } else { $editableKeys[$editableKey] = $editableType; } }; $walker = function ($object, $root = null) use(&$walker, &$fillEditable) { $array = $object; if ($object instanceof Json) { if (isset($object->recursive)) { $root = $object->recursive; } if (isset($object->editable)) { $fillEditable($object->editable, $root); } foreach ($object as $key => $value) { if ($key === 'content' && $value instanceof JsonCollection) { foreach ($value as $content) { $walker($content, $root); } } elseif (is_array($value)) { $walker($value, $root); } } } else { if (is_array($array)) { foreach ($array as $key => $value) { if ($key === 'editable' && isset($value['key'])) { $fillEditable($value, $root); } elseif (is_array($value) || $value instanceof JsonCollection) { $walker($value, $root); } } } } }; $walker($expandedBemJson); $expandedBemJson->attrs['data-editable-keys'] = \yii\helpers\Json::encode($editableKeys); } // @todo Add configuration param somewhere, where we add needed classes list for generating use statements $template = <<<'php' <?php use yii\helpers\ArrayHelper; use yii\helpers\Html; use yii\helpers\Json; use yii\helpers\Url; use DotPlant\Monster\components\ViewHelpers; /** * WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES WILL BE LOST. * * Please refer to the DotPlant CMS documentation(Monster subsystem section) * on extending and modifying your look'n'feel. * * @var \yii\web\View $this * @var array $data */ ?> php; $template .= $this->monsterBh->bh()->apply($expandedBemJson); // remove applied matchers $this->monsterBh->bh()->removeMatcherById(ArrayHelper::merge($newBhMatchers, $customizedBhMatchersIds)); Yii::endProfile('Materialize -> Template creation'); if (file_put_contents($templateFilename, $template) === false) { throw new \RuntimeException("Template file can't be saved: {$templateFilename} for ({$this->uniqueContentId},{$this->materialIndex})"); } unset($template); $this->trigger(static::EVENT_AFTER_TEMPLATE_CREATION, $event); } $this->trigger(static::EVENT_BEFORE_MATERIALIZE, $event); Yii::beginProfile('Materialize -> Template render'); try { $content = $this->renderFile($templateFilename, ['data' => &$this->data]); } catch (\Exception $e) { throw new MonsterViewException($templateFilename, $this->data, $e); } Yii::endProfile('Materialize -> Template render'); $this->trigger(static::EVENT_AFTER_MATERIALIZE, $event); Yii::beginProfile('Materialize -> Publish assets'); $this->material->publishAssets(); Yii::endProfile('Materialize -> Publish assets'); return $content; }