David Maus

Update VuFind® to 9.1, changes in the search subsystem

At the State and University Library we are currently in the process of updating our discovery systems from VuFind 8 to VuFind 9. One area that has changed from 8 to 9 is the VuFindSearch module, namely how an event-based listener interacts with it.

Today I updated the PruneSolrfieldfacetlistener, a listener that prunes (removes) field facet values from a facetted search response. We use this listener in our Katalogplus as well in our KatalogHamburg to facet over locations (field collection_details in the K10Plus Zentral search index) and display only locations relevant to the user. We do this by removing all facet values that do not match predefined criteria.

This listener stops working with VuFind 9 for the following reasons:

Addressing theses changes was no rocket science, the PruneSolrfieldfacetlistener is working again.

 namespace SUBHH\VuFind\Shared;-use VuFindSearch\Backend\Solr\Response\Json\RecordCollection;-use VuFindSearch\Backend\Solr\Response\Json\Facets; // @phan-suppress-current-line PhanUnreferencedUseNormal use VuFindSearch\Service;+use VuFindSearch\ParamBag;+use VuFindSearch\Command\CommandInterface;+use VuFindSearch\Backend\Solr\Response\Json\RecordCollection; use Laminas\EventManager\EventInterface; use Laminas\EventManager\SharedEventManagerInterface;@@ -51,28 +52,24 @@ final class PruneSolrFieldFacetListener         $events->attach('VuFindSearch', Service::EVENT_POST, [$this, 'onSearchPost']);     }+    /** @param EventInterface<Service, ParamBag> $event */     public function onSearchPost (EventInterface $event) : void     {-        $response = $event->getTarget();-        if ($response instanceof RecordCollection) {--            /** @var Facets */-            $facets = $response->getFacets();-            $fieldfacets = $facets->getFieldFacets(); // @phan-suppress-current-line PhanNonClassMethodCall-            if (isset($fieldfacets[$this->field])) {-                $facet = $fieldfacets[$this->field];-                $facet->rewind();--                $remove = array();-                while ($facet->valid())  namespace SUBHH\VuFind\Shared;-use VuFindSearch\Backend\Solr\Response\Json\RecordCollection;-use VuFindSearch\Backend\Solr\Response\Json\Facets; // @phan-suppress-current-line PhanUnreferencedUseNormal use VuFindSearch\Service;+use VuFindSearch\ParamBag;+use VuFindSearch\Command\CommandInterface;+use VuFindSearch\Backend\Solr\Response\Json\RecordCollection; use Laminas\EventManager\EventInterface; use Laminas\EventManager\SharedEventManagerInterface;@@ -51,27 +52,23 @@ final class PruneSolrFieldFacetListener         $events->attach('VuFindSearch', Service::EVENT_POST, [$this, 'onSearchPost']);     }+    /** @param EventInterface<Service, ParamBag> $event */     public function onSearchPost (EventInterface $event) : void     {-        $response = $event->getTarget();-        if ($response instanceof RecordCollection) {--            /** @var Facets */-            $facets = $response->getFacets();-            $fieldfacets = $facets->getFieldFacets(); // @phan-suppress-current-line PhanNonClassMethodCall-            if (isset($fieldfacets[$this->field])) {-                $facet = $fieldfacets[$this->field];-                $facet->rewind();--                $remove = array();-                while ($facet->valid()) {-                    $value = $facet->key();-                    if ($this->filter->accept($value) === false) {-                        $remove[] = $value;-                    }-                    $facet->next();+        $command = $event->getParam('command');+        if ($command instanceof CommandInterface) {+            $response = $command->getResult();+            if ($response instanceof RecordCollection) {+                $facets = $response->getFacets();+                if (array_key_exists($this->field, $facets)) {+                    $facets[$this->field] = array_filter($facets[$this->field], array($this, 'filter'), ARRAY_FILTER_USE_KEY);                 }-                $facet->removeKeys($remove);+                $response->setFacets($facets);             }         }     }++    private function filter (mixed $key) : bool+    {+        return $this->filter->accept($key);+    } }