Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
23.76% covered (danger)
23.76%
24 / 101
11.11% covered (danger)
11.11%
3 / 27
CRAP
0.00% covered (danger)
0.00%
0 / 1
EIT
23.76% covered (danger)
23.76%
24 / 101
11.11% covered (danger)
11.11%
3 / 27
1395.40
0.00% covered (danger)
0.00%
0 / 1
 setRawData
83.33% covered (warning)
83.33%
5 / 6
0.00% covered (danger)
0.00%
0 / 1
3.04
 getAllSubjectHeadings
57.14% covered (warning)
57.14%
4 / 7
0.00% covered (danger)
0.00%
0 / 1
3.71
 getBreadcrumb
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getCallNumbers
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getCleanOCLCNum
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getCleanISSN
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getDateSpan
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getEdition
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getFormats
60.00% covered (warning)
60.00%
3 / 5
0.00% covered (danger)
0.00%
0 / 1
5.02
 getPrimaryAuthors
60.00% covered (warning)
60.00%
3 / 5
0.00% covered (danger)
0.00%
0 / 1
5.02
 getPublicationDates
42.86% covered (danger)
42.86%
3 / 7
0.00% covered (danger)
0.00%
0 / 1
4.68
 getPublishers
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 getShortTitle
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getSummary
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
20
 getTitle
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getURLs
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
6
 getUniqueID
