You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@shindig.apache.org by ch...@apache.org on 2009/07/24 00:22:17 UTC

svn commit: r797247 - in /incubator/shindig/trunk/php/src/gadgets: render/GadgetBaseRenderer.php templates/ExpressionParser.php templates/TemplateLibrary.php templates/TemplateParser.php

Author: chabotc
Date: Thu Jul 23 22:22:17 2009
New Revision: 797247

URL: http://svn.apache.org/viewvc?rev=797247&view=rev
Log:
Implemented support for the OSML library and the os:Badge, os:Name and os:PeopleSelector tags, remote template libraries is still todo but minor to implement now

Modified:
    incubator/shindig/trunk/php/src/gadgets/render/GadgetBaseRenderer.php
    incubator/shindig/trunk/php/src/gadgets/templates/ExpressionParser.php
    incubator/shindig/trunk/php/src/gadgets/templates/TemplateLibrary.php
    incubator/shindig/trunk/php/src/gadgets/templates/TemplateParser.php

Modified: incubator/shindig/trunk/php/src/gadgets/render/GadgetBaseRenderer.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/render/GadgetBaseRenderer.php?rev=797247&r1=797246&r2=797247&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/render/GadgetBaseRenderer.php (original)
+++ incubator/shindig/trunk/php/src/gadgets/render/GadgetBaseRenderer.php Thu Jul 23 22:22:17 2009
@@ -36,7 +36,6 @@
   public $dataContext = array();
   public $unparsedTemplates = array();
   public $dataInserts = array();
-  public $templateLibraries = array();
 
   /**
    * Sets the $this->gadget property, and populates Msg, UserPref and ViewParams dataContext
@@ -109,7 +108,7 @@
     	// only load the template parser if there's any templates in the gadget content
     	require_once 'src/gadgets/templates/TemplateParser.php';
       require_once 'src/gadgets/templates/TemplateLibrary.php';
-    	$templateLibrary = new TemplateLibrary();
+    	$templateLibrary = new TemplateLibrary($this->gadget->gadgetContext);
     }
     foreach ($osTemplates[0] as $match) {
       if (($renderedTemplate = $this->renderTemplate($match, $templateLibrary)) !== false) {

Modified: incubator/shindig/trunk/php/src/gadgets/templates/ExpressionParser.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/templates/ExpressionParser.php?rev=797247&r1=797246&r2=797247&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/templates/ExpressionParser.php (original)
+++ incubator/shindig/trunk/php/src/gadgets/templates/ExpressionParser.php Thu Jul 23 22:22:17 2009
@@ -456,9 +456,6 @@
   static private function compute($var1, $var2, $sym) {
     $returnVal = 0;
     // JSP EL doesn't allow $A = 'foo'; $b = 1; $C = $A + $B, so make sure that both variables are numberic when doing arithmatic or boolean operations
-    if ($sym != 'empty' && (! is_numeric($var1) || ! is_numeric($var2))) {
-      throw new ExpressionException("Can't perform arithmatic or boolean operation (" . htmlentities($sym) . ") on non numeric values: " . htmlentities($var1) . ", " . htmlentities($var2) . ")");
-    }
     //TODO variable type coercion in JSP EL is different from PHP, it might be prudent to code out the same behavior
     switch ($sym) {
       // Unhandled operators

Modified: incubator/shindig/trunk/php/src/gadgets/templates/TemplateLibrary.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/templates/TemplateLibrary.php?rev=797247&r1=797246&r2=797247&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/templates/TemplateLibrary.php (original)
+++ incubator/shindig/trunk/php/src/gadgets/templates/TemplateLibrary.php Thu Jul 23 22:22:17 2009
@@ -31,10 +31,14 @@
   private $osmlTags = array('os:Name', 'os:PeopleSelector', 'os:badge');
   private $templates = array();
   private $osmlLoaded = false;
+  private $gadgetContext;
+
+  public function __construct($gadgetContext) {
+    $this->gadgetContext = $gadgetContext;
+  }
 
   public function parseTemplate($tag, $caller) {
     $template = $this->getTemplate($tag);
-    $ret = '';
     if ($template->dom instanceof DOMElement) {
       $templateDomCopy = new DOMDocument(null, 'utf-8');
       // If this template pulls in any new style and/or javascript, add those to the document
@@ -68,18 +72,98 @@
    *
    * @param DOMElement $node
    */
