]> git.immae.eu Git - github/shaarli/Shaarli.git/blobdiff - application/plugin/PluginManager.php
Merge pull request #1698 from ArthurHoaro/feature/plugins-search-filter
[github/shaarli/Shaarli.git] / application / plugin / PluginManager.php
index 7fc0cb047db70d1ca33d8f72529b57ff598b579e..939db1eaafa84acdb68915c4fdda659d1f416665 100644 (file)
@@ -2,6 +2,7 @@
 
 namespace Shaarli\Plugin;
 
+use Shaarli\Bookmark\Bookmark;
 use Shaarli\Config\ConfigManager;
 use Shaarli\Plugin\Exception\PluginFileNotFoundException;
 use Shaarli\Plugin\Exception\PluginInvalidRouteException;
@@ -45,6 +46,9 @@ class PluginManager
      */
     protected $errors;
 
+    /** @var callable[]|null Preloaded list of hook function for filterSearchEntry() */
+    protected $filterSearchEntryHooks = null;
+
     /**
      * Plugins subdirectory.
      *
@@ -273,6 +277,14 @@ class PluginManager
         return $this->registeredRoutes;
     }
 
+    /**
+     * @return array List of registered filter_search_entry hooks
+     */
+    public function getFilterSearchEntryHooks(): ?array
+    {
+        return $this->filterSearchEntryHooks;
+    }
+
     /**
      * Return the list of encountered errors.
      *
@@ -283,6 +295,50 @@ class PluginManager
         return $this->errors;
     }
 
+    /**
+     * Apply additional filter on every search result of BookmarkFilter calling plugins hooks.
+     *
+     * @param Bookmark $bookmark To check.
+     * @param array    $context  Additional info about search context, depends on the search source.
+     *
+     * @return bool True if the result must be kept in search results, false otherwise.
+     */
+    public function filterSearchEntry(Bookmark $bookmark, array $context): bool
+    {
+        if ($this->filterSearchEntryHooks === null) {
+            $this->loadFilterSearchEntryHooks();
+        }
+
+        if ($this->filterSearchEntryHooks === []) {
+            return true;
+        }
+
+        foreach ($this->filterSearchEntryHooks as $filterSearchEntryHook) {
+            if ($filterSearchEntryHook($bookmark, $context) === false) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     * filterSearchEntry() method will be called for every search result,
+     * so for performances we preload existing functions to invoke them directly.
+     */
+    protected function loadFilterSearchEntryHooks(): void
+    {
+        $this->filterSearchEntryHooks = [];
+
+        foreach ($this->loadedPlugins as $plugin) {
+            $hookFunction = $this->buildHookName('filter_search_entry', $plugin);
+
+            if (function_exists($hookFunction)) {
+                $this->filterSearchEntryHooks[] = $hookFunction;
+            }
+        }
+    }
+
     /**
      * Checks whether provided input is valid to register a new route.
      * It must contain keys `method`, `route`, `callable` (all strings).