Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 68 |
|
0.00% |
0 / 8 |
CRAP | |
0.00% |
0 / 1 |
ChannelLoader | |
0.00% |
0 / 68 |
|
0.00% |
0 / 8 |
462 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
2 | |||
performChannelSearch | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
6 | |||
getChannelsFromResults | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
6 | |||
getChannelProviders | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
20 | |||
getChannelProvider | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
12 | |||
getHomeContext | |
0.00% |
0 / 22 |
|
0.00% |
0 / 1 |
42 | |||
getRecordContext | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
6 | |||
getSearchContext | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | |
3 | /** |
4 | * Channel loader |
5 | * |
6 | * PHP version 8 |
7 | * |
8 | * Copyright (C) Villanova University 2016. |
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 Channels |
25 | * @author Demian Katz <demian.katz@villanova.edu> |
26 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License |
27 | * @link https://vufind.org/wiki/development Wiki |
28 | */ |
29 | |
30 | namespace VuFind\ChannelProvider; |
31 | |
32 | use Laminas\Config\Config; |
33 | use VuFind\Cache\Manager as CacheManager; |
34 | use VuFind\ChannelProvider\PluginManager as ChannelManager; |
35 | use VuFind\Record\Loader as RecordLoader; |
36 | use VuFind\Search\Base\Results; |
37 | use VuFind\Search\SearchRunner; |
38 | |
39 | use function in_array; |
40 | |
41 | /** |
42 | * Channel loader |
43 | * |
44 | * @category VuFind |
45 | * @package Channels |
46 | * @author Demian Katz <demian.katz@villanova.edu> |
47 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License |
48 | * @link https://vufind.org/wiki/development Wiki |
49 | */ |
50 | class ChannelLoader |
51 | { |
52 | /** |
53 | * Cache manager |
54 | * |
55 | * @var CacheManager |
56 | */ |
57 | protected $cacheManager; |
58 | |
59 | /** |
60 | * Channel manager |
61 | * |
62 | * @var ChannelManager |
63 | */ |
64 | protected $channelManager; |
65 | |
66 | /** |
67 | * Channel configuration |
68 | * |
69 | * @var Config |
70 | */ |
71 | protected $config; |
72 | |
73 | /** |
74 | * Record loader |
75 | * |
76 | * @var RecordLoader |
77 | */ |
78 | protected $recordLoader; |
79 | |
80 | /** |
81 | * Search runner |
82 | * |
83 | * @var SearchRunner |
84 | */ |
85 | protected $searchRunner; |
86 | |
87 | /** |
88 | * Current locale (used for caching) |
89 | * |
90 | * @var string |
91 | */ |
92 | protected $locale; |
93 | |
94 | /** |
95 | * Constructor |
96 | * |
97 | * @param Config $config Channels configuration |
98 | * @param CacheManager $cache Cache manager |
99 | * @param ChannelManager $cm Channel manager |
100 | * @param SearchRunner $runner Search runner |
101 | * @param RecordLoader $loader Record loader |
102 | * @param string $locale Current locale (used for caching) |
103 | */ |
104 | public function __construct( |
105 | Config $config, |
106 | CacheManager $cache, |
107 | ChannelManager $cm, |
108 | SearchRunner $runner, |
109 | RecordLoader $loader, |
110 | string $locale = '' |
111 | ) { |
112 | $this->config = $config; |
113 | $this->cacheManager = $cache; |
114 | $this->channelManager = $cm; |
115 | $this->searchRunner = $runner; |
116 | $this->recordLoader = $loader; |
117 | $this->locale = $locale; |
118 | } |
119 | |
120 | /** |
121 | * Get a search results object configured by channel providers. |
122 | * |
123 | * @param array $searchRequest Search request parameters |
124 | * @param array $providers Array of channel providers |
125 | * @param string $source Backend to use |
126 | * |
127 | * @return Results |
128 | */ |
129 | protected function performChannelSearch($searchRequest, $providers, $source) |
130 | { |
131 | // Perform search and configure providers: |
132 | $callback = function ($runner, $params) use ($providers) { |
133 | foreach ($providers as $provider) { |
134 | $provider->configureSearchParams($params); |
135 | } |
136 | }; |
137 | return $this->searchRunner->run($searchRequest, $source, $callback); |
138 | } |
139 | |
140 | /** |
141 | * Get channel details using an array of providers and a populated search |
142 | * results object. |
143 | * |
144 | * @param array $providers Array of channel providers |
145 | * @param Results $results Search results object from performChannelSearch |
146 | * @param string $token Optional channel token |
147 | * |
148 | * @return array |
149 | */ |
150 | protected function getChannelsFromResults($providers, Results $results, $token) |
151 | { |
152 | // Collect details: |
153 | $channels = []; |
154 | foreach ($providers as $provider) { |
155 | $channels = array_merge( |
156 | $channels, |
157 | $provider->getFromSearch($results, $token) |
158 | ); |
159 | } |
160 | return $channels; |
161 | } |
162 | |
163 | /** |
164 | * Get an array of channel providers matching the provided IDs (or just one, |
165 | * if the channelProvider GET parameter is set). |
166 | * |
167 | * @param string $source Search backend ID |
168 | * @param array $configSection Configuration section to load ID list from |
169 | * @param string $activeId Currently selected channel ID (if any; used |
170 | * when making an AJAX request for a single additional channel) |
171 | * |
172 | * @return array |
173 | */ |
174 | protected function getChannelProviders($source, $configSection, $activeId = null) |
175 | { |
176 | $providerIds = isset($this->config->{"source.$source"}->$configSection) |
177 | ? $this->config->{"source.$source"}->$configSection->toArray() : []; |
178 | $finalIds = (!empty($activeId) && in_array($activeId, $providerIds)) |
179 | ? [$activeId] : $providerIds; |
180 | return array_map([$this, 'getChannelProvider'], $finalIds); |
181 | } |
182 | |
183 | /** |
184 | * Convenience method to retrieve a channel provider. |
185 | * |
186 | * @param string $providerId Channel provider name and optional config |
187 | * (colon-delimited) |
188 | * |
189 | * @return ChannelProviderInterface |
190 | */ |
191 | protected function getChannelProvider($providerId) |
192 | { |
193 | // The provider ID consists of a service name and an optional config |
194 | // section -- break out the relevant parts: |
195 | [$serviceName, $configSection] = explode(':', $providerId . ':'); |
196 | |
197 | // Load configuration, using default value if necessary: |
198 | if (empty($configSection)) { |
199 | $configSection = "provider.$serviceName"; |
200 | } |
201 | $options = isset($this->config->{$configSection}) |
202 | ? $this->config->{$configSection}->toArray() : []; |
203 | |
204 | // Load the service, and configure appropriately: |
205 | $provider = $this->channelManager->get($serviceName); |
206 | $provider->setProviderId($providerId); |
207 | $provider->setOptions($options); |
208 | return $provider; |
209 | } |
210 | |
211 | /** |
212 | * Generates static front page of channels. |
213 | * |
214 | * @param string $token Channel token (optional, used for AJAX fetching) |
215 | * @param string $activeChannel Channel being requested (optional, used w/ token) |
216 | * @param string $activeSource Search backend to use (null to use configured |
217 | * default). |
218 | * |
219 | * @return array |
220 | */ |
221 | public function getHomeContext( |
222 | $token = null, |
223 | $activeChannel = null, |
224 | $activeSource = null |
225 | ) { |
226 | // Load appropriate channel objects: |
227 | $defaultSource = $this->config->General->default_home_source |
228 | ?? DEFAULT_SEARCH_BACKEND; |
229 | $source = $activeSource ?? $defaultSource; |
230 | $providers = $this->getChannelProviders($source, 'home', $activeChannel); |
231 | |
232 | // Set up the cache, if appropriate: |
233 | if ($this->config->General->cache_home_channels ?? false) { |
234 | $providerIds = array_map('get_class', $providers); |
235 | $parts = [implode(',', $providerIds), $source, $token, $this->locale]; |
236 | $cacheKey = md5(implode('-', $parts)); |
237 | $cache = $this->cacheManager->getCache('object', 'homeChannels'); |
238 | } else { |
239 | $cacheKey = false; |
240 | $cache = null; |
241 | } |
242 | |
243 | // Fetch channel data from cache, or populate cache if necessary: |
244 | if (!($channels = $cacheKey ? $cache->getItem($cacheKey) : false)) { |
245 | $searchParams = []; |
246 | if (isset($this->config->General->default_home_search)) { |
247 | $searchParams['lookfor'] |
248 | = $this->config->General->default_home_search; |
249 | } |
250 | $results = $this |
251 | ->performChannelSearch($searchParams, $providers, $source); |
252 | $channels = $this->getChannelsFromResults($providers, $results, $token); |
253 | if ($cacheKey) { |
254 | $cache->setItem($cacheKey, $channels); |
255 | } |
256 | } |
257 | |
258 | // Return context array: |
259 | return compact('token', 'channels'); |
260 | } |
261 | |
262 | /** |
263 | * Generates channels for a record. |
264 | * |
265 | * @param string $recordId Record ID to load |
266 | * @param string $token Channel token (optional, used for AJAX fetching) |
267 | * @param string $activeChannel Channel being requested (optional, used w/ token) |
268 | * @param string $source Search backend to use |
269 | * |
270 | * @return array |
271 | */ |
272 | public function getRecordContext( |
273 | $recordId, |
274 | $token = null, |
275 | $activeChannel = null, |
276 | $source = DEFAULT_SEARCH_BACKEND |
277 | ) { |
278 | // Load record: |
279 | $driver = $this->recordLoader->load($recordId, $source); |
280 | |
281 | // Load appropriate channel objects: |
282 | $providers = $this->getChannelProviders($source, 'record', $activeChannel); |
283 | |
284 | // Collect details: |
285 | $channels = []; |
286 | foreach ($providers as $provider) { |
287 | $channels = array_merge( |
288 | $channels, |
289 | $provider->getFromRecord($driver, $token) |
290 | ); |
291 | } |
292 | |
293 | // Return context array: |
294 | return compact('driver', 'channels', 'token'); |
295 | } |
296 | |
297 | /** |
298 | * Generates channels for a search. |
299 | * |
300 | * @param array $searchRequest Request parameters |
301 | * @param string $token Channel token (optional, used for AJAX fetching) |
302 | * @param string $activeChannel Channel being requested (optional, used w/ token) |
303 | * @param string $source Search backend to use |
304 | * |
305 | * @return array |
306 | */ |
307 | public function getSearchContext( |
308 | $searchRequest = [], |
309 | $token = null, |
310 | $activeChannel = null, |
311 | $source = DEFAULT_SEARCH_BACKEND |
312 | ) { |
313 | // Load appropriate channel objects: |
314 | $providers = $this->getChannelProviders($source, 'search', $activeChannel); |
315 | |
316 | // Perform search: |
317 | $results = $this->performChannelSearch($searchRequest, $providers, $source); |
318 | |
319 | // Collect details: |
320 | $lookfor = $searchRequest['lookfor'] ?? null; |
321 | $channels = $this->getChannelsFromResults($providers, $results, $token); |
322 | |
323 | // Return context array: |
324 | return compact('results', 'lookfor', 'channels', 'token'); |
325 | } |
326 | } |