Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 31
0.00% covered (danger)
0.00%
0 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
SolrPrefix
0.00% covered (danger)
0.00%
0 / 31
0.00% covered (danger)
0.00%
0 / 6
132
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getSuggestions
0.00% covered (danger)
0.00%
0 / 22
0.00% covered (danger)
0.00%
0 / 1
42
 mungeQuery
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 setConfig
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 addFilters
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 initSearchObject
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3/**
4 * Solr Prefix Autocomplete Module
5 *
6 * PHP version 8
7 *
8 * Copyright (C) Villanova University 2021.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2,
12 * as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 * @category VuFind
24 * @package  Autocomplete
25 * @author   Vaclav Rosecky <vaclav.rosecky@mzk.cz>
26 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
27 * @link     http://vufind.org/wiki/vufind2:autosuggesters Wiki
28 */
29
30namespace VuFind\Autocomplete;
31
32use function is_object;
33
34/**
35 * Solr autocomplete module with prefix queries using edge N-gram filter
36 *
37 * This class provides suggestions by using the local Solr index.
38 *
39 * @category VuFind
40 * @package  Autocomplete
41 * @author   Vaclav Rosecky <vaclav.rosecky@mzk.cz>
42 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
43 * @link     https://vufind.org/wiki/development:plugins:autosuggesters Wiki
44 */
45class SolrPrefix implements AutocompleteInterface
46{
47    /**
48     * Results manager
49     *
50     * @var \VuFind\Search\Results\PluginManager
51     */
52    protected $resultsManager;
53
54    /**
55     * Search object
56     *
57     * @var \VuFind\Search\Solr\Results
58     */
59    protected $searchObject;
60
61    /**
62     * Search class id
63     *
64     * @var string
65     */
66    protected $searchClassId = 'Solr';
67
68    /**
69     * Autocomplete field
70     *
71     * @var string
72     */
73    protected $autocompleteField;
74
75    /**
76     * Facet field
77     *
78     * @var string
79     */
80    protected $facetField;
81
82    /**
83     * Facet limit, can be overridden in subclasses
84     *
85     * @var int
86     */
87    protected $limit = 10;
88
89    /**
90     * Filters to apply to Solr search
91     *
92     * @var array
93     */
94    protected $filters = [];
95
96    /**
97     * Constructor
98     *
99     * @param \VuFind\Search\Results\PluginManager $results Results plugin manager
100     */
101    public function __construct(\VuFind\Search\Results\PluginManager $results)
102    {
103        $this->resultsManager = $results;
104    }
105
106    /**
107     * Get suggestions
108     *
109     * This method returns an array of strings matching the user's query for
110     * display in the autocomplete box.
111     *
112     * @param string $query The user query
113     *
114     * @return array        The suggestions for the provided query
115     */
116    public function getSuggestions($query)
117    {
118        if (!is_object($this->searchObject)) {
119            throw new \Exception('Please set configuration first.');
120        }
121
122        $results = [];
123        try {
124            $params = $this->searchObject->getParams();
125            $rawQuery = $this->autocompleteField . ':(' .
126                $this->mungeQuery($query) . ')';
127            $params->setBasicSearch($rawQuery);
128            $params->addFacet($this->facetField);
129            $params->setLimit(0);
130            $params->setFacetLimit($this->limit);
131            foreach ($this->filters as $current) {
132                $params->addFilter($current);
133            }
134            $options = $params->getOptions();
135            $options->disableHighlighting();
136            $options->spellcheckEnabled(false);
137            $this->searchObject->getResults();
138            $facets = $this->searchObject->getFacetList();
139            if (isset($facets[$this->facetField]['list'])) {
140                foreach ($facets[$this->facetField]['list'] as $filter) {
141                    $results[] = $filter['value'];
142                }
143            }
144        } catch (\Exception $e) {
145            // Ignore errors -- just return empty results if we must.
146        }
147        return array_unique($results);
148    }
149
150    /**
151     * Process the user query to make it suitable for a Solr query.
152     *
153     * @param string $query Incoming user query
154     *
155     * @return string       Processed query
156     */
157    protected function mungeQuery($query)
158    {
159        $forbidden = [':', '(', ')', '*', '+', '"'];
160        return str_replace($forbidden, ' ', $query);
161    }
162
163    /**
164     * Set configuration
165     *
166     * Set parameters that affect the behavior of the autocomplete handler.
167     * These values normally come from the search configuration file.
168     *
169     * @param string $params Parameters to set
170     *
171     * @return void
172     */
173    public function setConfig($params)
174    {
175        [$this->autocompleteField, $this->facetField] = explode(':', $params, 2);
176        $this->initSearchObject();
177    }
178
179    /**
180     * Add filters (in addition to the configured ones)
181     *
182     * @param array $filters Filters to add
183     *
184     * @return void
185     */
186    public function addFilters($filters)
187    {
188        $this->filters += $filters;
189    }
190
191    /**
192     * Initialize the search object used for finding recommendations.
193     *
194     * @return void
195     */
196    protected function initSearchObject()
197    {
198        // Build a new search object:
199        $this->searchObject = $this->resultsManager->get($this->searchClassId);
200        $this->searchObject->getOptions()->spellcheckEnabled(false);
201        $this->searchObject->getOptions()->disableHighlighting();
202    }
203}