Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
43 / 43
100.00% covered (success)
100.00%
3 / 3
CRAP
100.00% covered (success)
100.00%
1 / 1
DoiLookup
100.00% covered (success)
100.00%
43 / 43
100.00% covered (success)
100.00%
3 / 3
16
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
1
 handleRequest
100.00% covered (success)
100.00%
17 / 17
100.00% covered (success)
100.00%
1 / 1
9
 processIconLinks
100.00% covered (success)
100.00%
18 / 18
100.00% covered (success)
100.00%
1 / 1
6
1<?php
2
3/**
4 * AJAX handler to look up DOI data.
5 *
6 * PHP version 8
7 *
8 * Copyright (C) Villanova University 2018.
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  AJAX
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
30namespace VuFind\AjaxHandler;
31
32use Laminas\Mvc\Controller\Plugin\Params;
33use Laminas\View\Renderer\RendererInterface;
34use VuFind\DoiLinker\PluginManager;
35
36use function count;
37
38/**
39 * AJAX handler to look up DOI data.
40 *
41 * @category VuFind
42 * @package  AJAX
43 * @author   Demian Katz <demian.katz@villanova.edu>
44 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
45 * @link     https://vufind.org/wiki/development Wiki
46 */
47class DoiLookup extends AbstractBase
48{
49    /**
50     * DOI Linker Plugin Manager
51     *
52     * @var PluginManager
53     */
54    protected $pluginManager;
55
56    /**
57     * DOI resolver configuration value, exploded into an array of options
58     *
59     * @var string[]
60     */
61    protected $resolvers;
62
63    /**
64     * Behavior to use when multiple resolvers find results for the same DOI (may
65     * be 'first' -- use first match, or 'merge' -- use all results)
66     *
67     * @var string
68     */
69    protected $multiMode;
70
71    /**
72     * Whether to load icons via the cover proxy
73     *
74     * @var bool
75     */
76    protected $proxyIcons = false;
77
78    /**
79     * Whether to open links in a new window
80     *
81     * @var bool
82     */
83    protected $openInNewWindow = false;
84
85    /**
86     * View renderer
87     *
88     * @var RendererInterface
89     */
90    protected $viewRenderer = null;
91
92    /**
93     * Constructor
94     *
95     * @param PluginManager     $pluginManager DOI Linker Plugin Manager
96     * @param RendererInterface $viewRenderer  View renderer
97     * @param array             $config        Main configuration
98     */
99    public function __construct(
100        PluginManager $pluginManager,
101        RendererInterface $viewRenderer,
102        array $config
103    ) {
104        $this->pluginManager = $pluginManager;
105        $this->resolvers
106            = array_map('trim', explode(',', $config['DOI']['resolver'] ?? ''));
107        // Behavior to use when multiple resolvers to find results for the same
108        // DOI (may be 'first' -- use first match, or 'merge' -- use all
109        // results):
110        $this->multiMode
111            = trim(strtolower($config['DOI']['multi_resolver_mode'] ?? 'first'));
112        $this->proxyIcons = !empty($config['DOI']['proxy_icons']);
113        $this->openInNewWindow = !empty($config['DOI']['new_window']);
114        $this->viewRenderer = $viewRenderer;
115    }
116
117    /**
118     * Handle a request.
119     *
120     * @param Params $params Parameter helper from controller
121     *
122     * @return array [response data, HTTP status code]
123     */
124    public function handleRequest(Params $params)
125    {
126        $response = [];
127        $dois = (array)$params->fromQuery('doi', []);
128        foreach ($this->resolvers as $resolver) {
129            if ($this->pluginManager->has($resolver)) {
130                $next = $this->pluginManager->get($resolver)->getLinks($dois);
131                $next = $this->processIconLinks($next);
132                foreach ($next as $doi => $data) {
133                    foreach ($data as &$current) {
134                        $current['newWindow'] = $this->openInNewWindow;
135                    }
136                    unset($current);
137                    if (!isset($response[$doi])) {
138                        $response[$doi] = $data;
139                    } elseif ($this->multiMode == 'merge') {
140                        $response[$doi] = array_merge($response[$doi], $data);
141                    }
142                }
143                // If all DOIs have been found and we're not in merge mode, we
144                // can short circuit out of here.
145                if (
146                    $this->multiMode !== 'merge'
147                    && count(array_diff($dois, array_keys($response))) == 0
148                ) {
149                    break;
150                }
151            }
152        }
153        return $this->formatResponse($response);
154    }
155
156    /**
157     * Proxify external DOI icon links and render local icons
158     *
159     * @param array $dois DOIs
160     *
161     * @return array
162     */
163    protected function processIconLinks(array $dois): array
164    {
165        $serverHelper = $this->viewRenderer->plugin('serverurl');
166        $urlHelper = $this->viewRenderer->plugin('url');
167        $iconHelper = $this->viewRenderer->plugin('icon');
168
169        foreach ($dois as &$doiLinks) {
170            foreach ($doiLinks as &$doi) {
171                if ($this->proxyIcons && !empty($doi['icon'])) {
172                    $doi['icon'] = $serverHelper(
173                        $urlHelper(
174                            'cover-show',
175                            [],
176                            ['query' => ['proxy' => $doi['icon']]]
177                        )
178                    );
179                }
180                if (!empty($doi['localIcon'])) {
181                    $doi['localIcon'] = $iconHelper($doi['localIcon']);
182                }
183            }
184            unset($doi);
185        }
186        unset($doiLinks);
187        return $dois;
188    }
189}