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 2010/02/09 09:29:28 UTC

svn commit: r907966 - in /shindig/trunk/php/src/gadgets: GadgetFactory.php GadgetFeatureRegistry.php render/GadgetBaseRenderer.php render/GadgetRenderer.php render/GadgetUrlRenderer.php servlet/JsServlet.php

Author: chabotc
Date: Tue Feb  9 08:29:28 2010
New Revision: 907966

URL: http://svn.apache.org/viewvc?rev=907966&view=rev
Log:
Fix external feature code generation to include dependencies (SHINDIG-1260) by Jacky Wang

Modified:
    shindig/trunk/php/src/gadgets/GadgetFactory.php
    shindig/trunk/php/src/gadgets/GadgetFeatureRegistry.php
    shindig/trunk/php/src/gadgets/render/GadgetBaseRenderer.php
    shindig/trunk/php/src/gadgets/render/GadgetRenderer.php
    shindig/trunk/php/src/gadgets/render/GadgetUrlRenderer.php
    shindig/trunk/php/src/gadgets/servlet/JsServlet.php

Modified: shindig/trunk/php/src/gadgets/GadgetFactory.php
URL: http://svn.apache.org/viewvc/shindig/trunk/php/src/gadgets/GadgetFactory.php?rev=907966&r1=907965&r2=907966&view=diff
==============================================================================
--- shindig/trunk/php/src/gadgets/GadgetFactory.php (original)
+++ shindig/trunk/php/src/gadgets/GadgetFactory.php Tue Feb  9 08:29:28 2010
@@ -72,7 +72,7 @@
     $found = $missing = array();
     if (! $this->context->getRegistry()->resolveFeatures(
         array_merge($gadget->gadgetSpec->requiredFeatures, $gadget->gadgetSpec->optionalFeatures),
-        $found, $missing, true)) {
+        $found, $missing)) {
       $requiredMissing = false;
       foreach ($missing as $featureName) {
         if (in_array($featureName, $gadget->gadgetSpec->requiredFeatures)) {

Modified: shindig/trunk/php/src/gadgets/GadgetFeatureRegistry.php
URL: http://svn.apache.org/viewvc/shindig/trunk/php/src/gadgets/GadgetFeatureRegistry.php?rev=907966&r1=907965&r2=907966&view=diff
==============================================================================
--- shindig/trunk/php/src/gadgets/GadgetFeatureRegistry.php (original)
+++ shindig/trunk/php/src/gadgets/GadgetFeatureRegistry.php Tue Feb  9 08:29:28 2010
@@ -28,7 +28,8 @@
   public $features;
   private $coreDone = false;
   private $coreFeaturs;
-
+  private $sortedFeatures;
+  
   public function __construct($featurePath) {
     $this->registerFeatures($featurePath);
   }
@@ -86,90 +87,41 @@
     return $ret;
   }
 
-  public function resolveFeatures($needed, &$resultsFound, &$resultsMissing, $isExpand) {
+  public function resolveFeatures($needed, &$resultsFound, &$resultsMissing) {
     $resultsFound = array();
     $resultsMissing = array();
     if (! count($needed)) {
-      // Shortcut for gadgets that don't have any explicit dependencies.
-      $resultsFound = $this->coreFeatures;
-      return true;
+      $needed = $this->coreFeatures;
     }
     foreach ($needed as $featureName) {
       $feature = isset($this->features[$featureName]) ? $this->features[$featureName] : null;
       if ($feature == null) {
         $resultsMissing[] = $featureName;
       } else {
-        $this->addFeatureToResults($resultsFound, $feature, $isExpand);
+        $this->addFeatureToResults($resultsFound, $feature);
       }
     }
     return count($resultsMissing) == 0;
   }
   
-  public function sortFeatures($features, $forcedJsLibs, &$sortedFeatureGroups) {
-    $sortedFeatureGroups = array();
-    if (empty($features)) return;
-
-    // Topological sorting with constrain
-    // Build the topology matrix
-    $sortedFeatures = array();
-    $reverseDeps = array();
-    foreach ($features as $feature) {
-      $reverseDeps[$feature] = array();
-    }
-    $depCount = array();
-    foreach ($features as $feature) {
-      $deps = $this->features[$feature]['deps'];
-      $deps = array_uintersect($deps, $features, "strcasecmp");
-      $depCount[$feature] = count($deps);
-      foreach ($deps as $dep) {
-        $reverseDeps[$dep][] = $feature;
-      }
+  public function sortFeatures($features, &$sortedFeatures) {
+    if (empty($features)) {
+      return;
     }
-    
-    // iterate to do the sorting
-    $prevIsForcedJsLibs = true;
-    $featureQueue = array();
-    while (! empty($depCount)) {
-      $fail = true;
-      while (! empty($depCount)) {  // get grouped features greedily
-        $foundAll = true;
-        foreach ($depCount as $feature => $count) {
-          if ($count != 0) continue;
-          $fail = false; // found at least one root node
-          if ((! $prevIsForcedJsLibs) ^ in_array($feature, $forcedJsLibs)) {
-            $foundAll = false;
-            $featureQueue[] = $feature;
-            foreach ($reverseDeps[$feature] as $reverseDep) {
-              $depCount[$reverseDep] -= 1;
-            }
-            unset($depCount[$feature]);
-          }
-        }
-        if ($foundAll) break;
-      }
-      if ($fail) {
-        throw new GadgetException("Sorting feature dependence failed: it contains ring!");
-      }
-      if (! empty($featureQueue)) {
-        if ($prevIsForcedJsLibs) {
-          $sortedFeatureGroups[] = array('type' => 'external', 'features' => $featureQueue);
-        } else {
-          $sortedFeatureGroups[] = array('type' => 'inline', 'features' => $featureQueue);
-        }
+    $sortedFeatures = array();
+    foreach ($this->sortedFeatures as $feature) {
+      if (in_array($feature, $features)) {
+        $sortedFeatures[] = $feature;
       }
-      $prevIsForcedJsLibs = ! $prevIsForcedJsLibs;
-      $featureQueue = array();
     }
   }
   
-  private function addFeatureToResults(&$results, $feature, $isExpand) {
+  private function addFeatureToResults(&$results, $feature) {
     if (in_array($feature['name'], $results)) {
       return;
     }
-    if ($isExpand) {
-      foreach ($feature['deps'] as $dep) {
-        $this->addFeatureToResults($results, $this->features[$dep], true);
-      }
+    foreach ($feature['deps'] as $dep) {
+      $this->addFeatureToResults($results, $this->features[$dep]);
     }
     if (!in_array($feature['name'], $results)) {
       $results[] = $feature['name'];
@@ -214,6 +166,41 @@
         $this->features[$key]['deps'] = array_merge($entry['deps'], $this->coreFeatures);
       }
     }
+    // Topologically sort all features according to their dependency
+    $features = array();
+    foreach ($this->features as $feature) {
+      $features[] = $feature['name'];
+    }
+    $sortedFeatures = array();
+    $reverseDeps = array();
+    foreach ($features as $feature) {
+      $reverseDeps[$feature] = array();
+    }
+    $depCount = array();
+    foreach ($features as $feature) {
+      $deps = $this->features[$feature]['deps'];
+      $deps = array_uintersect($deps, $features, "strcasecmp");
+      $depCount[$feature] = count($deps);
+      foreach ($deps as $dep) {
+        $reverseDeps[$dep][] = $feature;
+      }
+    }
+    while (! empty($depCount)) {
+      $fail = true;
+      foreach ($depCount as $feature => $count) {
+        if ($count != 0) continue;
+        $fail = false;
+        $sortedFeatures[] = $feature;
+        foreach ($reverseDeps[$feature] as $reverseDep) {
+          $depCount[$reverseDep] -= 1;
+        }
+        unset($depCount[$feature]);
+      }
+      if ($fail && ! empty($depCount)) {
+        throw new GadgetException("Sorting feature dependence failed: it contains ring!");
+      }
+    }
+    $this->sortedFeatures = $sortedFeatures;
   }
 
   /**

Modified: shindig/trunk/php/src/gadgets/render/GadgetBaseRenderer.php
URL: http://svn.apache.org/viewvc/shindig/trunk/php/src/gadgets/render/GadgetBaseRenderer.php?rev=907966&r1=907965&r2=907966&view=diff
==============================================================================
--- shindig/trunk/php/src/gadgets/render/GadgetBaseRenderer.php (original)
+++ shindig/trunk/php/src/gadgets/render/GadgetBaseRenderer.php Tue Feb  9 08:29:28 2010
@@ -300,25 +300,36 @@
   public function getJavaScripts() {
     $registry = $this->context->getRegistry();
     $forcedJsLibs = $this->getForcedJsLibs();
-    $sortedFeatureGroups = array();
-    $registry->sortFeatures($this->gadget->features, $forcedJsLibs, $sortedFeatureGroups);
-    $scripts = array();
-    
-    // if some of the feature libraries are externalized (through a browser cachable <script src="/gadgets/js/opensocial-0.9:settitle.js"> type url)
-    // we inject the tag and don't inline those libs (and their dependencies)
-    foreach ($sortedFeatureGroups as $featureGroup) {
-      if ($featureGroup['type'] == 'inline') {
-        $featureGroup['content'] = $registry->getFeaturesContent($featureGroup['features'], $this->context, true);
+    $externFeatures = array();
+    $inlineFeatures = array();
+    foreach ($this->gadget->features as $feature) {
+      if (in_array($feature, $forcedJsLibs)) {
+        $externFeatures[] = $feature;
       } else {
-        $featureGroup['content'] = Config::get('default_js_prefix') . $this->getJsUrl($featureGroup['features']) . "&container=" . $this->context->getContainer();
+        $inlineFeatures[] = $feature;
       }
-      $scripts[] = $featureGroup;
     }
+    $sortedExternFeatures = array();
+    $sortedInlineFeatures = array();
+    $registry->sortFeatures($externFeatures, $sortedExternFeatures);
+    $registry->sortFeatures($inlineFeatures, $sortedInlineFeatures);
     
+    // if some of the feature libraries are externalized (through a browser cachable <script src="/gadgets/js/opensocial-0.9:settitle.js"> type url)
+    // we inject the tag and don't inline those libs (and their dependencies)
+    $scripts = array();
+    if (! empty($sortedExternFeatures)) {
+      $scripts[] = array(
+          'type' => 'extern',
+          'content' => Config::get('default_js_prefix') . $this->getJsUrl($sortedExternFeatures) . "&container=" . $this->context->getContainer()
+      );
+    }
     $script = '';
+    foreach ($sortedInlineFeatures as $feature) {
+      $script .= $registry->getFeatureContent($feature, $this->context, true);
+    }
     // Add the JavaScript initialization strings for the configuration, localization and preloads
     $script .= "\n";
-    $script .= $this->appendJsConfig($this->gadget, $sortedFeatureGroups);
+    $script .= $this->appendJsConfig($this->gadget, $sortedExternFeatures, $sortedInlineFeatures);
     $script .= $this->appendMessages($this->gadget);
     $script .= $this->appendPreloads($this->gadget);
     if (count($this->dataInserts)) {
@@ -380,7 +391,13 @@
     if (empty($forcedJsLibs)) {
       return array();
     } else {
-      return explode(':', $forcedJsLibs);
+      $features = explode(':', $forcedJsLibs);
+      // expend features here
+      $resultsFound = array();
+      $resultsMissing = array();
+      $registry = $this->context->getRegistry();
+      $registry->resolveFeatures($features, $resultsFound, $resultsMissing);
+      return $resultsFound;
     }
   }
 
@@ -388,23 +405,19 @@
    * Appends the javascript features configuration string
    *
    * @param Gadget $gadget
-   * @param $featureGroups
+   * @param $externFeatures
+   * @param $inlineFeatures
    * @return string
    */
-  private function appendJsConfig(Gadget $gadget, $featureGroups) {
+  private function appendJsConfig(Gadget $gadget, $externFeatures, $inlineFeatures) {
     $container = $this->context->getContainer();
     $containerConfig = $this->context->getContainerConfig();
-    $forcedJsLibs = $this->getForcedJsLibs();
     $gadgetConfig = array();
     $featureConfig = $containerConfig->getConfig($container, 'gadgets.features');
     
     // TODO some day we should parse the forcedLibs too, and include their config selectivly as well.
     // For now we just include everything.
-    $features = array();
-    foreach ($featureGroups as $featureGroup) {
-      $features = array_merge($features, $featureGroup['features']);
-    }
-    
+    $features = array_merge($externFeatures, $inlineFeatures);
     foreach ($features as $feature) {
       if (! isset($gadgetConfig[$feature]) && ! empty($featureConfig[$feature])) {
         $gadgetConfig[$feature] = $featureConfig[$feature];

Modified: shindig/trunk/php/src/gadgets/render/GadgetRenderer.php
URL: http://svn.apache.org/viewvc/shindig/trunk/php/src/gadgets/render/GadgetRenderer.php?rev=907966&r1=907965&r2=907966&view=diff
==============================================================================
--- shindig/trunk/php/src/gadgets/render/GadgetRenderer.php (original)
+++ shindig/trunk/php/src/gadgets/render/GadgetRenderer.php Tue Feb  9 08:29:28 2010
@@ -33,7 +33,7 @@
    * generates the library string (core:caja:etc.js) including a checksum of all the
    * javascript content (?v=<md5 of js>) for cache busting
    *
-   * @param string $libs
+   * @param string $features
    * @param Gadget $gadget
    * @return string the list of libraries in core:caja:etc.js?v=checksum> format
    */

Modified: shindig/trunk/php/src/gadgets/render/GadgetUrlRenderer.php
URL: http://svn.apache.org/viewvc/shindig/trunk/php/src/gadgets/render/GadgetUrlRenderer.php?rev=907966&r1=907965&r2=907966&view=diff
==============================================================================
--- shindig/trunk/php/src/gadgets/render/GadgetUrlRenderer.php (original)
+++ shindig/trunk/php/src/gadgets/render/GadgetUrlRenderer.php Tue Feb  9 08:29:28 2010
@@ -40,17 +40,10 @@
     $registry = $this->context->getRegistry();
     // since the URL mode doesn't actually have the gadget XML body, it can't inline
     // the javascript content anyway - thus could us just ignore the 'forcedJsLibs' part.
-    $forcedJsLibs = array();
-    $sortedFeatureGroups = array();
-    $registry->sortFeatures($gadget->features, $forcedJsLibs, $sortedFeatureGroups);
+    $sortedFeatures = array();
+    $registry->sortFeatures($gadget->features, $sortedFeatures);
     
-    // join the groups
-    $features = array();
-    foreach ($sortedFeatureGroups as $featureGroup) {
-      $features = array_merge($features, $featureGroup['features']);
-    }
-    
-    $query .= $this->appendLibsToQuery($features);
+    $query .= $this->appendLibsToQuery($sortedFeatures);
     $query .= '&lang=' . urlencode(isset($_GET['lang']) ? $_GET['lang'] : 'en');
     $query .= '&country=' . urlencode(isset($_GET['country']) ? $_GET['country'] : 'US');
     if (substr($query, 0, 1) == '&') {

Modified: shindig/trunk/php/src/gadgets/servlet/JsServlet.php
URL: http://svn.apache.org/viewvc/shindig/trunk/php/src/gadgets/servlet/JsServlet.php?rev=907966&r1=907965&r2=907966&view=diff
==============================================================================
--- shindig/trunk/php/src/gadgets/servlet/JsServlet.php (original)
+++ shindig/trunk/php/src/gadgets/servlet/JsServlet.php Tue Feb  9 08:29:28 2010
@@ -56,7 +56,7 @@
     $missing = array();
     $context = new GadgetContext('GADGET');
     $registry = new GadgetFeatureRegistry(Config::get('features_path'));
-    if ($registry->resolveFeatures($needed, $found, $missing, false)) {
+    if ($registry->resolveFeatures($needed, $found, $missing)) {
       $isGadgetContext = !isset($_GET["c"]) || $_GET['c'] == 0 ? true : false;
       $jsData = '';
       foreach ($found as $feature) {