Current Path : /var/www/www-root/data/www.catalog.monolith-realty.ru/bitrix/modules/iblock/lib/template/ |
Current File : /var/www/www-root/data/www.catalog.monolith-realty.ru/bitrix/modules/iblock/lib/template/engine.php |
<?php /** * Bitrix Framework * @package bitrix * @subpackage iblock */ /* \Bitrix\Main\Loader::includeModule('iblock'); $arFields = array( "IBLOCK_ID" => 422, "NAME" => "Product name", "CODE" => "main code", "IBLOCK_SECTION_ID" => 12744, "PROPERTY_VALUES" => array( "CML2_ARTICLE" => "XX-SM6-XXXXXXXXX", ), ); $element = new \Bitrix\Iblock\Template\Entity\Element(0); $element->setFields($arFields); echo "<pre>";//print_r($element); $arSkuCollection = array(); for ($i = 0; $i < 5; $i++) { $arSkuCollection[$i] = array( "IBLOCK_ID" => 423, "NAME" => null, "CODE" => "code($i)", "PROPERTY_VALUES" => array( "CML2_LINK" => $element, "1377" => "0x0555555".$i, "1875" => 1045, ), ); $sku = new \Bitrix\Iblock\Template\Entity\Element(0); $sku->setFields($arSkuCollection[$i]);//print_r($sku); $arSkuCollection[$i]["NAME"] = \Bitrix\Iblock\Template\Engine::process( $sku //,'{=this.property.cml2_link.name}: {=this.property.cml2_link.property.CML2_ARTICUL}, {=this.property.cml2_bar_code}' //,'Q{=this.code}Q' //,'Q{=this.property}Q' ,'Q{=this.property.1377}Q{=this.property.1875}Q' //,'Q{=this.property.CML2_LINK}Q' //,'Q{=this.property.CML2_LINK.name}Q' //,'Q{=this.property.CML2_LINK.code}Q' //,'Q{=this.property.CML2_LINK.property.CML2_ARTICLE}Q' //,'Q{=this.property.CML2_LINK.parent.property.str}Q' //,'Q{=this.catalog.price.base}Q' //,'Q{=this.catalog.weight}Q' //,'Q{=this.catalog.measure}Q' //,'Q{=this.catalog.store.1.name}Q' //,'Q{=catalog.store}Q' ); } echo "<pre>",htmlspecialcharsEx(print_r($arSkuCollection,1)),"</pre>"; */ namespace Bitrix\Iblock\Template; /** * Class Engine * Provides interface for templates processing. * @package Bitrix\Iblock\Template */ class Engine { /** * Takes an entity (Element, Section or Iblock) and processes the template. * <code> * if (\Bitrix\Main\Loader::includeModule('iblock')) * { * $e = new \Bitrix\Iblock\Template\Entity\Element(6369); * echo "<pre>", print_r(\Bitrix\Iblock\Template\Engine::process($e, "Name: {=this.Name}. Code:{=this.code}"), 1), "</pre>"; * } * </code> * * @param Entity\Base $entity Context entity for template processing. * @param string $template Template to make substitutions in. * * @return string */ public static function process(Entity\Base $entity, $template) { $rootNode = self::parseTemplateTree($template, new NodeRoot); return $rootNode->process($entity); } /** * Splits template by tokens and builds execution tree. * * @param string $template Source expression. * @param NodeRoot $parent Root node. * * @return NodeRoot */ protected static function parseTemplateTree($template, NodeRoot $parent) { list($template, $modifiers) = Helper::splitTemplate($template); if ($modifiers != "") $parent->setModifiers($modifiers); $parsedTemplate = preg_split('/({=|})/', $template, -1, PREG_SPLIT_DELIM_CAPTURE); while (($token = array_shift($parsedTemplate)) !== null) { $node = null; if ($token === "{=") { $node = self::parseFormula($parsedTemplate); } elseif ($token !== "") { $node = new NodeText($token); } if ($node) $parent->addChild($node); } return $parent; } /** * Parses "{=" part of the template. Moves internal pointer right behind balanced "}" * after {= a field of the entity should follow * or a function call. * * @param array[]string &$parsedTemplate Template tokens. * * @return NodeEntityField|NodeFunction|null */ protected static function parseFormula(array &$parsedTemplate) { $node = null; if (($token = array_shift($parsedTemplate)) !== null) { if (preg_match("/^([a-zA-Z0-9_]+\\.[a-zA-Z0-9_.]+)\\s*\$/", $token, $match)) { $node = new NodeEntityField($match[1]); } elseif (preg_match("/^([a-zA-Z0-9_]+)(.*)\$/", $token, $match)) { $node = new NodeFunction($match[1]); self::parseFunctionArguments($match[2], $parsedTemplate, $node); } } //Eat up to the formula end while (($token = array_shift($parsedTemplate)) !== null) { if ($token === "}") break; } return $node; } /** * Adds function arguments to a $function. * An formula may be evaluated as oa argument. * An number or * A string in double quotes. * * @param string $token Expression string. * @param array[]string &$parsedTemplate Template tokens. * @param NodeFunction $function Function object to which arguments will be added. * * @return void */ protected static function parseFunctionArguments($token, array &$parsedTemplate, NodeFunction $function) { $token = ltrim($token, " \t\n\r"); if ($token !== "") self::explodeFunctionArgument($token, $function); while (($token = array_shift($parsedTemplate)) !== null) { if ($token === "}") { array_unshift($parsedTemplate, $token); break; } elseif ($token === "{=") { $node = self::parseFormula($parsedTemplate); if ($node) $function->addParameter($node); } elseif ($token !== "") { self::explodeFunctionArgument($token, $function); } } } /** * Explodes a string into function arguments. * Numbers or strings. * * @param string $token Expression string. * @param NodeFunction $function Function object to which arguments will be added. * * @return void */ protected static function explodeFunctionArgument($token, NodeFunction $function) { if (preg_match_all("/ ( [a-zA-Z0-9_]+\\.[a-zA-Z0-9_.]+ |[0-9]+ |\"[^\"]*\" ) /x", $token, $wordList) ) { foreach ($wordList[0] as $word) { if ($word !== "") { if (preg_match("/^([a-zA-Z0-9_]+\\.[a-zA-Z0-9_.]+)\\s*\$/", $word, $match)) { $node = new NodeEntityField($match[1]); } else { $node = new NodeText(trim($word, '"')); } $function->addParameter($node); } } } } } /** * Class NodeBase * Base class for template parsed tree nodes. * @package Bitrix\Iblock\Template */ abstract class NodeBase { /** * Converts internal contents of the node into external presentation. * It's a string or an array of strings. * * @param Entity\Base $entity Sets the context of processing. * * @return string */ abstract public function process(Entity\Base $entity); } /** * Class NodeRoot * Present simple collection of child nodes * * @package Bitrix\Iblock\Template */ class NodeRoot extends NodeBase { /** @var array[int]NodeBase */ protected $children = array(); protected $modifiers = array(); /** * Appends a child to the children collection. * * @param NodeBase $child Object to be added as a child. * * @return void */ public function addChild(NodeBase $child) { $this->children[] = $child; } /** * Sets modifiers to be used at the last stage of processing. * * @param string $modifiers String which contains modifiers. * * @return void */ public function setModifiers($modifiers) { $this->modifiers = array(); foreach(Helper::splitModifiers($modifiers) as $mod) { if ($mod == "l") $modifierFunction = Functions\Fabric::createInstance("lower"); else $modifierFunction = Functions\Fabric::createInstance("translit", array( "replace_space" => mb_substr($mod, 1), )); $this->modifiers[] = $modifierFunction; } } /** * Calls process for each of it's children. * Returns concatenation of their results. * * @param Entity\Base $entity Sets the context of processing. * * @return string */ public function process(Entity\Base $entity) { $content = ""; /** @var NodeBase $child*/ foreach ($this->children as $child) { $childContent = $child->process($entity); if (is_array($childContent)) $content .= implode(" ", $childContent); else $content .= $childContent; } /** @var Functions\FunctionBase $modifier*/ foreach ($this->modifiers as $modifier) { $node = new NodeText($content); $arguments = $modifier->onPrepareParameters($entity, array($node)); $content = $modifier->calculate($arguments); } return $content; } } /** * Class NodeText * Plain text node * * @package Bitrix\Iblock\Template */ class NodeText extends NodeBase { protected $content = ""; /** * Sets text contents into $content. * * @param string $content A text to be saved. */ function __construct($content = "") { $this->content = $content; } /** * Returns text contents. * * @param Entity\Base $entity Sets the context of processing. * * @return string */ public function process(Entity\Base $entity) { return $this->content; } } /** * Class NodeEntityField * Represents an entity field in the formula. * For example: this.name * * @package Bitrix\Iblock\Template */ class NodeEntityField extends NodeBase { protected $entityField = ""; /** * Initializes the object. * $entityName and $entityField is case insensitive. * * @param string $entityField Field of the Entity. */ function __construct($entityField = "") { $this->entityField = mb_strtolower($entityField); } /** * Calls "resolve" method of the $entity. * On success returns field value of the resolved. * Otherwise returns empty string. * * @param Entity\Base $entity Sets the context of processing. * * @return string */ public function process(Entity\Base $entity) { $entityObject = $entity; $pathToField = explode(".", $this->entityField); for ($i = 0, $c = count($pathToField)-1; $i < $c; $i++) { $entityObject = $entityObject->resolve($pathToField[$i]); } if ($entityObject) return $entityObject->getField($pathToField[$c]); else return ""; } } /** * Class NodeFunction * Represents a function call in the formula. * * @package Bitrix\Iblock\Template */ class NodeFunction extends NodeBase { protected $functionName = ""; protected $parameters = array(); /** * Initialize function object. * * @param string $functionName Name of the function. Case insensitive. */ public function __construct($functionName = "") { $this->functionName = mb_strtolower($functionName); } /** * Adds new parameters to the function call. * * @param NodeBase $parameter A new parameter to be added. * * @return void */ public function addParameter(NodeBase $parameter) { $this->parameters[] = $parameter; } /** * Uses Functions\Fabric to get an instance of the function object by it's name. * On success calls onPrepareParameters, then calculate method. * Otherwise returns an empty string. * * @param Entity\Base $entity Sets the context of processing. * * @return string */ public function process(Entity\Base $entity) { $functionObject = Functions\Fabric::createInstance($this->functionName); if ($functionObject instanceof Functions\FunctionBase) { $arguments = $functionObject->onPrepareParameters($entity, $this->parameters); return $functionObject->calculate($arguments); } else { return ""; } } }