/** * Processes the opt:content attribute. * @internal * @param Opt_Xml_Node $node The node with the attribute * @param Opt_Xml_Attribute $attr The recognized attribute. */ public function processAttribute(Opt_Xml_Node $node, Opt_Xml_Attribute $attr) { $result = $this->_compiler->compileExpression($attr->getValue(), false, Opt_Compiler_Class::ESCAPE_BOTH); if ($result[2] == true) { // The expression is a single variable that can be handled in a simple way. $node->addAfter(Opt_Xml_Buffer::TAG_CONTENT_BEFORE, 'if(empty(' . $result[3] . ')){ '); $node->addAfter(Opt_Xml_Buffer::TAG_CONTENT_AFTER, '} else { echo ' . $result[0] . '; } '); } else { // In more complex expressions, we store the result to a temporary variable. $node->addAfter(Opt_Xml_Buffer::TAG_CONTENT_BEFORE, ' $_cont' . $this->_nesting . ' = ' . $result[0] . '; if(empty($_cont' . $this->_nesting . ')){ '); $node->addAfter(Opt_Xml_Buffer::TAG_CONTENT_AFTER, '} else { echo $_cont' . $this->_nesting . '; } '); } $this->_nesting++; $attr->set('postprocess', true); }
/** * Processes the opt:attribute instruction tag. * @internal * @param Opt_Xml_Node $node XML node. */ public function processNode(Opt_Xml_Node $node) { $params = array('name' => array(0 => self::REQUIRED, self::EXPRESSION, null, 'parse'), 'value' => array(0 => self::OPTIONAL, self::EXPRESSION, null, 'parse'), 'ns' => array(0 => self::OPTIONAL, self::EXPRESSION, null, 'parse')); $this->_extractAttributes($node, $params); self::$_cnt++; $parent = $node->getParent(); $returnStyle = $node->get('attributeValueStyle'); $returnStyle = is_null($returnStyle) ? self::ATTR_DISPLAY : $returnStyle; if ($returnStyle == self::ATTR_DISPLAY) { if (!$node->getParent() instanceof Opt_Xml_Element) { throw new Opt_InstructionInvalidParent_Exception('opt:attribute', 'printable tag'); } $parentName = $node->getParent()->getXmlName(); if (($this->_compiler->isInstruction($parentName) || $this->_compiler->isComponent($parentName) || $this->_compiler->isBlock($parentName)) && $node->getParent()->get('call:attribute-friendly') === null) { throw new Opt_InstructionInvalidParent_Exception('opt:attribute', 'printable tag'); } // This is a bit tricky optimization. If the name is constant, there is no need to process it as a variable name. // If the name is constant, the result must contain only a string if ($params['ns'] !== null) { $trNamespace = trim($params['ns'], '\' '); if (!(substr_count($params['ns'], '\'') == 2 && substr_count($trNamespace, '\'') == 0 && $this->_compiler->isIdentifier($trNamespace))) { unset($trNamespace); } } // Using the same tricky optimization for names $trName = trim($params['name'], '\' '); if (!(substr_count($params['name'], '\'') == 2 && substr_count($trName, '\'') == 0 && $this->_compiler->isIdentifier($trName))) { unset($trName); } if (isset($trName) && $params['ns'] === null || isset($trName) && isset($trNamespace)) { $attribute = new Opt_Xml_Attribute($trName, $params['value']); if (isset($trNamespace)) { $attribute->setNamespace($trNamespace); } } else { $attribute = new Opt_Xml_Attribute('__xattr_' . self::$_cnt, $params['value']); if (isset($trNamespace)) { $attribute->addAfter(Opt_Xml_Buffer::ATTRIBUTE_NAME, 'echo \'' . $trNamespace . ':\'.' . $params['name'] . '; '); } elseif ($params['ns'] !== null) { $attribute->addAfter(Opt_Xml_Buffer::ATTRIBUTE_NAME, ' $_ns = ' . $params['ns'] . '; echo (!empty($_ns) ? $_ns.\':\' : \'\').' . $params['name'] . '; '); } else { $attribute->addAfter(Opt_Xml_Buffer::ATTRIBUTE_NAME, 'echo ' . $params['name'] . '; '); } } // Construct the value for the attribute. if ($node->hasChildren()) { // The more complex statement with opt:value nodes... list($pairs, $else) = $this->_getValuePairs($node, $params); // Now, create the IF...ELSEIF statement // We perform here a small optimization. If the "ELSE" statement is set // the value will always appear, so we can put this code directly in ATTRIBUTE_VALUE // and do not bother with temporary variables. if ($else !== null) { $destination = 'echo'; $code = ''; } else { $destination = '$_attr' . self::$_cnt . '_val = '; $code = '$_attr' . self::$_cnt . '_val = null; '; } $start = true; foreach ($pairs as $pair) { if ($start) { $code = ' if(' . $pair[0] . '){ ' . $destination . ' ' . $pair[1] . '; }'; $start = false; } else { $code .= 'elseif(' . $pair[0] . '){ ' . $destination . ' ' . $pair[1] . '; }'; } } if ($else !== null) { $code .= 'else{ ' . $destination . ' ' . $else . '; } '; $attribute->addAfter(Opt_Xml_Buffer::ATTRIBUTE_VALUE, $code); } else { $attribute->addAfter(Opt_Xml_Buffer::ATTRIBUTE_BEGIN, $code . ' if($_attr' . self::$_cnt . '_val !== null){ '); $attribute->addAfter(Opt_Xml_Buffer::ATTRIBUTE_VALUE, ' echo $_attr' . self::$_cnt . '_val; '); $attribute->addAfter(Opt_Xml_Buffer::ATTRIBUTE_END, ' } '); } } else { // The ordinary behaviour if ($params['value'] === null) { throw new Opt_AttributeNotDefined_Exception('value', $node->getXmlName()); } $attribute->addAfter(Opt_Xml_Buffer::ATTRIBUTE_VALUE, 'echo ' . $params['value'] . '; '); } } else { // In the raw mode, we simply put the raw expressions, because they will be processed // later by another instruction processor. $attribute = new Opt_Xml_Attribute('__xattr_' . self::$_cnt++, $params['value']); $attribute->addAfter(Opt_Xml_Buffer::ATTRIBUTE_NAME, $params['name']); // Construct the value for the attribute. if ($node->hasChildren()) { // The more complex statement with opt:value nodes... $attribute->set('call:values', $this->_getValuePairs($node, $params)); $attribute->addAfter(Opt_Xml_Buffer::ATTRIBUTE_VALUE, ''); } else { // The ordinary behaviour $attribute->addAfter(Opt_Xml_Buffer::ATTRIBUTE_VALUE, $params['value']); } if ($params['ns'] !== null) { $attribute->set('priv:namespace', $params['ns']); } } $node->set('priv:attr', $attribute); $node->set('postprocess', true); // Add the newly created attribute to the list of dynamic attributes in the parent tag. // If the list does not exist, then create it. if (!is_null($list = $parent->get('call:attribute'))) { array_push($list, $attribute); $parent->set('call:attribute', $list); } else { $parent->set('call:attribute', array(0 => $attribute)); } // Check, if such attribute does not exist... if ($parent->getAttribute($attribute->getXmlName()) !== null) { throw new Opt_XmlDuplicatedAttribute_Exception($attribute->getXmlName(), $parent->getXmlName()); } $parent->addAttribute($attribute); $parent->removeChild($node); }
/** * Processes the opt:if and opt:omit-tag attributes. * @internal * @param Opt_Xml_Node $node The node with the attribute * @param Opt_Xml_Attribute $attr The recognized attribute. */ public function processAttribute(Opt_Xml_Node $node, Opt_Xml_Attribute $attr) { // TODO: Add opt:omit-tag implementation, changed opt:on->opt:omit-tag, it should work as before switch ($attr->getName()) { case 'omit-tag': if (!$this->_compiler->isNamespace($node->getNamespace())) { $expr = $this->_compiler->compileExpression((string) $attr, false, Opt_Compiler_Class::ESCAPE_OFF); $node->addBefore(Opt_Xml_Buffer::TAG_OPENING_BEFORE, ' $_tag_' . $this->_cnt . ' = false; if(' . $expr[0] . '){ $_tag_' . $this->_cnt . ' = true; '); $node->addAfter(Opt_Xml_Buffer::TAG_OPENING_AFTER, ' } '); $node->addBefore(Opt_Xml_Buffer::TAG_CLOSING_BEFORE, ' if($_tag_' . $this->_cnt . ' === true){ '); $node->addAfter(Opt_Xml_Buffer::TAG_CLOSING_AFTER, ' } '); $this->_cnt++; break; } case 'if': // opt:if added to an section must be handled differently. // Wait for the section processor and add the condition in the postprocessing. if ($this->_compiler->isInstruction($node->getXmlName()) instanceof Opt_Instruction_BaseSection) { $attr->set('postprocess', true); return; } $expr = $this->_compiler->compileExpression((string) $attr, false, Opt_Compiler_Class::ESCAPE_OFF); $node->addBefore(Opt_Xml_Buffer::TAG_BEFORE, ' if(' . $expr[0] . '){ '); $node->addAfter(Opt_Xml_Buffer::TAG_AFTER, ' } '); } }
/** * Processes the opt:use attribute. * * @internal * @param Opt_Xml_Node $node The node the attribute is added to * @param Opt_Xml_Attribute $attr The found attribute. */ public function processAttribute(Opt_Xml_Node $node, Opt_Xml_Attribute $attr) { if (isset($this->_snippets[$attr->getValue()])) { array_push($this->_current, $attr->getValue()); $snippet =& $this->_snippets[$attr->getValue()]; // Move all the stuff to the fake node. if ($node->hasChildren()) { $newNode = new Opt_Xml_Element('opt:_'); $newNode->moveChildren($node); $size = sizeof($snippet); $snippet[$size] = $newNode; $attr->set('snippetObj', $snippet); $attr->set('size', $size); } $node->removeChildren(); // Process the snippets $node->set('escaping', $this->_compiler->get('escaping')); $this->_compiler->set('escaping', $snippet[0]->get('escaping')); foreach ($snippet[0] as $subnode) { $node->appendChild(clone $subnode); } $node->set('call:use', $attr->getValue()); $attr->set('postprocess', true); } }
/** * Processes the opt:single instruction attribute. * * @internal * @param Opt_Xml_Node $node XML node. * @param Opt_Xml_Attribute $attr XML attribute. * @throws Opt_AttributeInvalidNamespace_Exception */ public function processAttribute(Opt_Xml_Node $node, Opt_Xml_Attribute $attr) { if ($this->_compiler->isNamespace($node->getNamespace())) { throw new Opt_AttributeInvalidNamespace_Exception($node->getXmlName()); } if ($attr->getValue() == 'yes') { $attr->set('postprocess', true); } }