Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 40
0.00% covered (danger)
0.00%
0 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
ApiController
0.00% covered (danger)
0.00%
0 / 40
0.00% covered (danger)
0.00%
0 / 4
156
0.00% covered (danger)
0.00%
0 / 1
 addApi
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
6
 indexAction
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
12
 getApiSpecFragment
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
2
 getApiSpecs
0.00% covered (danger)
0.00%
0 / 19
0.00% covered (danger)
0.00%
0 / 1
42
1<?php
2
3/**
4 * API Controller
5 *
6 * PHP version 8
7 *
8 * Copyright (C) The National Library of Finland 2015-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  Controller
25 * @author   Ere Maijala <ere.maijala@helsinki.fi>
26 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
27 * @link     https://vufind.org/wiki/development:plugins:controllers Wiki
28 */
29
30namespace VuFindApi\Controller;
31
32use function in_array;
33
34/**
35 * API Controller
36 *
37 * Controls the API functionality
38 *
39 * @category VuFind
40 * @package  Controller
41 * @author   Ere Maijala <ere.maijala@helsinki.fi>
42 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
43 * @link     https://vufind.org/wiki/development:plugins:controllers Wiki
44 */
45class ApiController extends \VuFind\Controller\AbstractBase
46{
47    use ApiTrait;
48
49    /**
50     * Array of available API controllers
51     *
52     * @var array
53     */
54    protected $apiControllers = [];
55
56    /**
57     * Add an API controller to the list of available controllers
58     *
59     * @param Laminas\Mvc\Controller\AbstractActionController $controller API
60     * Controller
61     *
62     * @return void
63     */
64    public function addApi($controller)
65    {
66        if (!in_array($controller, $this->apiControllers)) {
67            $this->apiControllers[] = $controller;
68        }
69    }
70
71    /**
72     * Index action
73     *
74     * Return API specification or redirect to Swagger UI
75     *
76     * @return \Laminas\Http\Response
77     */
78    public function indexAction()
79    {
80        // Disable session writes
81        $this->disableSessionWrites();
82
83        if (
84            null === $this->getRequest()->getQuery('swagger')
85            && null === $this->getRequest()->getQuery('openapi')
86        ) {
87            $urlHelper = $this->getViewRenderer()->plugin('url');
88            $base = rtrim($urlHelper('home'), '/');
89            $url = "$base/swagger-ui/?url=" . urlencode("$base/api?openapi");
90            return $this->redirect()->toUrl($url);
91        }
92        $response = $this->getResponse();
93        $headers = $response->getHeaders();
94        $headers->addHeaderLine('Content-type', 'application/json');
95        $json = json_encode($this->getApiSpecs(), JSON_PRETTY_PRINT);
96        $response->setContent($json);
97        return $response;
98    }
99
100    /**
101     * Get API specification JSON fragment for the root nodes
102     *
103     * @return string
104     */
105    protected function getApiSpecFragment()
106    {
107        $config = $this->getConfig();
108        $params = [
109            'config' => $config,
110            'version' => \VuFind\Config\Version::getBuildVersion(),
111        ];
112        return $this->getViewRenderer()->render('api/openapi', $params);
113    }
114
115    /**
116     * Merge specification fragments from all APIs to an array
117     *
118     * @return array
119     */
120    protected function getApiSpecs(): array
121    {
122        $results = [];
123
124        foreach (array_merge([$this], $this->apiControllers) as $controller) {
125            $api = $controller->getApiSpecFragment();
126            $specs = json_decode($api, true);
127            if (null === $specs) {
128                throw new \Exception(
129                    'Could not parse API spec fragment of '
130                    . $controller::class . ': ' . json_last_error_msg()
131                );
132            }
133            foreach ($specs as $key => $spec) {
134                if (isset($results[$key])) {
135                    if ('components' === $key) {
136                        $results['components']['schemas'] = array_merge(
137                            $results['components']['schemas'] ?? [],
138                            $spec['schemas'] ?? []
139                        );
140                    } else {
141                        $results[$key] = array_merge($results[$key], $spec);
142                    }
143                } else {
144                    $results[$key] = $spec;
145                }
146            }
147        }
148
149        return $results;
150    }
151}