/** * Checks if attribute is deprecated and needs migration. * @param Opt_Xml_Attribute $attr Attribute to migrate * @return boolean If attribute needs migration */ public function attributeNeedMigration(Opt_Xml_Attribute $attr) { $name = $attr->getXmlName(); if (in_array($name, $this->_deprecatedAttributes)) { return true; } return false; }
/** * 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); }
/** * Compiles the XML attribute which may contain some dynamic data. * The method automatically recognizes the registered expression * engine and launches it. * * @param Opt_Xml_Attribute $attr The attribute to parse. */ public function compileAttribute(Opt_Xml_Attribute $attr) { $value = $attr->getValue(); if (preg_match('/^([a-zA-Z0-9\\_]+)\\:([^\\:].*)$/', $value, $found)) { switch ($found[1]) { case 'parse': $result = $this->parseExpression($found[2], $found[1], self::ESCAPE_ON, $this->_tpl->attributeModifier); $attr->addAfter(Opt_Xml_Buffer::ATTRIBUTE_VALUE, 'echo ' . $result['expression'] . '; '); break; case 'str': $result = $this->parseExpression($found[2], $found[1], self::ESCAPE_ON, $this->_tpl->attributeModifier); $attr->addAfter(Opt_Xml_Buffer::ATTRIBUTE_VALUE, 'echo ' . $result['escaped'] . '; '); break; case null: $attr->setValue($found[2]); break; } } }
/** * Processes the opt:attributes-build and opt:attributes-ignore attributes. * @internal * @param Opt_Xml_Element $node The node * @param Opt_Xml_Attribute $attr The attribute to process */ public function processAttribute(Opt_Xml_Node $node, Opt_Xml_Attribute $attr) { if ($attr->getName() == 'attributes-build') { $ignoreList = $node->getAttribute('opt:attributes-ignore'); if ($ignoreList instanceof Opt_Xml_Attribute) { $ignore = $this->_compiler->compileExpression($ignoreList->getValue(), false, Opt_Compiler_Class::ESCAPE_OFF); $ignore = $ignore[0]; } else { $ignore = 'array()'; } $expression = $this->_compiler->compileExpression($attr->getValue(), false, Opt_Compiler_Class::ESCAPE_OFF); $node->addAfter(Opt_Xml_Buffer::TAG_ENDING_ATTRIBUTES, 'echo Opt_Function::buildAttributes(' . $expression[0] . ', ' . $ignore . ', \' \'); '); } }
/** * Tries to extract a single attribute, using the specified value type. * * @final * @internal * @param Opt_Xml_Element $item The scanned XML element. * @param Opt_Xml_Attribute $attr The parsed attribute * @param Int $type The requested value type. * @return Mixed The extracted attribute value */ private final function _extractAttribute(Opt_Xml_Element $item, Opt_Xml_Attribute $attr, $type, $exprType = null) { $value = (string) $attr; switch ($type) { // An identifier, but with empty values allowed. case self::ID_EMP: if ($value == '') { return $value; } // An identifier // An identifier case self::ID: if (!preg_match('/^[a-zA-Z0-9\\_\\.]+$/', $value)) { throw new Opt_InvalidAttributeType_Exception($attr->getXmlName(), $item->getXmlName(), 'identifier'); } return $value; // A number // A number case self::NUMBER: if (!preg_match('/^\\-?([0-9]+\\.?[0-9]*)|(0[xX][0-9a-fA-F]+)$/', $value)) { throw new Opt_InvalidAttributeType_Exception($attr->getXmlName(), $item->getXmlName(), 'number'); } return $value; // Boolean value: "yes" or "no" // Boolean value: "yes" or "no" case self::BOOL: if ($value != 'yes' && $value != 'no') { throw new Opt_InvalidAttributeType_Exception($attr->getXmlName(), $item->getXmlName(), '"yes" or "no"'); } return $value == 'yes'; // A string packed into PHP expression. Can be switched to EXPRESSION. // A string packed into PHP expression. Can be switched to EXPRESSION. case self::STRING: return $value; break; // An OPT expression. // An OPT expression. case self::EXPRESSION: case self::ASSIGN_EXPR: if (strlen(trim($value)) == 0) { throw new Opt_AttributeEmpty_Exception($attr->getXmlName(), $item->getXmlName()); } if (preg_match('/^([a-zA-Z0-9\\_]{2,})\\:([^\\:].*)$/', $value, $found)) { $result = $this->_compiler->parseExpression($found[2], $found[1]); } else { $result = $this->_compiler->parseExpression($value, $exprType); } if ($result['type'] == Opt_Expression_Interface::ASSIGNMENT && $type != self::ASSIGN_EXPR) { Opt_ExpressionOptionDisabled_Exception('Assignments', 'compiler requirements'); } return $result['bare']; } }
/** * Creates a new section record, using the information from the specified node. * If the node is not a valid OPT instruction, the method scans the ancestors * to find a free opt:show node. * * The method can also initialize the attributed section, if we provide the * opt:section attribute object as the second argument. * * The method initializes also the neighbourhood of the section by parsing the * opt:show tag, if necessary and creating the enter condition. Note that it * does not start the section - the record is neither put onto the section stack * nor opt:use integration is not made. You have to use _sectionStart() in order * to fully initialize the section. * * @param Opt_Xml_Element $node * @param Opt_Xml_Attribute $attr optional * @param Array $extraAttributes optional * @return Array The section record. */ protected function _sectionCreate(Opt_Xml_Element $node, $attr = NULL, $extraAttributes = NULL) { /* First, we need to determine, whether the section is associated with * opt:show. In case of tag sections, this is done only if the node * does not contain any section attributes. */ $show = NULL; if ($attr instanceof Opt_Xml_Attribute) { $show = $this->_findShowNode($node, $attr->getValue()); if (!is_null($show)) { // In this case we can obtain the attributes from opt:show. $section = $this->_extractSectionAttributes($show, $extraAttributes); $section['show'] = $show; $section['node'] = $node; $section['attribute'] = $attr; } else { // Generate a default section record, using the $attr value and // optionally checking for the "separator" attribute in the current node. $_params = array('separator' => array(0 => self::OPTIONAL, self::EXPRESSION, NULL)); $this->_extractAttributes($node, $_params); $section = array('name' => $attr->getValue(), 'order' => 'asc', 'parent' => NULL, 'datasource' => NULL, 'display' => NULL, 'separator' => $_params['separator'], 'show' => null, 'node' => $node, 'attribute' => $attr); } } else { if (is_null($node->getAttribute('name'))) { // We must look for opt:show $show = $this->_findShowNode($node); if (is_null($show)) { throw new Opt_AttributeNotDefined_Exception('name', $node->getXmlName()); } $section = $this->_extractSectionAttributes($show, $extraAttributes); $section['show'] = $show; $section['node'] = $node; $section['attribute'] = null; } else { $section = $this->_extractSectionAttributes($node, $extraAttributes); $section['show'] = null; $section['node'] = $node; $section['attribute'] = null; } } $this->_validateSection($section); if (is_null($section['show'])) { $this->_createShowCondition($node, $section); } elseif (is_null($section['show']->get('priv:initialized'))) { $this->_createShowCondition($section['show'], $section); } // A faster way to obtain the section name associated with this section. $node->set('priv:section', $section['name']); return $section; }
/** * A postprocessing routine for opt:use * @internal * @param Opt_Xml_Node $node * @param Opt_Xml_Attribute $attr */ public function postprocessAttribute(Opt_Xml_Node $node, Opt_Xml_Attribute $attr) { if (!is_null($attr->get('size'))) { $snippet = $attr->get('snippetObj'); unset($snippet[$attr->get('size')]); } // Restore the original escaping state $this->_compiler->set('escaping', $node->get('escaping')); array_pop($this->_current); }
/** * Adds a new attribute to the tag. * * @param Opt_Xml_Attribute $attribute The new attribute. */ public function addAttribute(Opt_Xml_Attribute $attribute) { if (!is_array($this->_attributes)) { $this->_attributes = array(); } $this->_attributes[$attribute->getXmlName()] = $attribute; }
/** * 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:capture 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) { if ($this->_compiler->isIdentifier($attr->getValue())) { $node->addAfter(Opt_Xml_Buffer::TAG_BEFORE, 'ob_start(); '); $node->addBefore(Opt_Xml_Buffer::TAG_AFTER, 'self::$_capture[\'' . $attr->getValue() . '\'] = ob_get_clean();'); $this->_process($node); } else { throw new Opt_InvalidAttributeType_Exception('opt:capture', 'identifier'); } }
/** * Postprocesses the opt:single instruction attribute. * * @internal * @param Opt_Xml_Node $node XML node. * @param Opt_Xml_Attribute $attr XML attribute. */ public function postprocessAttribute(Opt_Xml_Node $node, Opt_Xml_Attribute $attr) { if ($attr->getValue() == 'yes') { $node->set('single', true); $node->removeChildren(); } }