CRM_Extension_Container_Basic - Add mechanism for filtering
authorTim Otten <totten@civicrm.org>
Sat, 1 Jun 2019 00:03:50 +0000 (17:03 -0700)
committerTim Otten <totten@civicrm.org>
Sat, 1 Jun 2019 00:11:10 +0000 (17:11 -0700)
This function allows one to filter down the list of extensions which are visible.

A few notes:

* The result of the scanning/filtering is stored in cache.  On a typical
  page-load, the system uses this cache -- which happily means that
  filtering shouldn't result in any extra page-load time.

* The extension-system is generally boot-critical.  I could imagine some
  scope-creep around making making the filter mechanism hookable, but that's
  a separate+complicated issue.  Optimistically...  if `array $containers`
  somehow becomes hookable, then one could use the same mechanism to
  manipulate the filters.

CRM/Extension/Container/Basic.php

index 42277242767a5b3b84c04697f2c2adf10e6a9562..3251722565e766a623d8201fbfd561d24cb34bfb 100644 (file)
@@ -82,6 +82,14 @@ class CRM_Extension_Container_Basic implements CRM_Extension_Container_Interface
    */
   public $relUrls = FALSE;
 
+  /**
+   * @var array
+   *   Array(function(CRM_Extension_Info $info): bool)
+   *   List of callables which determine whether an extension is visible.
+   *   Each function returns TRUE if the extension should be visible.
+   */
+  protected $filters = [];
+
   /**
    * @param string $baseDir
    *   Local path to the container.
@@ -216,7 +224,16 @@ class CRM_Extension_Container_Basic implements CRM_Extension_Container_Interface
             CRM_Core_Error::debug_log_message("Parse error in extension: " . $e->getMessage());
             continue;
           }
-          $this->relPaths[$info->key] = $relPath;
+          $visible = TRUE;
+          foreach ($this->filters as $filter) {
+            if (!$filter($info)) {
+              $visible = FALSE;
+              break;
+            }
+          }
+          if ($visible) {
+            $this->relPaths[$info->key] = $relPath;
+          }
         }
         if ($this->cache) {
           $this->cache->set($this->cacheKey, $this->relPaths);
@@ -259,6 +276,20 @@ class CRM_Extension_Container_Basic implements CRM_Extension_Container_Interface
     return $this->relUrls;
   }
 
+  /**
+   * Register a filter which determine whether a copy of an extension
+   * appears as available.
+   *
+   * @param callable $callable
+   *   function(CRM_Extension_Info $info): bool
+   *   Each function returns TRUE if the extension should be visible.
+   * @return $this
+   */
+  public function addFilter($callable) {
+    $this->filters[] = $callable;
+    return $this;
+  }
+
   /**
    * Convert a list of relative paths to relative URLs.
    *