40.00% covered (danger)
40.00%
2 / 5
0.00% covered (danger)
0.00%
0 / 1
2.86
 getContainerTitle
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getContainerVolume
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getContainerIssue
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getContainerStartPage
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getContainerPageCount
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getContainerEndPage
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
6
 getSortTitle
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getOpenUrlFormat
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
20
 getCoinsID
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getContainerReference
0.00% covered (danger)
0.00%
0 / 22
0.00% covered (danger)
0.00%
0 / 1
56
1<?php
2
3/**
4 * Model for records retrieved via EBSCO's EIT API.
5 *
6 * PHP version 8
7 *
8 * Copyright (C) Julia Bauder 2013.
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  RecordDrivers
25 * @author   Julia Bauder <bauderj@grinnell.edu>
26 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
27 * @link     https://vufind.org/wiki/development:plugins:record_drivers Wiki
28 */
29
30namespace VuFind\RecordDriver;
31
32use function in_array;
33use function is_array;
34use function strlen;
35
36/**
37 * Model for records retrieved via EBSCO's EIT API.
38 *
39 * @category VuFind
40 * @package  RecordDrivers
41 * @author   Julia Bauder <bauderj@grinnell.edu>
42 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
43 * @link     https://vufind.org/wiki/development:plugins:record_drivers Wiki
44 */
45class EIT extends DefaultRecord
46{
47    use \VuFind\Log\VarDumperTrait;
48
49    /**
50     * Used for identifying search backends
51     *
52     * @var string
53     */
54    protected $sourceIdentifier = 'EIT';
55
56    /**
57     * Reference to controlInfo section of fields, for readability
58     *
59     * @var array
60     */
61    protected $controlInfo;
62
63    /**
64     * Set raw data to initialize the object.
65     *
66     * @param mixed $data Raw data representing the record; Record Model
67     * objects are normally constructed by Record Driver objects using data
68     * passed in from a Search Results object. The exact nature of the data may
69     * vary depending on the data source -- the important thing is that the
70     * Record Driver + Search Results objects work together correctly.
71     *
72     * @return void
73     */
74    public function setRawData($data)
75    {
76        // Easy way to recursively convert a SimpleXML Object to an array
77        $data = json_decode(json_encode((array)$data), 1);
78        if (isset($data['fields'])) {
79            $this->fields = $data['fields'];
80        } else {
81            // The following works for EITRecord pages
82            $this->fields['fields'] = $data;
83        }
84        if (isset($this->fields['fields']['header']['controlInfo'])) {
85            $this->controlInfo = & $this->fields['fields']['header']['controlInfo'];
86        }
87    }
88
89    /**
90     * Get all subject headings associated with this record. Each heading is
91     * returned as an array of chunks, increasing from least specific to most
92     * specific.
93     *
94     * @param bool $extended Whether to return a keyed array with the following
95     * keys:
96     * - heading: the actual subject heading chunks
97     * - type: heading type
98     * - source: source vocabulary
99     *
100     * @return array
101     */
102    public function getAllSubjectHeadings($extended = false)
103    {
104        $su = $this->controlInfo['artinfo']['su'] ?? [];
105
106        // The EIT index doesn't currently subject headings in a broken-down
107        // format, so we'll just send each value as a single chunk.
108        $retval = [];
109        foreach ($su as $s) {
110            $retval[] = $extended
111                ? ['heading' => [$s], 'type' => '', 'source' => '']
112                : [$s];
113        }
114        return $retval;
115    }
116
117    /**
118     * Get text that can be displayed to represent this record in
119     * breadcrumbs.
120     *
121     * @return string Breadcrumb text to represent this record.
122     */
123    public function getBreadcrumb()
124    {
125        return $this->controlInfo['artinfo']['tig']['atl'] ?? '';
126    }
127
128    /**
129     * Get the call numbers associated with the record (empty string if none).
130     *
131     * @return array
132     */
133    public function getCallNumbers()
134    {
135        return [];
136    }
137
138    /**
139     * Get just the first listed OCLC Number (or false if none available).
140     *
141     * @return mixed
142     */
143    public function getCleanOCLCNum()
144    {
145        return false;
146    }
147
148    /**
149     * Get just the first ISSN (or false if none available).
150     *
151     * @return mixed
152     */
153    public function getCleanISSN()
154    {
155        return $this->controlInfo['jinfo']['issn'] ?? false;
156    }
157
158    /**
159     * Get the date coverage for a record which spans a period of time (i.e. a
160     * journal). Use getPublicationDates for publication dates of particular
161     * monographic items.
162     *
163     * @return array
164     */
165    public function getDateSpan()
166    {
167        return [];
168    }
169
170    /**
171     * Get the edition of the current record.
172     *
173     * @return string
174     */
175    public function getEdition()
176    {
177        return null;
178    }
179
180    /**
181     * Get an array of all the formats associated with the record.
182     *
183     * @return array
184     */
185    public function getFormats()
186    {
187        if (
188            isset($this->controlInfo['artinfo']['doctype'])
189            && is_array($this->controlInfo['artinfo']['doctype'])
190        ) {
191            return $this->controlInfo['artinfo']['doctype'];
192        }
193        return isset($this->controlInfo['artinfo']['doctype'])
194            ? [$this->controlInfo['artinfo']['doctype']] : [];
195    }
196
197    /**
198     * Get the main author of the record.
199     *
200     * @return string
201     */
202    public function getPrimaryAuthors()
203    {
204        if (
205            isset($this->controlInfo['artinfo']['aug']['au'])
206            && is_array($this->controlInfo['artinfo']['aug']['au'])
207        ) {
208            return $this->controlInfo['artinfo']['aug']['au'];
209        } else {
210            return isset($this->controlInfo['artinfo']['aug']['au'])
211                ? [$this->controlInfo['artinfo']['aug']['au']] : [];
212        }
213    }
214
215    /**
216     * Get the publication dates of the record.  See also getDateSpan().
217     *
218     * @return array
219     */
220    public function getPublicationDates()
221    {
222        if (isset($this->controlInfo['pubinfo']['dt']['@attributes']['year'])) {
223            return [
224                $this->controlInfo['pubinfo']['dt']['@attributes']['year'],
225            ];
226        } elseif (isset($this->controlInfo['pubinfo']['dt'])) {
227            return [$this->controlInfo['pubinfo']['dt']];
228        } else {
229            return [];
230        }
231    }
232
233    /**
234     * Get the publishers of the record.
235     *
236     * @return array
237     */
238    public function getPublishers()
239    {
240        return isset($this->controlInfo['pubinfo']['pub'])
241            ? [$this->controlInfo['pubinfo']['pub']] : [];
242    }
243
244    /**
245     * Get the short (pre-subtitle) title of the record.
246     *
247     * @return string
248     */
249    public function getShortTitle()
250    {
251        return $this->controlInfo['artinfo']['tig']['atl'] ?? '';
252    }
253
254    /**
255     * Get an array of summary strings for the record.
256     *
257     * @return array
258     */
259    public function getSummary()
260    {
261        // We need to return an array, so if we have a description, turn it into an
262        // array as needed (it should be a flat string according to the default
263        // schema, but we might as well support the array case just to be on the safe
264        // side:
265        if (
266            isset($this->controlInfo['artinfo']['ab'])
267            && !empty($this->controlInfo['artinfo']['ab'])
268        ) {
269            return is_array($this->controlInfo['artinfo']['ab'])
270                ? $this->controlInfo['artinfo']['ab']
271                : [$this->controlInfo['artinfo']['ab']];
272        }
273
274        // If we got this far, no description was found:
275        return [];
276    }
277
278    /**
279     * Get the full title of the record.
280     *
281     * @return string
282     */
283    public function getTitle()
284    {
285        return $this->controlInfo['artinfo']['tig']['atl'] ?? '';
286    }
287
288    /**
289     * Return an array of associative URL arrays with one or more of the following
290     * keys:
291     *
292     * <li>
293     *   <ul>desc: URL description text to display (optional)</ul>
294     *   <ul>url: fully-formed URL (required if 'route' is absent)</ul>
295     *   <ul>route: VuFind route to build URL with (required if 'url' is absent)</ul>
296     *   <ul>routeParams: Parameters for route (optional)</ul>
297     *   <ul>queryString: Query params to append after building route (optional)</ul>
298     * </li>
299     *
300     * @return array
301     */
302    public function getURLs()
303    {
304        // If non-empty, map internal URL array to expected return format;
305        // otherwise, return empty array:
306        if (isset($this->fields['fields']['plink'])) {
307            $links = [$this->fields['fields']['plink']];
308            $desc = $this->translate('View this record in EBSCOhost');
309            $filter = function ($url) use ($desc) {
310                return compact('url', 'desc');
311            };
312            return array_map($filter, $links);
313        } else {
314            return [];
315        }
316    }
317
318    /**
319     * Return the unique identifier of this record within the Solr index;
320     * useful for retrieving additional information (like tags and user
321     * comments) from the external MySQL database.
322     *
323     * @return string Unique identifier.
324     */
325    public function getUniqueID()
326    {
327        if (!isset($this->fields['fields']['header']['@attributes']['uiTerm'])) {
328            throw new \Exception(
329                'ID not set!' . $this->varDump($this->fields['fields'])
330            );
331        }
332        return $this->fields['fields']['header']['@attributes']['uiTerm'];
333    }
334
335    /**
336     * Get the title of the item that contains this record (i.e. MARC 773s of a
337     * journal).
338     *
339     * @return string
340     */
341    public function getContainerTitle()
342    {
343        return $this->controlInfo['jinfo']['jtl'] ?? '';
344    }
345
346    /**
347     * Get the volume of the item that contains this record (i.e. MARC 773v of a
348     * journal).
349     *
350     * @return string
351     */
352    public function getContainerVolume()
353    {
354        return $this->controlInfo['pubinfo']['vid'] ?? null;
355    }
356
357    /**
358     * Get the issue of the item that contains this record (i.e. MARC 773l of a
359     * journal).
360     *
361     * @return string
362     */
363    public function getContainerIssue()
364    {
365        return $this->controlInfo['pubinfo']['iid'] ?? null;
366    }
367
368    /**
369     * Get the start page of the item that contains this record (i.e. MARC 773q of a
370     * journal).
371     *
372     * @return string
373     */
374    public function getContainerStartPage()
375    {
376        return $this->controlInfo['artinfo']['ppf'] ?? null;
377    }
378
379    /**
380     * Support method for getContainerEndPage()
381     *
382     * @return string
383     */
384    protected function getContainerPageCount()
385    {
386        return $this->controlInfo['artinfo']['ppct'] ?? null;
387    }
388
389    /**
390     * Get the end page of the item that contains this record.
391     *
392     * @return string
393     */
394    public function getContainerEndPage()
395    {
396        $startpage = $this->getContainerStartPage();
397        $pagecount = $this->getContainerPageCount();
398        $endpage = $startpage + $pagecount;
399        if ($endpage != 0) {
400            return $endpage;
401        } else {
402            return null;
403        }
404    }
405
406    /**
407     * Get a sortable title for the record (i.e. no leading articles).
408     *
409     * @return string
410     */
411    public function getSortTitle()
412    {
413        return $this->controlInfo['artinfo']['tig']['atl'] ?? '';
414    }
415
416    /**
417     * Support method for getOpenUrl() -- pick the OpenURL format.
418     *
419     * @return string
420     */
421    protected function getOpenUrlFormat()
422    {
423        // If we have multiple formats, Book, Journal and Article are most
424        // important...
425        $formats = $this->getFormats();
426        if (in_array('Book', $formats)) {
427            return 'Book';
428        } elseif (in_array('Article', $formats)) {
429            return 'Article';
430        } elseif (in_array('Journal', $formats)) {
431            return 'Journal';
432        }
433        // Defaulting to "Article" because many EBSCO databases have things like
434        // "Film Criticism" instead of "Article" -- the other defaults from the
435        // SolrDefault driver don't work well in this context.
436        return 'Article';
437    }
438
439    /**
440     * Get the COinS identifier.
441     *
442     * @return string
443     */
444    protected function getCoinsID()
445    {
446        // Added at Richard and Leslie's request, to facilitate ILL
447        return parent::getCoinsID() . '.ebsco';
448    }
449
450    /**
451     * Get a full, free-form reference to the context of the item that contains this
452     * record (i.e. volume, year, issue, pages).
453     *
454     * @return string
455     */
456    public function getContainerReference()
457    {
458        $str = '';
459        $vol = $this->getContainerVolume();
460        if (!empty($vol)) {
461            $str .= $this->translate('citation_volume_abbrev')
462                . ' ' . $vol;
463        }
464        $no = $this->getContainerIssue();
465        if (!empty($no)) {
466            if (strlen($str) > 0) {
467                $str .= '; ';
468            }
469            $str .= $this->translate('citation_issue_abbrev')
470                . ' ' . $no;
471        }
472        $start = $this->getContainerStartPage();
473        if (!empty($start)) {
474            if (strlen($str) > 0) {
475                $str .= '; ';
476            }
477            $end = $this->getContainerEndPage();
478            if ($start == $end) {
479                $str .= $this->translate('citation_singlepage_abbrev')
480                    . ' ' . $start;
481            } else {
482                $str .= $this->translate('citation_multipage_abbrev')
483                    . ' ' . $start . ' - ' . $end;
484            }
485        }
486        return $str;
487    }
488}