templateFactory = $templateFactory; $this->fields = $fields; } /** * Validate if design configuration has recursive references * * @param DesignConfigInterface $designConfig * * @throws LocalizedException * @return void */ public function validate(DesignConfigInterface $designConfig) { /** @var DesignConfigDataInterface[] $designConfigData */ $designConfigData = $designConfig->getExtensionAttributes()->getDesignConfigData(); $elements = []; foreach ($designConfigData as $designElement) { if (!in_array($designElement->getFieldConfig()['field'], $this->fields)) { continue; } /* Save mapping between field names and config paths */ $elements[$designElement->getFieldConfig()['field']] = [ 'config_path' => $designElement->getPath(), 'value' => $designElement->getValue() ]; } foreach ($elements as $name => $data) { $templateId = $data['value']; $text = $this->getTemplateText($templateId, $designConfig); // Check if template body has a reference to the same config path if (preg_match_all(Template::CONSTRUCTION_TEMPLATE_PATTERN, $text, $constructions, PREG_SET_ORDER)) { foreach ($constructions as $construction) { $configPath = isset($construction[2]) ? $construction[2] : ''; $params = $this->getParameters($configPath); if (isset($params['config_path']) && $params['config_path'] == $data['config_path']) { throw new LocalizedException( __( 'The "%templateName" template contains an incorrect configuration, with a reference ' . 'to itself. Remove or change the reference, then try again.', ["templateName" => $name] ) ); } } } } } /** * Returns store identifier if is store scope * * @param DesignConfigInterface $designConfig * @return string|bool */ private function getScopeId(DesignConfigInterface $designConfig) { if ($designConfig->getScope() == 'stores') { return $designConfig->getScopeId(); } return false; } /** * Load template text in configured scope * * @param integer|string $templateId * @param DesignConfigInterface $designConfig * @return string */ private function getTemplateText($templateId, DesignConfigInterface $designConfig) { // Load template object by configured template id $template = $this->templateFactory->create(); $template->emulateDesign($this->getScopeId($designConfig)); if (is_numeric($templateId)) { $template->load($templateId); } else { $template->setForcedArea($templateId); $template->loadDefault($templateId); } $text = $template->getTemplateText(); $template->revertDesign(); return $text; } /** * Return associative array of parameters. * * @param string $value raw parameters * @return array */ private function getParameters($value) { $tokenizer = new ParameterTokenizer(); $tokenizer->setString($value); $params = $tokenizer->tokenize(); return $params; } }