Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
93.94% covered (success)
93.94%
31 / 33
71.43% covered (warning)
71.43%
5 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
BackendManager
93.94% covered (success)
93.94%
31 / 33
71.43% covered (warning)
71.43%
5 / 7
13.04
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
 getBackendRegistry
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 get
100.00% covered (success)
100.00%
17 / 17
100.00% covered (success)
100.00%
1 / 1
3
 has
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 onResolve
75.00% covered (warning)
75.00%
3 / 4
0.00% covered (danger)
0.00%
0 / 1
3.14
 attachShared
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 detachShared
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3/**
4 * Manager for search backends.
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   David Maus <maus@hab.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;
31
32use Laminas\EventManager\EventInterface;
33use Laminas\EventManager\SharedEventManagerInterface;
34use Laminas\ServiceManager\ServiceLocatorInterface;
35use SplObjectStorage;
36use UnexpectedValueException;
37use VuFindSearch\Backend\BackendInterface;
38use VuFindSearch\Service;
39
40use function gettype;
41use function is_object;
42
43/**
44 * Manager for search backends.
45 *
46 * @category VuFind
47 * @package  Search
48 * @author   David Maus <maus@hab.de>
49 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
50 * @link     https://vufind.org Main Site
51 */
52class BackendManager
53{
54    /**
55     * Backend registry.
56     *
57     * @var ServiceLocatorInterface
58     */
59    protected $registry;
60
61    /**
62     * Attached listeners.
63     *
64     * @var SplObjectStorage
65     */
66    protected $listeners;
67
68    /**
69     * Constructor.
70     *
71     * @param ServiceLocatorInterface $registry Backend registry
72     *
73     * @return void
74     */
75    public function __construct(ServiceLocatorInterface $registry)
76    {
77        $this->registry  = $registry;
78        $this->listeners = new SplObjectStorage();
79    }
80
81    /**
82     * Return backend registry.
83     *
84     * @return ServiceLocatorInterface
85     */
86    public function getBackendRegistry()
87    {
88        return $this->registry;
89    }
90
91    /**
92     * Return named backend.
93     *
94     * @param string $name Backend name
95     *
96     * @return BackendInterface
97     *
98     * @throws UnexpectedValueException Retrieved backend is not an object
99     * @throws UnexpectedValueException Retrieved backend does not implement
100     * BackendInterface
101     */
102    public function get($name)
103    {
104        $backend = $this->registry->get($name);
105        if (!is_object($backend)) {
106            throw new UnexpectedValueException(
107                sprintf(
108                    'Expected backend registry to return object, got %s',
109                    gettype($backend)
110                )
111            );
112        }
113        if (!$backend instanceof BackendInterface) {
114            throw new UnexpectedValueException(
115                sprintf(
116                    'Object of class %s does not implement the expected interface',
117                    $backend::class
118                )
119            );
120        }
121        $backend->setIdentifier($name);
122        return $backend;
123    }
124
125    /**
126     * Return true if named backend is available.
127     *
128     * @param string $name Backend name
129     *
130     * @return bool
131     */
132    public function has($name)
133    {
134        return $this->registry->has($name);
135    }
136
137    /**
138     * Listener for search system event `resolve`.
139     *
140     * @param EventInterface $e Event object
141     *
142     * @return BackendInterface|null
143     */
144    public function onResolve(EventInterface $e)
145    {
146        $name = $e->getParam('command')->getTargetIdentifier();
147        if ($name && $this->has($name)) {
148            return $this->get($name);
149        }
150        return null;
151    }
152
153    /**
154     * Attach to shared event manager.
155     *
156     * @param SharedEventManagerInterface $events Shared event manager
157     *
158     * @return void
159     */
160    public function attachShared(SharedEventManagerInterface $events)
161    {
162        if (!$this->listeners->offsetExists($events)) {
163            $listener = [$this, 'onResolve'];
164            $events->attach(Service::class, Service::EVENT_RESOLVE, $listener);
165            $this->listeners->attach($events, $listener);
166        }
167    }
168
169    /**
170     * Detach from shared event manager.
171     *
172     * @param SharedEventManagerInterface $events Shared event manager
173     *
174     * @return void
175     */
176    public function detachShared(SharedEventManagerInterface $events)
177    {
178        if ($this->listeners->offsetExists($events)) {
179            $listener = $this->listeners->offsetGet($events);
180            $events->detach($listener, Service::class);
181            $this->listeners->detach($events);
182        }
183    }
184}