Exemplo n.º 1
0
 private function parseNodeAttributes(DOMNode &$node)
 {
     if ($node->hasAttributes()) {
         foreach ($node->attributes as $attr) {
             if (strpos($attr->value, '${') !== false) {
                 $expressions = array();
                 preg_match_all('/(\\$\\{)(.*)(\\})/imsxU', $attr->value, $expressions);
                 for ($i = 0; $i < count($expressions[0]); $i++) {
                     $toReplace = $expressions[0][$i];
                     $expression = $expressions[2][$i];
                     $expressionResult = ExpressionParser::evaluate($expression, $this->dataContext);
                     switch (strtolower($attr->name)) {
                         case 'repeat':
                             // Can only loop if the result of the expression was an array
                             if (!is_array($expressionResult)) {
                                 throw new ExpressionException("Can't repeat on a singular var");
                             }
                             // Make sure the repeat variable doesn't show up in the cloned nodes (otherwise it would infinit recurse on this->parseNode())
                             $node->removeAttribute('repeat');
                             // Is a named var requested?
                             $variableName = $node->getAttribute('var') ? trim($node->getAttribute('var')) : false;
                             // Store the current 'Cur', index and count state, we might be in a nested repeat loop
                             $previousCount = isset($this->dataContext['Context']['Count']) ? $this->dataContext['Context']['Count'] : null;
                             $previousIndex = isset($this->dataContext['Context']['Index']) ? $this->dataContext['Context']['Index'] : null;
                             $previousCur = $this->dataContext['Cur'];
                             // For information on the loop context, see http://opensocial-resources.googlecode.com/svn/spec/0.9/OpenSocial-Templating.xml#rfc.section.10.1
                             $this->dataContext['Context']['Count'] = count($expressionResult);
                             foreach ($expressionResult as $index => $entry) {
                                 if ($variableName) {
                                     // this is cheating a little since we're not putting it on the top level scope, the variable resolver will check 'Cur' first though so myVar.Something will still resolve correctly
                                     $this->dataContext['Cur'][$variableName] = $entry;
                                 }
                                 $this->dataContext['Cur'] = $entry;
                                 $this->dataContext['Context']['Index'] = $index;
                                 // Clone this node and it's children
                                 $newNode = $node->cloneNode(true);
                                 // Append the parsed & expanded node to the parent
                                 $newNode = $node->parentNode->insertBefore($newNode, $node);
                                 // And parse it (using the global + loop context)
                                 $this->parseNode($newNode, true);
                             }
                             // Restore our previous data context state
                             $this->dataContext['Cur'] = $previousCur;
                             if ($previousCount) {
                                 $this->dataContext['Context']['Count'] = $previousCount;
                             } else {
                                 unset($this->dataContext['Context']['Count']);
                             }
                             if ($previousIndex) {
                                 $this->dataContext['Context']['Index'] = $previousIndex;
                             } else {
                                 unset($this->dataContext['Context']['Index']);
                             }
                             return $node;
                             break;
                         case 'if':
                             if (!$expressionResult) {
                                 return $node;
                             } else {
                                 $node->removeAttribute('if');
                             }
                             break;
                             // These special cases that only apply for certain tag types
                         // These special cases that only apply for certain tag types
                         case 'selected':
                             if ($node->tagName == 'option') {
                                 if ($expressionResult) {
                                     $node->setAttribute('selected', 'selected');
                                 } else {
                                     $node->removeAttribute('selected');
                                 }
                             } else {
                                 throw new ExpressionException("Can only use selected on an option tag");
                             }
                             break;
                         case 'checked':
                             if ($node->tagName == 'input') {
                                 if ($expressionResult) {
                                     $node->setAttribute('checked', 'checked');
                                 } else {
                                     $node->removeAttribute('checked');
                                 }
                             } else {
                                 throw new ExpressionException("Can only use checked on an input tag");
                             }
                             break;
                         case 'disabled':
                             $disabledTags = array('input', 'button', 'select', 'textarea');
                             if (in_array($node->tagName, $disabledTags)) {
                                 if ($expressionResult) {
                                     $node->setAttribute('disabled', 'disabled');
                                 } else {
                                     $node->removeAttribute('disabled');
                                 }
                             } else {
                                 throw new ExpressionException("Can only use disabled on input, button, select and textarea tags");
                             }
                             break;
                         default:
                             // On non os-template spec attributes, do a simple str_replace with the evaluated value
                             $stringVal = htmlentities(ExpressionParser::stringValue($expressionResult), ENT_QUOTES, 'UTF-8');
                             $newAttrVal = str_replace($toReplace, $stringVal, $attr->value);
                             $node->setAttribute($attr->name, $newAttrVal);
                             break;
                     }
                 }
             }
         }
     }
     // if a repeat attribute was found, don't recurse on it's child nodes, the repeat handling already did that
     if (isset($node->childNodes) && $node->childNodes->length > 0) {
         $removeNodes = array();
         // recursive loop to all this node's children
         foreach ($node->childNodes as $childNode) {
             if (($removeNode = $this->parseNode($childNode)) !== false) {
                 $removeNodes[] = $removeNode;
             }
         }
         if (count($removeNodes)) {
             foreach ($removeNodes as $removeNode) {
                 $removeNode->parentNode->removeChild($removeNode);
             }
         }
     }
     return false;
 }