Example #1
0
 /**
  * This helper method is the default instruction attribute handler in OPT.
  * It allows to parse the list of attributes using the specified rules.
  * The attribute configuration is passed as a second argument by reference,
  * and OPT returns the compiled attribute values in the same way.
  *
  * If the attribute specification contains "__UNKNOWN__" element, the node
  * may contain an undefined number of attributes. The undefined attributes
  * must match to the rules in "__UNKNOWN__" element and are returned by the
  * method as a separate array. For details, see the OPT user manual.
  *
  * @final
  * @param Opt_Xml_Element $subitem The scanned XML element.
  * @param Array &$config The reference to the attribute configuration
  * @return Array|Null The list of undefined attributes, if "__UNKNOWN__" is set.
  */
 protected final function _extractAttributes(Opt_Xml_Element $subitem, array &$config)
 {
     $required = array();
     $optional = array();
     $unknown = null;
     // Decide, what is what.
     foreach ($config as $name => &$data) {
         if (!isset($data[3])) {
             $data[3] = null;
         }
         if ($name == '__UNKNOWN__') {
             $unknown =& $data;
         } elseif ($data[0] == self::REQUIRED) {
             $required[$name] =& $data;
         } elseif ($data[0] == self::OPTIONAL) {
             $optional[$name] =& $data;
         }
     }
     $config = array();
     $return = array();
     $exprEngines = $this->_compiler->getExpressionEngines();
     // Parse required attributes
     $attrList = $subitem->getAttributes(false);
     foreach ($required as $name => &$data) {
         $ok = false;
         if (isset($attrList[$name])) {
             $aname = $name;
             $ok = true;
         } elseif (($data[1] == self::EXPRESSION || $data[1] == self::ASSIGN_EXPR) && $this->_tpl->backwardCompatibility == true) {
             // DEPRECATED: Legacy code for compatibility with OPT 2.0
             foreach ($exprEngines as $eeName => $eeValue) {
                 if (isset($attrList[$eeName . ':' . $name])) {
                     $aname = $eeName . ':' . $name;
                     $data[3] = $eeName;
                     $ok = true;
                     break;
                 }
             }
         }
         if (!$ok) {
             throw new Opt_AttributeNotDefined_Exception($name, $subitem->getXmlName());
         }
         $config[$name] = $this->_extractAttribute($subitem, $attrList[$aname], $data[1], $data[3]);
         unset($attrList[$aname]);
     }
     // Parse optional attributes
     foreach ($optional as $name => &$data) {
         $ok = false;
         if (isset($attrList[$name])) {
             $aname = $name;
             $ok = true;
         } elseif (($data[1] == self::EXPRESSION || $data[1] == self::ASSIGN_EXPR) && $this->_tpl->backwardCompatibility == true) {
             // DEPRECATED: Legacy code for compatibility with OPT 2.0
             foreach ($exprEngines as $eeName => $eeValue) {
                 if (isset($attrList[$eeName . ':' . $name])) {
                     $aname = $eeName . ':' . $name;
                     $data[3] = $eeName;
                     $ok = true;
                     break;
                 }
             }
         }
         if (!$ok) {
             // We can't use isset() because the default data might be "NULL"
             if (!array_key_exists(2, $data)) {
                 throw new Opt_APIMissingDefaultValue_Exception($name, $subitem->getXmlName());
             }
             $config[$name] = $data[2];
             continue;
         }
         $config[$name] = $this->_extractAttribute($subitem, $attrList[$aname], $data[1], $data[3]);
         unset($attrList[$aname]);
     }
     // The remaining tags must be processed using $unknown rule, however it
     // must be defined.
     if (!is_null($unknown)) {
         $type = $unknown[1];
         foreach ($attrList as $name => $attr) {
             try {
                 if (($type == self::EXPRESSION || $type == self::ASSIGN_EXPR) && $this->_tpl->backwardCompatibility == true) {
                     // DEPRECATED: Legacy code for compatibility with OPT 2.0
                     $exprType = $unknown[3];
                     foreach ($exprEngines as $eeName => $eeValue) {
                         if (isset($attrList[$eeName . ':' . $name])) {
                             $name = substr($name, strlen($eeName), strlen($name) - strlen($eeName));
                             $exprType = $eeName;
                             // Skip the tag, if this is a special OPT namespace.
                             if ($this->_compiler->isNamespace($exprType)) {
                                 throw new Exception();
                             }
                             break;
                         }
                     }
                 }
                 $return[$name] = $this->_extractAttribute($subitem, $attr, $type, $exprType);
             } catch (Exception $e) {
                 /* null */
             }
         }
     }
     return $return;
 }