-  public function addTemplateByNode(DOMElement &$node) {
+  public function addTemplateByNode(DOMElement &$node, $scripts = false, $styles = false) {
     $tag = $node->getAttribute('tag');
-    $this->templates[$tag] = new TemplateLibraryEntry($node);
+    $template = new TemplateLibraryEntry($node);
+    if ($scripts) {
+      foreach ($scripts as $script) {
+        $template->addScript($script);
+      }
+    }
+    if ($styles) {
+      foreach ($styles as $style) {
+        $template->addstyle($style);
+      }
+    }
+    $this->templates[$tag] = $template;
+  }
+
+  private function addTemplateDef(DOMElement &$node, $globalScript, $globalStyle) {
+    $tag = $node->getAttribute('tag');
+    if (empty($tag)) {
+      throw new ExpressionException("Missing tag attribute on TemplateDef element");
+    }
+    $templateNodes = array();
+    foreach ($node->childNodes as $childNode) {
+      if (isset($childNode->tagName)) {
+        switch ($childNode->tagName) {
+          case 'Template':
+            $templateNodes[] = $childNode;
+            break;
+          case 'JavaScript':
+            $globalScript[] = new TemplateLibraryContent($childNode->nodeValue);
+            break;
+          case 'Style':
+            $globalStyle[] = new TemplateLibraryContent($childNode->nodeValue);
+            break;
+        }
+      }
+    }
+    // Initialize the templates after scanning the entire structure so that all scripts and styles will be included with each template
+    foreach ($templateNodes as $templateNode) {
+    	$templateNode->setAttribute('tag', $tag);
+      $this->addTemplateByNode($templateNode, $globalScript, $globalStyle);
+    }
   }
 
   /**
-   * Add an external template library by URL
+   * Add a template library set, for details see:
+   * http://opensocial-resources.googlecode.com/svn/spec/0.9/OpenSocial-Templating.xml#rfc.section.13
    *
-   * @param string $libraryUrl (ie: 'http://www.example.com/templates.xml')
+   * @param string $library
    */
-  public function addTemplateLibrary($libraryUrl) {// add library by external URL and addTemplate for each entry contained in it
-}
+  public function addTemplateLibrary($library) {
+    libxml_use_internal_errors(true);
+    $doc = new DOMDocument(null, 'utf-8');
+    $doc->preserveWhiteSpace = true;
+    $doc->formatOutput = false;
+    $doc->strictErrorChecking = false;
+    $doc->recover = false;
+    $doc->resolveExternals = false;
+    if (! $doc->loadXML($library)) {
+      throw new ExpressionException("Error parsing template library:\n" . XmlError::getErrors($library));
+    }
+    // Theoretically this could support multiple <Templates> root nodes, which isn't quite spec, but owell
+    foreach ($doc->childNodes as $rootNode) {
+      $templateNodes = array();
+	    $globalScript = array();
+	    $globalStyle = array();
+      if (isset($rootNode->tagName) && $rootNode->tagName == 'Templates') {
+        foreach ($rootNode->childNodes as $childNode) {
+          if (isset($childNode->tagName)) {
+            switch ($childNode->tagName) {
+              case 'TemplateDef':
+                $this->addTemplateDef($childNode, $globalScript, $globalStyle);
+                break;
+              case 'Template':
+                $templateNodes[] = $childNode;
+                break;
+              case 'JavaScript':
+                $globalScript[] = new TemplateLibraryContent($childNode->nodeValue);
+                break;
+              case 'Style':
+                $globalStyle[] = new TemplateLibraryContent($childNode->nodeValue);
+                break;
+            }
+          }
+        }
+      }
+      // Initialize the templates after scanning the entire structure so that all scripts and styles will be included with each template
+      foreach ($templateNodes as $templateNode) {
+        $this->addTemplateByNode($templateNode, $globalScript, $globalStyle);
+      }
+    }
+  }
 
   /**
    * Check to see if a template with name $tag exists
@@ -105,15 +189,20 @@
   }
 
   private function loadOsmlLibrary() {
+    $container = $this->gadgetContext->getContainer();
+    $containerConfig = $this->gadgetContext->getContainerConfig();
+    $gadgetsFeatures = $containerConfig->getConfig($container, 'gadgets.features');
+    if (! isset($gadgetsFeatures['osml'])) {
+      throw new ExpressionException("Missing OSML configuration key in config/config.js");
+    } elseif (! isset($gadgetsFeatures['osml']['library'])) {
+      throw new ExpressionException("Missing OSML.Library configuration key in config/config.js");
+    }
+    $osmlLibrary = Config::get('container_path') . str_replace('config/', '', $gadgetsFeatures['osml']['library']);
+    if (! File::exists($osmlLibrary)) {
+      throw new ExpressionException("Missing OSML Library ($osmlLibrary)");
+    }
+    $this->addTemplateLibrary(file_get_contents($osmlLibrary));
     $this->osmlLoaded = true;
-    // preload osml lib, see container config key for location (gadget context->container config->osml->library
-  /*
-    "osml": {
-     // OSML library resource.  Can be set to null or the empty string to disable OSML
-     // for a container.
-     "library": "config/OSML_library.xml"
-   }
-   */
   }
 }
 
@@ -138,8 +227,8 @@
    *
    * @param unknown_type $script
    */
