Exemplo n.º 1
0
 /**
  * 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);
 }