Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
36 / 36
100.00% covered (success)
100.00%
15 / 15
CRAP
100.00% covered (success)
100.00%
1 / 1
QueryGroup
100.00% covered (success)
100.00%
36 / 36
100.00% covered (success)
100.00%
15 / 15
23
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 __clone
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 getReducedHandler
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setReducedHandler
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 unsetReducedHandler
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 addQuery
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getQueries
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setQueries
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 addQueries
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 setOperator
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
3
 getOperator
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 isNegated
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 containsTerm
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
3
 getAllTerms
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 replaceTerm
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3/**
4 * A group of single/simples queries, joined by boolean operator.
5 *
6 * PHP version 8
7 *
8 * Copyright (C) Villanova University 2010.
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  Search
25 * @author   David Maus <maus@hab.de>
26 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
27 * @link     https://vufind.org
28 */
29
30namespace VuFindSearch\Query;
31
32use VuFindSearch\Exception\InvalidArgumentException;
33
34use function in_array;
35
36/**
37 * A group of single/simples queries, joined by boolean operator.
38 *
39 * @category VuFind
40 * @package  Search
41 * @author   David Maus <maus@hab.de>
42 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
43 * @link     https://vufind.org
44 */
45class QueryGroup extends AbstractQuery
46{
47    /**
48     * Valid boolean operators.
49     *
50     * @var array
51     */
52    protected static $operators = ['AND', 'OR', 'NOT'];
53
54    /**
55     * Name of the handler to be used if the query group is reduced.
56     *
57     * @see \VuFindSearch\Backend\Solr\QueryBuilder::reduceQueryGroup()
58     *
59     * @var string
60     *
61     * @todo Check if we actually use/need this feature
62     */
63    protected $reducedHandler;
64
65    /**
66     * Boolean operator.
67     *
68     * @var string
69     */
70    protected $operator;
71
72    /**
73     * Is the query group negated?
74     *
75     * @var bool
76     */
77    protected $negation;
78
79    /**
80     * Queries.
81     *
82     * @var array
83     */
84    protected $queries;
85
86    /**
87     * Constructor.
88     *
89     * @param string $operator       Boolean operator
90     * @param array  $queries        Queries
91     * @param string $reducedHandler Handler to be uses if reduced
92     *
93     * @return void
94     */
95    public function __construct(
96        $operator,
97        array $queries = [],
98        $reducedHandler = null
99    ) {
100        $this->setOperator($operator);
101        $this->setQueries($queries);
102        $this->setReducedHandler($reducedHandler);
103    }
104
105    /**
106     * Copy constructor
107     *
108     * @return void
109     */
110    public function __clone()
111    {
112        $new = [];
113        foreach ($this->queries as $q) {
114            $new[] = clone $q;
115        }
116        $this->queries = $new;
117    }
118
119    /**
120     * Return name of reduced handler.
121     *
122     * @return string|null
123     */
124    public function getReducedHandler()
125    {
126        return $this->reducedHandler;
127    }
128
129    /**
130     * Set name of reduced handler.
131     *
132     * @param string $handler Reduced handler
133     *
134     * @return void
135     */
136    public function setReducedHandler($handler)
137    {
138        $this->reducedHandler = $handler;
139    }
140
141    /**
142     * Unset reduced handler.
143     *
144     * @return void
145     */
146    public function unsetReducedHandler()
147    {
148        $this->reducedHandler = null;
149    }
150
151    /**
152     * Add a query to the group.
153     *
154     * @param AbstractQuery $query Query to add
155     *
156     * @return void
157     */
158    public function addQuery(AbstractQuery $query)
159    {
160        $this->queries[] = $query;
161    }
162
163    /**
164     * Return group queries.
165     *
166     * @return array
167     */
168    public function getQueries()
169    {
170        return $this->queries;
171    }
172
173    /**
174     * Set group queries.
175     *
176     * @param array $queries Group queries
177     *
178     * @return void
179     */
180    public function setQueries(array $queries)
181    {
182        $this->queries = [];
183        $this->addQueries($queries);
184    }
185
186    /**
187     * Add group queries.
188     *
189     * @param array $queries Group queries
190     *
191     * @return void
192     */
193    public function addQueries(array $queries)
194    {
195        foreach ($queries as $query) {
196            $this->addQuery($query);
197        }
198    }
199
200    /**
201     * Set boolean operator.
202     *
203     * @param string $operator Boolean operator
204     *
205     * @return void
206     *
207     * @throws \InvalidArgumentException Unknown or invalid boolean operator
208     */
209    public function setOperator($operator)
210    {
211        if (!in_array($operator, self::$operators)) {
212            throw new InvalidArgumentException(
213                "Unknown or invalid boolean operator: {$operator}"
214            );
215        }
216        if ($operator == 'NOT') {
217            $this->operator = 'OR';
218            $this->negation = true;
219        } else {
220            $this->operator = $operator;
221        }
222    }
223
224    /**
225     * Return boolean operator.
226     *
227     * @return string
228     */
229    public function getOperator()
230    {
231        return $this->operator;
232    }
233
234    /**
235     * Return true if group is an exclusion group.
236     *
237     * @return bool
238     */
239    public function isNegated()
240    {
241        return $this->negation;
242    }
243
244    /**
245     * Does the query contain the specified term? An optional normalizer can be
246     * provided to allow for fuzzier matching.
247     *
248     * @param string   $needle     Term to check
249     * @param callable $normalizer Function to normalize text strings (null for
250     * no normalization)
251     *
252     * @return bool
253     */
254    public function containsTerm($needle, $normalizer = null)
255    {
256        foreach ($this->getQueries() as $q) {
257            if ($q->containsTerm($needle, $normalizer)) {
258                return true;
259            }
260        }
261        return false;
262    }
263
264    /**
265     * Get a concatenated list of all query strings within the object.
266     *
267     * @return string
268     */
269    public function getAllTerms()
270    {
271        $parts = [];
272        foreach ($this->getQueries() as $q) {
273            $parts[] = $q->getAllTerms();
274        }
275        return implode(' ', $parts);
276    }
277
278    /**
279     * Replace a term.
280     *
281     * @param string   $from       Search term to find
282     * @param string   $to         Search term to insert
283     * @param callable $normalizer Function to normalize text strings (null for
284     * no normalization)
285     *
286     * @return void
287     */
288    public function replaceTerm($from, $to, $normalizer = null)
289    {
290        foreach ($this->getQueries() as $q) {
291            $q->replaceTerm($from, $to, $normalizer);
292        }
293    }
294}