Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
30 / 30
100.00% covered (success)
100.00%
4 / 4
CRAP
100.00% covered (success)
100.00%
1 / 1
InjectConditionalFilterListener
100.00% covered (success)
100.00%
30 / 30
100.00% covered (success)
100.00%
4 / 4
11
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 attach
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
 addConditionalFilter
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
5
 onSearchPre
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
1 / 1
4
1<?php
2
3/**
4 * Conditional Filter listener.
5 *
6 * PHP version 8
7 *
8 * Copyright (C) Villanova University 2013.
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   Oliver Goldschmidt <o.goldschmidt@tuhh.de>
26 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
27 * @link     https://vufind.org Main Site
28 */
29
30namespace VuFind\Search\Solr;
31
32use Laminas\EventManager\EventInterface;
33use Laminas\EventManager\SharedEventManagerInterface;
34use LmcRbacMvc\Service\AuthorizationServiceAwareTrait;
35use VuFindSearch\Backend\BackendInterface;
36use VuFindSearch\Service;
37
38use function is_array;
39
40/**
41 * Conditional Filter listener.
42 *
43 * @category VuFind
44 * @package  Search
45 * @author   Oliver Goldschmidt <o.goldschmidt@tuhh.de>
46 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
47 * @link     https://vufind.org Main Site
48 */
49class InjectConditionalFilterListener
50{
51    use AuthorizationServiceAwareTrait;
52
53    /**
54     * Filters to apply.
55     *
56     * @var array
57     */
58    protected $filterList;
59
60    /**
61     * Filters from configuration.
62     *
63     * @var array
64     */
65    protected $filters;
66
67    /**
68     * Constructor.
69     *
70     * @param BackendInterface $backend    Backend
71     * @param array            $searchConf Search configuration parameters
72     *
73     * @return void
74     */
75    public function __construct(protected BackendInterface $backend, $searchConf)
76    {
77        $this->filters = $searchConf;
78        $this->filterList = [];
79    }
80
81    /**
82     * Attach listener to shared event manager.
83     *
84     * @param SharedEventManagerInterface $manager Shared event manager
85     *
86     * @return void
87     */
88    public function attach(SharedEventManagerInterface $manager)
89    {
90        $manager->attach(
91            Service::class,
92            Service::EVENT_PRE,
93            [$this, 'onSearchPre']
94        );
95    }
96
97    /**
98     * Add a conditional filter.
99     *
100     * @param String $configOption Conditional Filter
101     *
102     * @return void
103     */
104    protected function addConditionalFilter($configOption)
105    {
106        $filterArr = explode('|', $configOption);
107        $filterCondition = $filterArr[0];
108        $filter = $filterArr[1];
109        $authService = $this->getAuthorizationService();
110
111        // if no authorization service is available, don't do anything
112        if (!$authService) {
113            return;
114        }
115
116        // if the filter condition starts with a minus (-), it should not match
117        // to get the filter applied
118        if (str_starts_with($filterCondition, '-')) {
119            if (!$authService->isGranted(substr($filterCondition, 1))) {
120                $this->filterList[] = $filter;
121            }
122        } else {
123            // otherwise the condition should match to apply the filter
124            if ($authService->isGranted($filterCondition)) {
125                $this->filterList[] = $filter;
126            }
127        }
128    }
129
130    /**
131     * Set up conditional hidden filters.
132     *
133     * @param EventInterface $event Event
134     *
135     * @return EventInterface
136     */
137    public function onSearchPre(EventInterface $event)
138    {
139        $command = $event->getParam('command');
140        if ($command->getTargetIdentifier() !== $this->backend->getIdentifier()) {
141            return $event;
142        }
143
144        // Add conditional filters
145        foreach ($this->filters as $fc) {
146            $this->addConditionalFilter($fc);
147        }
148
149        $params = $command->getSearchParameters();
150        $fq = $params->get('fq');
151        if (!is_array($fq)) {
152            $fq = [];
153        }
154        $new_fq = array_merge($fq, $this->filterList);
155        $params->set('fq', $new_fq);
156
157        return $event;
158    }
159}