Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 44
0.00% covered (danger)
0.00%
0 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
OpenLibrary
0.00% covered (danger)
0.00%
0 / 44
0.00% covered (danger)
0.00%
0 / 4
420
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getSubjects
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
42
 processSubjectsApi
0.00% covered (danger)
0.00%
0 / 24
0.00% covered (danger)
0.00%
0 / 1
156
 normaliseSubjectString
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3/**
4 * Open Library Utilities
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  OpenLibrary
25 * @author   Eoghan Ó Carragáin <eoghan.ocarragain@gmail.com>
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\Connection;
31
32use function count;
33
34/**
35 * Open Library Utilities
36 *
37 * Class for accessing helpful Open Library APIs.
38 *
39 * @category VuFind
40 * @package  OpenLibrary
41 * @author   Eoghan Ó Carragáin <eoghan.ocarragain@gmail.com>
42 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
43 * @link     https://vufind.org/wiki/development Wiki
44 */
45class OpenLibrary
46{
47    /**
48     * HTTP client
49     *
50     * @var \Laminas\Http\Client
51     */
52    protected $client;
53
54    /**
55     * Constructor
56     *
57     * @param \Laminas\Http\Client $client HTTP client
58     */
59    public function __construct(\Laminas\Http\Client $client)
60    {
61        $this->client = $client;
62    }
63
64    /**
65     * Returns an array of elements for each work matching the
66     *    parameters. An API call will be made for each subjectType until
67     *    data is returned
68     *
69     * @param string $subject        The subject term to be looked for
70     * @param string $publishedIn    Date range in the form YYYY-YYYY
71     * @param array  $subjectTypes   An array of subject types to check
72     * @param bool   $ebooks         Whether to use ebook filter
73     * @param bool   $details        Whether to return full details
74     * @param int    $limit          The number of works to return
75     * @param int    $offset         Paging offset
76     * @param bool   $publicFullText Only return publicly available, full-text
77     * works
78     *
79     * @return array
80     */
81    public function getSubjects(
82        $subject,
83        $publishedIn,
84        $subjectTypes,
85        $ebooks = true,
86        $details = false,
87        $limit = 5,
88        $offset = null,
89        $publicFullText = true
90    ) {
91        // empty array to hold the result
92        $result = [];
93
94        // normalise subject term
95        $subject = $this->normaliseSubjectString($subject);
96        if ($ebooks) {
97            $ebooks = 'true';
98        }
99        if ($details) {
100            $details = 'true';
101        }
102
103        for ($i = 0; $i < count($subjectTypes); $i++) {
104            if (empty($result)) {
105                $subjectType = $subjectTypes[$i] == 'topic' ? '' :
106                    $subjectTypes[$i] . ':';
107
108                // build url
109                // ebooks parameter does not work at present, so limit has been set
110                // to 50 to increase likelihood of full-text, public scans being
111                // returned. see https://bugs.launchpad.net/openlibrary/+bug/709772
112                $url = 'http://openlibrary.org/subjects/' . $subjectType . $subject .
113                    '.json?ebooks=' . $ebooks . '&details=' . $details .
114                    '&offset=' . $offset . '&limit=50&published_in=' . $publishedIn;
115
116                // make API call
117                $result = $this->processSubjectsApi($url, $limit, $publicFullText);
118            }
119        }
120        return $result;
121    }
122
123    /**
124     * Return the following array of values for each work:
125     * title, cover_id, cover_id_type, key, ia, mainAuthor
126     *
127     * @param string $url            URL to request
128     * @param int    $limit          The number of works to return
129     * @param bool   $publicFullText Only return publicly available, full-text
130     * works
131     *
132     * @return array
133     */
134    protected function processSubjectsApi($url, $limit, $publicFullText)
135    {
136        // empty array to hold the result
137        $result = [];
138
139        // find out if there are any reviews
140        $response = $this->client->setUri($url)->setMethod('GET')->send();
141        // Was the request successful?
142        if ($response->isSuccess()) {
143            // grab the response:
144            $json = $response->getBody();
145            // parse json
146            $data = json_decode($json, true);
147            if ($data && isset($data['works']) && !empty($data['works'])) {
148                $i = 1;
149                foreach ($data['works'] as $work) {
150                    if ($i <= $limit) {
151                        if (
152                            $publicFullText && (!$work['public_scan']
153                            || !$work['has_fulltext'])
154                        ) {
155                            continue;
156                        }
157                        $result[$i]['title'] = $work['title'];
158                        if (isset($work['cover_id'])) {
159                            $result[$i]['cover_id_type'] = 'ID';
160                            $result[$i]['cover_id'] = $work['cover_id'];
161                        } elseif (isset($work['cover_edition_key'])) {
162                            $result[$i]['cover_id_type'] = 'OLID';
163                            $result[$i]['cover_id'] = $work['cover_edition_key'];
164                        }
165                        $result[$i]['key'] = $work['key'];
166                        $result[$i]['ia'] = $work['ia'];
167                        $result[$i]['mainAuthor'] = $work['authors'][0]['name'];
168                        $i++;
169                    }
170                }
171            }
172        }
173        return $result;
174    }
175
176    /**
177     * Support function to return a normalised version of the search string
178     *     for use in the API url
179     *
180     * @param string $subject Search string to normalise
181     *
182     * @return string
183     */
184    protected function normaliseSubjectString($subject)
185    {
186        // Normalise search term
187        $subject = str_replace(['"', ',', '/'], '', $subject);
188        $subject = trim(strtolower($subject));
189        $subject = preg_replace("/\s+/", '_', $subject);
190        return $subject;
191    }
192}