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