Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
8.33% covered (danger)
8.33%
2 / 24
16.67% covered (danger)
16.67%
1 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
AbstractSearchObject
8.33% covered (danger)
8.33%
2 / 24
16.67% covered (danger)
16.67%
1 / 6
267.56
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 setConfig
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
30
 init
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
90
 process
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getResults
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getHeading
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getSearchClassId
n/a
0 / 0
n/a
0 / 0
0
 getDefaultHeading
n/a
0 / 0
n/a
0 / 0
0
1<?php
2
3/**
4 * Abstract SearchObject Recommendations Module (needs to be extended to use
5 * a particular search object).
6 *
7 * PHP version 8
8 *
9 * Copyright (C) Villanova University 2010-2023.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2,
13 * as published by the Free Software Foundation.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
23 *
24 * @category VuFind
25 * @package  Recommendations
26 * @author   Demian Katz <demian.katz@villanova.edu>
27 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
28 * @link     https://vufind.org/wiki/development:plugins:recommendation_modules Wiki
29 */
30
31namespace VuFind\Recommend;
32
33use VuFind\Search\SearchRunner;
34
35use function intval;
36use function is_object;
37
38/**
39 * Abstract SearchObject Recommendations Module (needs to be extended to use
40 * a particular search object).
41 *
42 * @category VuFind
43 * @package  Recommendations
44 * @author   Demian Katz <demian.katz@villanova.edu>
45 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
46 * @link     https://vufind.org/wiki/development:plugins:recommendation_modules Wiki
47 */
48abstract class AbstractSearchObject implements RecommendInterface
49{
50    /**
51     * Results object
52     *
53     * @var \VuFind\Search\Base\Results
54     */
55    protected $results;
56
57    /**
58     * Number of results to show
59     *
60     * @var int
61     */
62    protected $limit;
63
64    /**
65     * Sort order for results (null = default)
66     *
67     * @var ?string
68     */
69    protected $sort;
70
71    /**
72     * Heading for this recommendation module
73     *
74     * @var string
75     */
76    protected $heading;
77
78    /**
79     * Config section with filters for this search
80     *
81     * @var string
82     */
83    protected $filterIniSection;
84
85    /**
86     * Name of request parameter to use for search query
87     *
88     * @var string
89     */
90    protected $requestParam;
91
92    /**
93     * Search runner
94     *
95     * @var SearchRunner
96     */
97    protected $runner;
98
99    /**
100     * Config PluginManager
101     *
102     * @var \VuFind\Config\PluginManager
103     */
104    protected $configManager;
105
106    /**
107     * Constructor
108     *
109     * @param SearchRunner                 $runner        Search runner
110     * @param \VuFind\Config\PluginManager $configManager Config manager
111     */
112    public function __construct(SearchRunner $runner, \VuFind\Config\PluginManager $configManager)
113    {
114        $this->runner = $runner;
115        $this->configManager = $configManager;
116    }
117
118    /**
119     * Store the configuration of the recommendation module.
120     *
121     * @param string $settings Settings from searches.ini.
122     *
123     * @return void
124     */
125    public function setConfig($settings)
126    {
127        $settings = explode(':', $settings);
128        $this->requestParam = empty($settings[0]) ? 'lookfor' : $settings[0];
129        $this->limit
130            = (isset($settings[1]) && is_numeric($settings[1]) && $settings[1] > 0)
131            ? intval($settings[1]) : 5;
132
133        $this->heading = $settings[2] ?? $this->getDefaultHeading();
134        $this->filterIniSection = $settings[3] ?? false;
135        $this->sort = $settings[4] ?? null;
136    }
137
138    /**
139     * Called before the Search Results object performs its main search
140     * (specifically, in response to \VuFind\Search\SearchRunner::EVENT_CONFIGURED).
141     * This method is responsible for setting search parameters needed by the
142     * recommendation module and for reading any existing search parameters that may
143     * be needed.
144     *
145     * @param \VuFind\Search\Base\Params $params  Search parameter object
146     * @param \Laminas\Stdlib\Parameters $request Parameter object representing user
147     * request.
148     *
149     * @return void
150     */
151    public function init($params, $request)
152    {
153        // See if we can determine the label for the current search type; first
154        // check for an override in the GET parameters, then look at the incoming
155        // params object....
156        $typeLabel = $request->get('typeLabel');
157        $type = $request->get('type');
158        if (empty($typeLabel) && !empty($type)) {
159            $typeLabel = $params->getOptions()->getLabelForBasicHandler($type);
160        }
161
162        // Extract a search query:
163        $lookfor = $request->get($this->requestParam);
164        if (empty($lookfor) && is_object($params)) {
165            $lookfor = $params->getQuery()->getAllTerms();
166        }
167
168        // Set up the callback to initialize the parameters:
169        $callback = function ($runner, $params) use ($lookfor, $typeLabel) {
170            $params->setLimit($this->limit);
171            if ($this->sort) {
172                $params->setSort($this->sort, true);
173            }
174            $params->setBasicSearch(
175                $lookfor,
176                $params->getOptions()->getHandlerForLabel($typeLabel)
177            );
178
179            // Set any filters configured for this search
180            if (!empty($this->filterIniSection)) {
181                $ini = $params->getOptions()->getSearchIni();
182                $config = $this->configManager->get($ini);
183                try {
184                    $filters = $config->{$this->filterIniSection}->toArray() ?? [];
185                } catch (\Error $e) {
186                    throw new \Exception(
187                        "No section found matching '$this->filterIniSection' in $ini.ini."
188                    );
189                }
190                foreach ($filters as $filter) {
191                    $params->addFilter($filter);
192                }
193            }
194        };
195
196        // Perform the search:
197        $this->results
198            = $this->runner->run([], $this->getSearchClassId(), $callback);
199    }
200
201    /**
202     * Called after the Search Results object has performed its main search. This
203     * may be used to extract necessary information from the Search Results object
204     * or to perform completely unrelated processing.
205     *
206     * @param \VuFind\Search\Base\Results $results Search results object
207     *
208     * @return void
209     */
210    public function process($results)
211    {
212        // No action needed.
213    }
214
215    /**
216     * Get search results.
217     *
218     * @return \VuFind\Search\Base\Results
219     */
220    public function getResults()
221    {
222        return $this->results;
223    }
224
225    /**
226     * Get the heading.
227     *
228     * @return string
229     */
230    public function getHeading()
231    {
232        return $this->heading;
233    }
234
235    /**
236     * Get the search class ID to use for building search objects.
237     *
238     * @return string
239     */
240    abstract protected function getSearchClassId();
241
242    /**
243     * Get the default heading for this recommendation module.
244     *
245     * @return string
246     */
247    abstract protected function getDefaultHeading();
248}