Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
45 / 45
100.00% covered (success)
100.00%
5 / 5
CRAP
100.00% covered (success)
100.00%
1 / 1
Router
100.00% covered (success)
100.00%
45 / 45
100.00% covered (success)
100.00%
5 / 5
15
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getActionRouteDetails
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getTabRouteDetails
100.00% covered (success)
100.00%
23 / 23
100.00% covered (success)
100.00%
1 / 1
8
 getRouteDetails
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
3
 extractSourceAndId
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3/**
4 * Record route generator
5 *
6 * PHP version 8
7 *
8 * Copyright (C) Villanova University 2010.
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  Record
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 Main Site
28 */
29
30namespace VuFind\Record;
31
32use function count;
33use function is_object;
34
35/**
36 * Record route generator
37 *
38 * @category VuFind
39 * @package  Record
40 * @author   Demian Katz <demian.katz@villanova.edu>
41 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
42 * @link     https://vufind.org Main Site
43 */
44class Router
45{
46    /**
47     * VuFind configuration
48     *
49     * @var \Laminas\Config\Config
50     */
51    protected $config;
52
53    /**
54     * Constructor
55     *
56     * @param \Laminas\Config\Config $config VuFind configuration
57     */
58    public function __construct(\Laminas\Config\Config $config)
59    {
60        $this->config = $config;
61    }
62
63    /**
64     * Get routing details for a controller action.
65     *
66     * @param \VuFind\RecordDriver\AbstractBase|string $driver Record driver
67     * representing record to link to, or source|id pipe-delimited string
68     * @param string                                   $action Action to access
69     *
70     * @return array
71     */
72    public function getActionRouteDetails($driver, $action)
73    {
74        return $this->getRouteDetails($driver, '-' . strtolower($action));
75    }
76
77    /**
78     * Get routing details to display a particular tab.
79     *
80     * @param \VuFind\RecordDriver\AbstractBase|string $driver Record driver
81     * representing record to link to, or source|id pipe-delimited string
82     * @param string                                   $tab    Action to access
83     * @param array                                    $query  Optional query params
84     *
85     * @return array
86     */
87    public function getTabRouteDetails($driver, $tab = null, $query = [])
88    {
89        $route = $this->getRouteDetails(
90            $driver,
91            '',
92            empty($tab) ? [] : ['tab' => $tab]
93        );
94        // Add the options and query elements only if we need a query to avoid
95        // an empty element in the route definition:
96        if ($query) {
97            $route['options']['query'] = $query;
98        }
99
100        // If collections are active and the record route was selected, we need
101        // to check if the driver is actually a collection; if so, we should switch
102        // routes.
103        if ($this->config->Collections->collections ?? false) {
104            $routeConfig = isset($this->config->Collections->route)
105                ? $this->config->Collections->route->toArray() : [];
106            $collectionRoutes
107                = array_merge(
108                    ['record' => 'collection',
109                     'search2record' => 'search2collection'],
110                    $routeConfig
111                );
112            $routeName = $route['route'];
113            if ($collectionRoute = ($collectionRoutes[$routeName] ?? null)) {
114                if (!is_object($driver)) {
115                    // Avoid loading the driver. Set a flag so that if the link is
116                    // used, record controller will check for redirection.
117                    $route['options']['query']['checkRoute'] = 1;
118                } elseif (true === $driver->tryMethod('isCollection')) {
119                    $route['route'] = $collectionRoute;
120                }
121            }
122        }
123        return $route;
124    }
125
126    /**
127     * Get routing details (route name and parameters array) to link to a record.
128     *
129     * @param \VuFind\RecordDriver\AbstractBase|string $driver      Record driver
130     * representing record to link to, or source|id pipe-delimited string
131     * @param string                                   $routeSuffix Suffix to add
132     * to route name
133     * @param array                                    $extraParams Extra parameters
134     * for route
135     *
136     * @return array
137     */
138    public function getRouteDetails(
139        $driver,
140        $routeSuffix = '',
141        $extraParams = []
142    ) {
143        // Extract source and ID from driver or string:
144        if (is_object($driver)) {
145            $source = $driver->getSourceIdentifier();
146            $id = $driver->getUniqueId();
147        } else {
148            [$source, $id] = $this->extractSourceAndId($driver);
149        }
150
151        // Build URL parameters:
152        $params = $extraParams;
153        $params['id'] = $id;
154
155        // Determine route based on naming convention (default VuFind route is
156        // the exception to the rule):
157        $routeBase = ($source == DEFAULT_SEARCH_BACKEND)
158            ? 'record' : strtolower($source . 'record');
159
160        // Disable path normalization since it can unencode e.g. encoded slashes in
161        // record id's
162        $options = [
163            'normalize_path' => false,
164        ];
165
166        return [
167            'params' => $params,
168            'route' => $routeBase . $routeSuffix,
169            'options' => $options,
170        ];
171    }
172
173    /**
174     * Extract source and ID from a pipe-delimited string, adding a default
175     * source if appropriate.
176     *
177     * @param string $driver source|ID string
178     *
179     * @return array
180     */
181    protected function extractSourceAndId($driver)
182    {
183        $parts = explode('|', $driver, 2);
184        if (count($parts) < 2) {
185            $source = DEFAULT_SEARCH_BACKEND;
186            $id = $parts[0];
187        } else {
188            $source = $parts[0];
189            $id = $parts[1];
190        }
191        return [$source, $id];
192    }
193}