From 4828560900b696447164c38c6a5ebd763c3db592 Mon Sep 17 00:00:00 2001 From: Demian Katz <demian.katz@villanova.edu> Date: Fri, 15 May 2020 07:10:18 -0400 Subject: [PATCH] Add website API access. (#1620) --- config/vufind/WebApiRecordFields.yaml | 27 +++++++ module/VuFindApi/config/module.config.php | 27 ++++++- .../Controller/ApiControllerFactory.php | 1 + .../Controller/Search2ApiController.php | 14 ++++ .../Controller/SearchApiController.php | 16 ++++ .../VuFindApi/Controller/WebApiController.php | 78 +++++++++++++++++++ .../Controller/WebApiControllerFactory.php | 70 +++++++++++++++++ .../Formatter/WebRecordFormatter.php | 42 ++++++++++ .../Formatter/WebRecordFormatterFactory.php | 48 ++++++++++++ themes/root/templates/searchapi/swagger.phtml | 18 ++--- 10 files changed, 331 insertions(+), 10 deletions(-) create mode 100644 config/vufind/WebApiRecordFields.yaml create mode 100644 module/VuFindApi/src/VuFindApi/Controller/WebApiController.php create mode 100644 module/VuFindApi/src/VuFindApi/Controller/WebApiControllerFactory.php create mode 100644 module/VuFindApi/src/VuFindApi/Formatter/WebRecordFormatter.php create mode 100644 module/VuFindApi/src/VuFindApi/Formatter/WebRecordFormatterFactory.php diff --git a/config/vufind/WebApiRecordFields.yaml b/config/vufind/WebApiRecordFields.yaml new file mode 100644 index 00000000000..ac94e097696 --- /dev/null +++ b/config/vufind/WebApiRecordFields.yaml @@ -0,0 +1,27 @@ +# Key is the field name that can be requested. It has the following subkeys: +# - vufind.method: name to call (either in the SearchApiController class or the record driver) +# - vufind.default: true if the field is displayed by default when the request does not specify fields +# - Swagger specification fields describing the returned data. +# +# See http://swagger.io/specification/ for information on the Swagger-specific fields +# +id: + vufind.method: getUniqueID + vufind.default: true + description: Record unique ID (can be used in the record endpoint) + type: string +lastModified: + vufind.method: getLastModified + vufind.default: true + description: Last modification date + type: string +title: + vufind.method: getTitle + vufind.default: true + description: Title including any subtitle + type: string +url: + vufind.method: getUrl + vufind.default: true + description: URL for resource + type: string diff --git a/module/VuFindApi/config/module.config.php b/module/VuFindApi/config/module.config.php index 6c0df9838eb..35d91142f48 100644 --- a/module/VuFindApi/config/module.config.php +++ b/module/VuFindApi/config/module.config.php @@ -7,11 +7,13 @@ $config = [ 'VuFindApi\Controller\ApiController' => 'VuFindApi\Controller\ApiControllerFactory', 'VuFindApi\Controller\SearchApiController' => 'VuFindApi\Controller\SearchApiControllerFactory', 'VuFindApi\Controller\Search2ApiController' => 'VuFindApi\Controller\Search2ApiControllerFactory', + 'VuFindApi\Controller\WebApiController' => 'VuFindApi\Controller\WebApiControllerFactory', ], 'aliases' => [ 'Api' => 'VuFindApi\Controller\ApiController', 'SearchApi' => 'VuFindApi\Controller\SearchApiController', 'Search2Api' => 'VuFindApi\Controller\Search2ApiController', + 'WebApi' => 'VuFindApi\Controller\WebApiController', ], ], 'service_manager' => [ @@ -19,6 +21,7 @@ $config = [ 'VuFindApi\Formatter\FacetFormatter' => 'Laminas\ServiceManager\Factory\InvokableFactory', 'VuFindApi\Formatter\RecordFormatter' => 'VuFindApi\Formatter\RecordFormatterFactory', 'VuFindApi\Formatter\Search2RecordFormatter' => 'VuFindApi\Formatter\Search2RecordFormatterFactory', + 'VuFindApi\Formatter\WebRecordFormatter' => 'VuFindApi\Formatter\WebRecordFormatterFactory', ], ], 'router' => [ @@ -77,7 +80,29 @@ $config = [ 'action' => 'record', ] ] - ] + ], + 'websearchApiv1' => [ + 'type' => 'Laminas\Router\Http\Literal', + 'verb' => 'get,post,options', + 'options' => [ + 'route' => '/api/v1/web/search', + 'defaults' => [ + 'controller' => 'WebApi', + 'action' => 'search', + ] + ] + ], + 'webrecordApiv1' => [ + 'type' => 'Laminas\Router\Http\Literal', + 'verb' => 'get,post,options', + 'options' => [ + 'route' => '/api/v1/web/record', + 'defaults' => [ + 'controller' => 'WebApi', + 'action' => 'record', + ] + ] + ], ], ], ]; diff --git a/module/VuFindApi/src/VuFindApi/Controller/ApiControllerFactory.php b/module/VuFindApi/src/VuFindApi/Controller/ApiControllerFactory.php index 62c41e24b68..a4e1bb5d42c 100644 --- a/module/VuFindApi/src/VuFindApi/Controller/ApiControllerFactory.php +++ b/module/VuFindApi/src/VuFindApi/Controller/ApiControllerFactory.php @@ -64,6 +64,7 @@ class ApiControllerFactory implements FactoryInterface $controller = new $requestedName($container); $controller->addApi($container->get('ControllerManager')->get('SearchApi')); $controller->addApi($container->get('ControllerManager')->get('Search2Api')); + $controller->addApi($container->get('ControllerManager')->get('WebApi')); return $controller; } } diff --git a/module/VuFindApi/src/VuFindApi/Controller/Search2ApiController.php b/module/VuFindApi/src/VuFindApi/Controller/Search2ApiController.php index 1e636d20689..196f2564522 100644 --- a/module/VuFindApi/src/VuFindApi/Controller/Search2ApiController.php +++ b/module/VuFindApi/src/VuFindApi/Controller/Search2ApiController.php @@ -61,4 +61,18 @@ class Search2ApiController extends SearchApiController * @var string */ protected $searchRoute = 'index2/search'; + + /** + * Descriptive label for the index managed by this controller + * + * @var string + */ + protected $indexLabel = 'secondary'; + + /** + * Prefix for use in model names used by API + * + * @var string + */ + protected $modelPrefix = 'Secondary'; } diff --git a/module/VuFindApi/src/VuFindApi/Controller/SearchApiController.php b/module/VuFindApi/src/VuFindApi/Controller/SearchApiController.php index d26db72868a..c618fa2e2c3 100644 --- a/module/VuFindApi/src/VuFindApi/Controller/SearchApiController.php +++ b/module/VuFindApi/src/VuFindApi/Controller/SearchApiController.php @@ -96,6 +96,20 @@ class SearchApiController extends \VuFind\Controller\AbstractSearch */ protected $searchRoute = 'search'; + /** + * Descriptive label for the index managed by this controller + * + * @var string + */ + protected $indexLabel = 'primary'; + + /** + * Prefix for use in model names used by API + * + * @var string + */ + protected $modelPrefix = ''; + /** * Constructor * @@ -142,6 +156,8 @@ class SearchApiController extends \VuFind\Controller\AbstractSearch 'recordRoute' => $this->recordRoute, 'searchRoute' => $this->searchRoute, 'searchIndex' => $this->searchClassId, + 'indexLabel' => $this->indexLabel, + 'modelPrefix' => $this->modelPrefix, ]; $json = $this->getViewRenderer()->render( 'searchapi/swagger', $viewParams diff --git a/module/VuFindApi/src/VuFindApi/Controller/WebApiController.php b/module/VuFindApi/src/VuFindApi/Controller/WebApiController.php new file mode 100644 index 00000000000..89d9033080b --- /dev/null +++ b/module/VuFindApi/src/VuFindApi/Controller/WebApiController.php @@ -0,0 +1,78 @@ +<?php + +/** + * Class WebApiController + * + * PHP version 7 + * + * Copyright (C) Villanova University 2020. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category VuFind + * @package VuFindApi\Controller + * @author Demian Katz <demian.katz@villanova.edu> + * @license https://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://knihovny.cz Main Page + */ +namespace VuFindApi\Controller; + +/** + * Web API Controller + * + * Controls the Search API functionality on website index + * + * @category VuFind + * @package VuFindApi\Controller + * @author Demian Katz <demian.katz@villanova.edu> + * @license https://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development:plugins:controllers Wiki + */ +class WebApiController extends SearchApiController +{ + /** + * Search class family to use. + * + * @var string + */ + protected $searchClassId = 'SolrWeb'; + + /** + * Record route uri + * + * @var string + */ + protected $recordRoute = 'web/record'; + + /** + * Search route uri + * + * @var string + */ + protected $searchRoute = 'web/search'; + + /** + * Descriptive label for the index managed by this controller + * + * @var string + */ + protected $indexLabel = 'website'; + + /** + * Prefix for use in model names used by API + * + * @var string + */ + protected $modelPrefix = 'Web'; +} diff --git a/module/VuFindApi/src/VuFindApi/Controller/WebApiControllerFactory.php b/module/VuFindApi/src/VuFindApi/Controller/WebApiControllerFactory.php new file mode 100644 index 00000000000..09804ec356b --- /dev/null +++ b/module/VuFindApi/src/VuFindApi/Controller/WebApiControllerFactory.php @@ -0,0 +1,70 @@ +<?php +/** + * Factory for WebApiController. + * + * PHP version 7 + * + * Copyright (C) Villanova University 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category VuFind + * @package Controller + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development:plugins:controllers Wiki + */ +namespace VuFindApi\Controller; + +use Interop\Container\ContainerInterface; +use Laminas\ServiceManager\Factory\FactoryInterface; + +/** + * Factory for WebApiController. + * + * @category VuFind + * @package Controller + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development:plugins:controllers Wiki + */ +class WebApiControllerFactory implements FactoryInterface +{ + /** + * Create an object + * + * @param ContainerInterface $container Service manager + * @param string $requestedName Service being created + * @param null|array $options Extra options (optional) + * + * @return object + * + * @throws ServiceNotFoundException if unable to resolve the service. + * @throws ServiceNotCreatedException if an exception is raised when + * creating a service. + * @throws ContainerException if any other error occurs + */ + public function __invoke(ContainerInterface $container, $requestedName, + array $options = null + ) { + if (!empty($options)) { + throw new \Exception('Unexpected options sent to factory.'); + } + return new $requestedName( + $container, + $container->get(\VuFindApi\Formatter\WebRecordFormatter::class), + $container->get(\VuFindApi\Formatter\FacetFormatter::class) + ); + } +} diff --git a/module/VuFindApi/src/VuFindApi/Formatter/WebRecordFormatter.php b/module/VuFindApi/src/VuFindApi/Formatter/WebRecordFormatter.php new file mode 100644 index 00000000000..4e7e342eb69 --- /dev/null +++ b/module/VuFindApi/src/VuFindApi/Formatter/WebRecordFormatter.php @@ -0,0 +1,42 @@ +<?php + +/** + * Class WebRecordFormatter + * + * PHP version 7 + * + * Copyright (C) Villanova University 2020. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category VuFind + * @package API_Formatter + * @author Demian Katz <demian.katz@villanova.edu> + * @license https://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development Wiki + */ +namespace VuFindApi\Formatter; + +/** + * Record formatter for web API responses + * + * @category VuFind + * @package API_Formatter + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development Wiki + */ +class WebRecordFormatter extends RecordFormatter +{ +} diff --git a/module/VuFindApi/src/VuFindApi/Formatter/WebRecordFormatterFactory.php b/module/VuFindApi/src/VuFindApi/Formatter/WebRecordFormatterFactory.php new file mode 100644 index 00000000000..067b33dab82 --- /dev/null +++ b/module/VuFindApi/src/VuFindApi/Formatter/WebRecordFormatterFactory.php @@ -0,0 +1,48 @@ +<?php + +/** + * Class WebRecordFormatterFactory + * + * PHP version 7 + * + * Copyright (C) Villanova University 2020. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category VuFind + * @package API_Formatter + * @author Demian Katz <demian.katz@villanova.edu> + * @license https://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development Wiki + */ +namespace VuFindApi\Formatter; + +/** + * Web Record Formatter factory. + * + * @category VuFind + * @package API_Formatter + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development Wiki + */ +class WebRecordFormatterFactory extends RecordFormatterFactory +{ + /** + * Record fields configuration file name + * + * @var string + */ + protected $configFile = 'WebApiRecordFields.yaml'; +} diff --git a/themes/root/templates/searchapi/swagger.phtml b/themes/root/templates/searchapi/swagger.phtml index ed27073c35d..56d16141646 100644 --- a/themes/root/templates/searchapi/swagger.phtml +++ b/themes/root/templates/searchapi/swagger.phtml @@ -40,8 +40,8 @@ "paths": { "/<?=$recordRoute?>": { "get": { - "summary": "Fetch records from <?=($this->searchIndex == 'Solr') ? "primary" : "secondary" ?> index", - "description": "Return a single record or multiple records from <?=($this->searchIndex == 'Solr') ? "primary" : "secondary" ?> index. POST method may also be used if sending a long request.", + "summary": "Fetch records from <?=$this->indexLabel?> index", + "description": "Return a single record or multiple records from <?=$this->indexLabel?> index. POST method may also be used if sending a long request.", "parameters": [ { "name": "id", @@ -71,7 +71,7 @@ "200": { "description": "Response containing result count and records", "schema": { - "$ref": "#/definitions/SearchResponse" + "$ref": "#/definitions/<?=$this->modelPrefix?>SearchResponse" } }, "default": { @@ -85,8 +85,8 @@ }, "/<?=$searchRoute?>": { "get": { - "summary": "Search <?=($this->searchIndex == 'Solr') ? "primary" : "secondary" ?> index", - "description": "Search <?=($this->searchIndex == 'Solr') ? "primary" : "secondary" ?> index with given terms and filters. POST method may also be used if sending a long request.\n\nThe URL syntax here is the as the one used in VuFind user interface. It is possible to make a search in VuFind and copy the query parameters here to make the same search via the API.", + "summary": "Search <?=$this->indexLabel?> index", + "description": "Search <?=$this->indexLabel?> index with given terms and filters. POST method may also be used if sending a long request.\n\nThe URL syntax here is the as the one used in VuFind user interface. It is possible to make a search in VuFind and copy the query parameters here to make the same search via the API.", "parameters": [ { "name": "lookfor", @@ -168,7 +168,7 @@ "200": { "description": "Response containing result count, records and/or facets.", "schema": { - "$ref": "#/definitions/SearchResponse" + "$ref": "#/definitions/<?=$this->modelPrefix?>SearchResponse" } }, "default": { @@ -287,7 +287,7 @@ } } }, - "Record": { + "<?=$this->modelPrefix?>Record": { "type": "object", "properties": <?=json_encode($this->recordFields) ?> }, @@ -307,7 +307,7 @@ } } }, - "SearchResponse": { + "<?=$this->modelPrefix?>SearchResponse": { "type": "object", "properties": { "resultCount": { @@ -318,7 +318,7 @@ "description": "Records", "type": "array", "items": { - "$ref": "#/definitions/Record" + "$ref": "#/definitions/<?=$this->modelPrefix?>Record" } }, "facets": { -- GitLab