aboutsummaryrefslogtreecommitdiff
path: root/lib/classes/librarysearch/LibraryDocument.php
diff options
context:
space:
mode:
authorPhilipp Schüttlöffel <schuettloeffel@zqs.uni-hannover.de>2024-09-24 10:53:31 +0200
committerPhilipp Schüttlöffel <schuettloeffel@zqs.uni-hannover.de>2024-09-24 10:53:31 +0200
commit4459dd7917f4d1c34f40bb68f0e991e9c3d53e4c (patch)
tree5c07151ae61276d334e88f6309c30d439a85c12e /lib/classes/librarysearch/LibraryDocument.php
parentda0022e5c1abbf9825ae76debaabdff7e8623bb4 (diff)
parent97a188592c679890a25c37ab78463add76a52ff7 (diff)
Merge branch 'main' into issue-3911issue-3911
Diffstat (limited to 'lib/classes/librarysearch/LibraryDocument.php')
-rw-r--r--lib/classes/librarysearch/LibraryDocument.php442
1 files changed, 442 insertions, 0 deletions
diff --git a/lib/classes/librarysearch/LibraryDocument.php b/lib/classes/librarysearch/LibraryDocument.php
new file mode 100644
index 0000000..c1d297e
--- /dev/null
+++ b/lib/classes/librarysearch/LibraryDocument.php
@@ -0,0 +1,442 @@
+<?php
+/**
+ * This file is part of Stud.IP.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * @author Moritz Strohm <strohm@data-quest.de>
+ * @copyright 2020
+ * @license http://www.gnu.org/licenses/gpl-2.0.html GPL version 2
+ * @category Stud.IP
+ * @since 4.6
+ */
+
+/**
+ * This class represents a document from a library.
+ */
+class LibraryDocument
+{
+ /**
+ * An unique ID of the document.
+ */
+ public $id = '';
+
+
+ /**
+ * The OPAC ID of the document.
+ */
+ public $opac_document_id = '';
+
+
+ /**
+ * The link to the document page in the OPAC system.
+ */
+ public $opac_link = '';
+
+
+ /**
+ * The CSL document type.
+ */
+ public $type = '';
+
+
+ /**
+ * The CSL datafields.
+ */
+ public $csl_data = [];
+
+
+ /**
+ * The name of the catalog from which the document has been retrieved.
+ */
+ public $catalog = '';
+
+
+ /**
+ * Other data that cannot be stored in the $csl_data array.
+ */
+ public $datafields;
+
+
+ /**
+ * The search parameter that have been used to retrieve this item.
+ */
+ public $search_params = [];
+
+
+ /**
+ * Generates an ID for the document.
+ */
+ public function getId()
+ {
+ if (!$this->id) {
+ $this->id = md5(uniqid('LibraryDocument' . $this->getTitle()));
+ }
+ return $this->id;
+ }
+
+
+ /**
+ * Returns the type of the document as string.
+ *
+ * @returns string The type of the document.
+ */
+ public function getType($format = 'name'): string
+ {
+ global $LIBRARY_DOCUMENT_TYPES;
+
+ if ($format === 'name') {
+ return $this->type;
+ }
+ if ($format === 'display_name') {
+ $ldt = SimpleCollection::createFromArray($LIBRARY_DOCUMENT_TYPES);
+ $found = $ldt->findOneBy('name', $this->type);
+ $lang = in_array($_SESSION['_language'], ['de_DE', 'en_GB']) ? $_SESSION['_language'] : 'de_DE';
+ if ($found) {
+ return $found['display_name'][$lang];
+ }
+ }
+
+ return '';
+ }
+
+
+ /**
+ * Returns the title of the document as string.
+ *
+ * @param string $format The format of the title.
+ * 'short' means that only the title is returned.
+ * 'long' means that the author, the year and the title are
+ * concatenated into one string.
+ * 'long-comma' means that the author, the title and the year
+ * are concatenated in that order, only separated by a comma.
+ *
+ * @returns string The title of the document.
+ */
+ public function getTitle($format = 'short'): string
+ {
+ if ($format == 'long') {
+ $long_title = '';
+ if (isset($this->csl_data['issued'], $this->csl_data['author'])) {
+ $first_author_last_name = $this->csl_data['author'][0]['family'];
+ $year = $this->getIssueDate(true);
+ if ($year) {
+ $long_title = sprintf('%1$s (%2$s) - ', $first_author_last_name, $year);
+ } else {
+ $long_title = sprintf('%s - ', $first_author_last_name);
+ }
+ } elseif (isset($this->csl_data['author'])) {
+ $first_author_last_name = $this->csl_data['author'][0]['family'];
+ $long_title = sprintf('%s - ', $first_author_last_name);
+ }
+ $long_title .= $this->csl_data['title'] ?? '';
+ return $long_title;
+ } elseif ($format == 'long-comma') {
+ $data = [];
+ $first_author_last_name = trim($this->csl_data['author'][0]['family']);
+ $year = trim($this->getIssueDate(true));
+ if ($first_author_last_name) {
+ $data[] = $first_author_last_name;
+ }
+ $data[] = $this->csl_data['title'] ?? '';
+ if ($year) {
+ $data[] = $year;
+ }
+ return implode(', ', $data);
+ } else {
+ return $this->csl_data['title'] ?? '';
+ }
+ }
+
+
+ /**
+ * @returns string A list with all author names.
+ */
+ public function getAuthorNames(): string
+ {
+ if (empty($this->csl_data['author'])) {
+ return '';
+ }
+
+ $names = [];
+ foreach ($this->csl_data['author'] as $author) {
+ $names[] = sprintf('%1$s, %2$s', $author['family'], $author['given']);
+ }
+ return implode('; ', $names);
+ }
+
+
+ /**
+ * Returns a string with the issue date.
+ *
+ * @param bool $year_only Whether to return only the year of the date (true)
+ * or the whole date (false). Defaults to false.
+ *
+ * @returns string A string representing the issue date.
+ */
+ public function getIssueDate($year_only = false): string
+ {
+ if (!$this->csl_data['issued']) {
+ return '';
+ }
+ if ($year_only) {
+ $year = @$this->csl_data['issued']['date-parts'][0][0];
+ return $year ?: '';
+ }
+ return implode('-', $this->csl_data['issued']['date-parts'][0]) ?: '';
+ }
+
+
+ /**
+ * @returns string A string with identifiers of the document (ISBN, URL, ...).
+ */
+ public function getIdentifiers(): string
+ {
+ $identifiers = [];
+ if ($this->csl_data['ISBN']) {
+ $identifiers[] = sprintf(_('ISBN: %s'), $this->csl_data['ISBN']);
+ }
+ if ($this->csl_data['ISSN']) {
+ $identifiers[] = sprintf(_('ISSN: %s'), $this->csl_data['ISSN']);
+ }
+ return implode('; ', $identifiers);
+ }
+
+
+ /**
+ * Filters the CSL data fields by the document type.
+ * Only those CSL fields that are specified in library_config.inc.php for
+ * the document type are kept.
+ */
+ public function filterCslFieldsByType()
+ {
+ if (!$this->type) {
+ return;
+ }
+
+ $doc_type_config = null;
+ foreach ($GLOBALS['LIBRARY_DOCUMENT_TYPES'] as $doc_config) {
+ if ($doc_config['name'] == $this->type) {
+ $doc_type_config = $doc_config;
+ break;
+ }
+ }
+ if ($doc_type_config == null) {
+ return;
+ }
+ $this->csl_data = array_filter(
+ $this->csl_data,
+ function ($field) use ($doc_type_config) {
+ return in_array($field, $doc_type_config['properties']);
+ },
+ ARRAY_FILTER_USE_KEY
+ );
+ }
+
+
+ /**
+ * Converts this LibraryDocument to an associative array.
+ *
+ * @returns array An associative array containing the data of this
+ * LibraryDocument instance.
+ */
+ public function toArray(): array
+ {
+ $data = [
+ 'id' => $this->getId(),
+ 'type' => $this->getType(),
+ 'csl_data' => $this->csl_data,
+ 'datafields' => $this->datafields,
+ 'search_params' => $this->search_params,
+ 'catalog' => $this->catalog,
+ 'opac_link' => $this->opac_link
+ ];
+ return $data;
+ }
+
+
+ /**
+ * Converts this LibraryDocument to JSON data.
+ *
+ * @returns string A string containing the JSON encoded version of this
+ * LibraryDocument instance.
+ */
+ public function toJson(): string
+ {
+ return json_encode($this->toArray());
+ }
+
+
+ /**
+ * Fills or creates empty or missing CSL data fields that may be required
+ * when rendering the CSL data.
+ *
+ * @returns array The "enriched" CSL data from this document.
+ */
+ public function fillEmptyCslFields(): array
+ {
+ $enriched_data = [];
+ foreach ($this->csl_data as $key => $field) {
+ if ($key == 'author') {
+ if (!$field[0]['family']) {
+ $field[0]['family'] = ' ';
+ }
+ }
+ $enriched_data[$key] = $field;
+ }
+ //Make sure all "mandatory" fields are there:
+ if (!array_key_exists('author', $enriched_data)) {
+ $enriched_data['author'] = [
+ [
+ 'given' => '',
+ 'family' => ' ',
+ 'suffix' => ''
+ ]
+ ];
+ }
+ return $enriched_data;
+ }
+
+
+ /**
+ * Creates a LibraryDocument instance from an associative array.
+ *
+ * @param array $data An associative array containing data for
+ * a LibraryDocument instance.
+ *
+ * @returns LibraryDocument|null A LibraryDocument instance on success
+ * or null on failure.
+ */
+ public static function createFromArray(array $data = [])
+ {
+ if (!$data) {
+ return null;
+ }
+ $doc = new LibraryDocument();
+ $doc->id = $data['id'];
+ $doc->type = $data['type'];
+ $doc->csl_data = $data['csl_data'];
+ $doc->datafields = $data['datafields'];
+ $doc->search_params = $data['search_params'];
+ $doc->catalog = $data['catalog'] ?? null;
+ $doc->opac_link = $data['opac_link'] ?? null;
+ return $doc;
+ }
+
+
+ /**
+ * Creates a LibraryDocument instance from JSON data.
+ *
+ * @param string $json_string A JSON string containing data for
+ * a LibraryDocument instance.
+ *
+ * @returns LibraryDocument|null A LibraryDocument instance on success
+ * or null on failure.
+ */
+ public static function createFromJson(string $json_string = "")
+ {
+ if (!$json_string) {
+ return null;
+ }
+ $data = json_decode($json_string);
+ if (!$data) {
+ return null;
+ }
+ return self::createFromArray($data);
+ }
+
+
+ /**
+ * Determines if this document is equal to another document.
+ * Equality is determined by comparing various ID fields
+ * and as a last resort, the title, author and year are compared.
+ *
+ * @param LibraryDocument $other Another library document that shall be
+ * compared to this document.
+ *
+ * @returns bool True, if this document is equal to the other document,
+ * false otherwise.
+ */
+ public function isEqualTo(LibraryDocument $other): bool
+ {
+ if ($this->type != $other->type) {
+ //No need to do any further checks.
+ return false;
+ }
+ if ($this->id && ($this->id == $other->id)) {
+ return true;
+ } elseif ($this->csl_data['ISSN'] && ($this->csl_data['ISSN'] == $other->csl_data['ISSN'])) {
+ return true;
+ } elseif ($this->csl_data['ISBN'] && ($this->csl_data['ISBN'] == $other->csl_data['ISBN'])) {
+ return true;
+ } elseif ($this->csl_data['DOI'] && ($this->csl_data['DOI'] == $other->csl_data['DOI'])) {
+ return true;
+ } elseif ($this->csl_data['title'] && $this->csl_data['author'] && $this->csl_data['issued']
+ && ($this->csl_data['title'] == $other->csl_data['title'])
+ && ($this->csl_data['author'] == $other->csl_data['author'])
+ && ($this->csl_data['issued'] == $other->csl_data['issued'])) {
+ return true;
+ }
+ return false;
+ }
+
+
+ /**
+ * @returns Flexi\Template A template containing information about the
+ * the document.
+ */
+ public function getInfoTemplate($format = 'short')
+ {
+ $factory = new Flexi\Factory(
+ $GLOBALS['STUDIP_BASE_PATH'] . '/templates/library/'
+ );
+ $template = $factory->open('library_document_info');
+ $template->set_attribute('document', $this);
+ $template->set_attribute('format', $format);
+ return $template;
+ }
+
+
+ /**
+ * Creates a descriptive text of the search parameters that lead to the
+ * retrieval of this document.
+ *
+ * @returns string[] An array with a textual representation of all
+ * used search parameters.
+ */
+ public function getSearchDescription()
+ {
+ $description = [];
+ if (isset($this->search_params[LibrarySearch::AUTHOR])) {
+ $description[] = sprintf(_('Autor: „%s“'), $this->search_params[LibrarySearch::AUTHOR]);
+ }
+ if (isset($this->search_params[LibrarySearch::YEAR])) {
+ $description[] = sprintf(_('Jahr: „%s“'), $this->search_params[LibrarySearch::YEAR]);
+ }
+ if (isset($this->search_params[LibrarySearch::TITLE])) {
+ $description[] = sprintf(_('Titel: „%s“'), $this->search_params[LibrarySearch::TITLE]);
+ }
+ if (isset($this->search_params[LibrarySearch::NUMBER])) {
+ $description[] = sprintf(_('Nummer: „%s“'), $this->search_params[LibrarySearch::NUMBER]);
+ }
+ if (isset($this->search_params[LibrarySearch::PUBLICATION])) {
+ $description[] = sprintf(_('Zeitschrift: „%s“'), $this->search_params[LibrarySearch::PUBLICATION]);
+ }
+ if (isset($this->search_params[LibrarySearch::SIGNATURE])) {
+ $description[] = sprintf(_('Signatur: „%s“'), $this->search_params[LibrarySearch::SIGNATURE]);
+ }
+ return $description;
+ }
+
+ public function getIcon()
+ {
+ global $LIBRARY_DOCUMENT_TYPES;
+ $ldt = SimpleCollection::createFromArray($LIBRARY_DOCUMENT_TYPES);
+ $found = $ldt->findOneBy('name', $this->type);
+ $shape = $found['icon'] ?? 'literature-request';
+ return Icon::create($shape);
+ }
+}