-  public function addScript($script) {
-    $this->script[] = new TemplateLibraryContent($script);
+  public function addScript(TemplateLibraryContent $script) {
+    $this->script[] = $script;
   }
 
   /**
@@ -147,7 +236,7 @@
    *
    * @param unknown_type $style
    */
-  public function addStyle($style) {
+  public function addStyle(TemplateLibraryContent $style) {
     $this->style[] = new TemplateLibraryContent($style);
   }
 

Modified: incubator/shindig/trunk/php/src/gadgets/templates/TemplateParser.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/templates/TemplateParser.php?rev=797247&r1=797246&r2=797247&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/templates/TemplateParser.php (original)
+++ incubator/shindig/trunk/php/src/gadgets/templates/TemplateParser.php Thu Jul 23 22:22:17 2009
@@ -76,8 +76,14 @@
     }
   }
 
-  private function parseLibrary($tagName, DOMNode &$node) {
-    // loop through attributes and assign vars to the context
+  /**
+   * Misc function that maps the node's attributes to a key => value array
+   * and results any expressions to actual values
+   *
+   * @param DOMElement $node
+   * @return array
+   */
+  private function nodeAttributesToScope(DOMElement &$node) {
     $myContext = array();
     if ($node->hasAttributes()) {
       foreach ($node->attributes as $attr) {
@@ -95,21 +101,32 @@
         }
       }
     }
+    return $myContext;
+  }
 
-    // Parse the template library
+  /**
+   * Parses the specified template library
+   *
+   * @param string $tagName
+   * @param DOMNode $node
+   */
+  private function parseLibrary($tagName, DOMNode &$node) {
+    $myContext = $this->nodeAttributesToScope($node);
+    // Parse the template library (store the My scope since this could be a nested call)
+    $previousMy = $this->dataContext['My'];
     $this->dataContext['My'] = $myContext;
     $ret = $this->templateLibrary->parseTemplate($tagName, $this);
-    $this->dataContext['My'] = array();
+    $this->dataContext['My'] = $previousMy;
 
     if ($ret) {
-	    // And replace the node with the parsed output
-	    $ownerDocument = $node->ownerDocument;
-	    foreach ($ret->childNodes as $childNode) {
-	    	if ($childNode instanceOf DOMElement) {
-	        $importedNode = $ownerDocument->importNode($childNode, true);
-	        $node->parentNode->insertBefore($importedNode, $node);
-	    	}
-	    }
+      // And replace the node with the parsed output
+      $ownerDocument = $node->ownerDocument;
+      foreach ($ret->childNodes as $childNode) {
+        if ($childNode instanceof DOMElement) {
+          $importedNode = $ownerDocument->importNode($childNode, true);
+          $node->parentNode->insertBefore($importedNode, $node);
+        }
+      }
       $node->parentNode->removeChild($node);
     }
   }
@@ -245,6 +262,7 @@
 
       // Control statements
 
+
       case 'os:repeat':
         if (! $node->getAttribute('expression')) {
           throw new ExpressionException("Invalid os:Repeat tag, missing expression attribute");
@@ -293,23 +311,32 @@
 
       // OSML tags (os: name space)
 
+
       case 'os:name':
+        $this->parseLibrary('os:Name', $node);
         break;
 
-      case 'os:peopleselector':
+      case 'os:badge':
+        $myContext = $this->nodeAttributesToScope();
+        $previousMy = $this->dataContext['My'];
+        $this->dataContext['My'] = $myContext;
+        $ret = $this->templateLibrary->parseTemplate('os:Badge', $this);
+        $this->dataContext['My'] = $previousMy;
         break;
 
-      case 'os:badge':
+      case 'os:peopleselector':
+        $myContext = $this->nodeAttributesToScope();
+        $previousMy = $this->dataContext['My'];
+        $this->dataContext['My'] = $myContext;
+        $ret = $this->templateLibrary->parseTemplate('os:PeopleSelector', $this);
+        $this->dataContext['My'] = $previousMy;
         break;
 
       case 'os:html':
         if (! $node->getAttribute('code')) {
           throw new ExpressionException("Invalid os:Html tag, missing code attribute");
         }
-        //FIXME this seems to not work out to well, probably need to use the original domdocument to $doc->createTextNode() to make this work
-        $newNode = new DOMText();
-        $newNode->nodeValue = $node->getAttribute('code');
-        $node->parentNode->replaceChild($newNode, $node);
+        $node->parentNode->replaceChild($node->ownerDocument->createTextNode($node->getAttribute('code')), $node);
         break;
 
       case 'os:render':
@@ -317,6 +344,7 @@
 
       // Extension - Tags
 
+
       case 'osx:flash':
         break;
 
@@ -328,6 +356,7 @@
 
       // Extension - Functions
 
+
       case 'osx:parsejson':
         break;