*/ declare(strict_types = 1); /** * Represents an external norm data repository. */ enum MDNodaRepository implements MDValueEnumInterface, JsonSerializable { case allgemein; // General link to a good source case aat; case ackerbau; case bne; case bnf; case cona; case editionhumboldtdigital; case gnd; case grobsystematik; case iconclass; case klbb; case lcsh; case loc; // Duplicate? case mbl; case mindatorg; case moebeltypologie; case ndb_adb; case ndl; case ndp_ikmk; case ndp_ikmk_persons; case nomisma; case npg; case oberbegriffsdatei; case orcid; case osm; case pim; case pleiades; case rkd; case ulan; case viaf; case wikidata; case wikipedia; /** * Returns a value of this type based on a string. * * @param string $input Input to get a value from. * * @return MDNodaRepository */ public static function fromString(string $input):MDNodaRepository { return match($input) { 'allgemein' => self::allgemein, // General link to a good source 'aat' => self::aat, 'ackerbau' => self::ackerbau, 'bne' => self::bne, 'bnf' => self::bnf, 'cona' => self::cona, 'edition humboldt digital' => self::editionhumboldtdigital, 'gnd' => self::gnd, 'GND' => self::gnd, 'o-gnd' => self::gnd, 'O-GND' => self::gnd, 'pnd' => self::gnd, 'http://d-nb.info/gnd' => self::gnd, 'http://d-nb.info/gnd/' => self::gnd, 'd-nb.info' => self::gnd, 'https://portal.dnb.de' => self::gnd, 'grobsystematik' => self::grobsystematik, 'iconclass' => self::iconclass, 'klbb' => self::klbb, 'kl-bb' => self::klbb, 'lcsh' => self::lcsh, 'loc' => self::loc, // Duplicate? 'mbl' => self::mbl, 'MBL' => self::mbl, 'mindat.org' => self::mindatorg, 'moebeltypologie' => self::moebeltypologie, 'ndb/adb' => self::ndb_adb, 'NDB/ADB' => self::ndb_adb, 'ndl' => self::ndl, 'ndp-ikmk' => self::ndp_ikmk, 'ndp-ikmk-persons' => self::ndp_ikmk_persons, 'nomisma' => self::nomisma, 'npg' => self::npg, 'oberbegriffsdatei' => self::oberbegriffsdatei, 'orcid' => self::orcid, 'osm' => self::osm, 'pim' => self::pim, 'pleiades' => self::pleiades, 'rkd' => self::rkd, 'ulan' => self::ulan, 'ULAN' => self::ulan, 'viaf' => self::viaf, 'wikidata' => self::wikidata, 'Wikidata' => self::wikidata, 'WIKIDATA' => self::wikidata, 'WIKIPEDIA' => self::wikidata, 'wikipedia' => self::wikipedia, 'Wikipedia' => self::wikipedia, default => throw new MDpageParameterNotFromListException("Unknown noda repository: '" . $input . "'"), }; } /** * Returns the name as stored in the DB. * * @return string */ public function toDbName():string { return match($this) { self::allgemein => 'allgemein', // General link to a good source self::aat => 'aat', self::ackerbau => 'ackerbau', self::bne => 'bne', self::bnf => 'bnf', self::cona => 'cona', self::editionhumboldtdigital => 'edition humboldt digital', self::gnd => 'gnd', self::grobsystematik => 'grobsystematik', self::iconclass => 'iconclass', self::klbb => 'kl-bb', self::lcsh => 'lcsh', self::loc => 'loc', self::mbl => 'MBL', self::mindatorg => 'mindat.org', self::moebeltypologie => 'moebeltypologie', self::ndb_adb => 'NDB/ADB', self::ndl => 'ndl', self::ndp_ikmk => 'ndp-ikmk', self::ndp_ikmk_persons => 'ndp-ikmk-persons', self::nomisma => 'nomisma', self::npg => 'npg', self::oberbegriffsdatei => 'oberbegriffsdatei', self::orcid => 'orcid', self::osm => 'osm', self::pim => 'pim', self::pleiades => 'pleiades', self::rkd => 'rkd', self::ulan => 'ulan', self::viaf => 'viaf', self::wikidata => 'wikidata', self::wikipedia => 'Wikipedia', }; } /** * Returns the URL prefix for the current repository. * * @return string */ public function getUrlPrefix():string { return match($this) { self::allgemein => '', self::aat => 'https://vocab.getty.edu/page/aat/', self::ackerbau => 'https://term.museum-digital.de/ackerbau/tag/', self::bne => 'http://datos.bne.es/persona/', self::bnf => "https://catalogue.bnf.fr/ark:/12148/cb", self::cona => 'https://vocab.getty.edu/page/cona/', self::editionhumboldtdigital => 'https://edition-humboldt.de/register/personen/detail.xql?normid=http://d-nb.info/gnd/', self::gnd => 'https://d-nb.info/gnd/', self::grobsystematik => 'https://term.museum-digital.de/grobsystematik/tag/', self::iconclass => 'http://iconclass.org/rkd/', self::klbb => 'https://www.kl-bb.de/artist/', self::lcsh => 'http://id.loc.gov/authorities/names/', self::loc => 'http://id.loc.gov/authorities/names/', self::mbl => 'http://www.uni-magdeburg.de/mbl/PHP_Skripte/mbl_verwaltung/mbl_verw_anzeige_biog.php?auswahl=3&liste_biog_name=', self::mindatorg => 'https://www.mindat.org/min-', // Has suffix self::moebeltypologie => 'https://term.museum-digital.de/moebel/tag/', self::ndb_adb => 'https://www.deutsche-biographie.de/pnd', self::ndl => 'https://id.ndl.go.jp/auth/ndlna/', self::ndp_ikmk => 'https://ikmk.smb.museum/ndp/land/', self::ndp_ikmk_persons => 'https://ikmk.smb.museum/ndp/person/', self::nomisma => 'http://nomisma.org/id/', self::npg => 'https://www.npg.org.uk/collections/search/person/', self::oberbegriffsdatei => 'https://term.museum-digital.de/oberbegriffsdatei/tag/', self::orcid => 'https://orcid.org/', self::osm => 'https://www.openstreetmap.org/relation/', self::pim => 'https://opac-nevter.pim.hu/en/record/-/record/', self::pleiades => 'https://pleiades.stoa.org/places/', self::rkd => 'https://rkd.nl/explore/artists/', self::ulan => 'https://vocab.getty.edu/page/ulan/', self::viaf => 'https://viaf.org/viaf/', self::wikidata => 'https://www.wikidata.org/wiki/', self::wikipedia => 'https://de.wikipedia.org/wiki/', }; } /** * Returns the base of the repository's entity page URLs. * * @param string $id Identifier to link to. * * @return string */ public function getEntityLink(string $id):string { return match ($this) { self::ndb_adb => 'https://www.deutsche-biographie.de/pnd' . $id . '.html', self::mindatorg => 'https://www.mindat.org/min-' . $id . '.html', default => $this->getUrlPrefix() . $id, }; } /** * Returns a link to search for a given search term. * * @param string $searchTerm Search term. * * @return string */ public function getSearchLink(string $searchTerm):string { return match($this) { self::allgemein => 'https://www.google.de/search?q=' . urlencode($searchTerm), self::aat => 'https://www.getty.edu/vow/AATServlet?english=N&find=' . urlencode($searchTerm) . '&page=1¬e=', self::ackerbau => 'https://term.museum-digital.de/redir.php?search=' . urlencode($searchTerm) . '&kind=tag|ackerbau', self::bne => 'http://datos.bne.es/persona/' . urlencode($searchTerm), self::bnf => 'https://catalogue.bnf.fr/resultats-auteur.do?nomAuteur=' . urlencode($searchTerm) . '+&filtre=1&pageRech=rau', self::cona => 'http://vocab.getty.edu/page/cona/' . urlencode($searchTerm), self::editionhumboldtdigital => 'https://edition-humboldt.de/suche/ergebnisRegistersuche.xql?indexType=&q_text=' . urlencode($searchTerm), self::gnd => 'https://portal.dnb.de/opac.htm?method=moveDown¤tResultId=' . urlencode((string)str_replace(' ', ' and ', $searchTerm)) . '%26any&categoryId=subjects', self::grobsystematik => 'https://term.museum-digital.de/redir.php?search=' . urlencode($searchTerm) . '&kind=tag|grobsystematik', self::iconclass => 'http://iconclass.org/rkd/48C51/?q=' . urlencode($searchTerm) . '&q_s=1', self::lcsh => 'https://id.loc.gov/search/?q=cs:http://id.loc.gov/authorities/subjects&q=' . urlencode($searchTerm), self::klbb => 'https://www.kl-bb.de/gezielte-suche?page=gezielte-suche&artist_name=' . urlencode($searchTerm), self::loc => 'http://id.loc.gov/authorities/names/' . urlencode($searchTerm), self::mbl => 'http://www.uni-magdeburg.de/mbl/PHP_Skripte/mbl_verwaltung/mbl_verw_anzeige_biog.php?auswahl=7&suchbegriffe=' . urlencode($searchTerm) . '&methode=or&schreibung=nein', self::mindatorg => 'https://www.mindat.org/search.php?search=' . urlencode($searchTerm) . '&q_s=1', self::moebeltypologie => 'https://term.museum-digital.de/redir.php?search=' . urlencode($searchTerm) . '&kind=tag|moebel', self::ndb_adb => 'https://www.deutsche-biographie.de/search?name=' . urlencode($searchTerm), self::ndl => 'https://id.ndl.go.jp/auth/ndlna/' . urlencode($searchTerm), self::ndp_ikmk => 'https://ikmk.smb.museum/ndp/list?lang=de&q=' . urlencode($searchTerm), self::ndp_ikmk_persons => 'https://ikmk.smb.museum/ndp/list?lang=de&q=' . urlencode($searchTerm), self::nomisma => 'http://nomisma.org/browse?q=' . urlencode($searchTerm), self::npg => 'https://www.npg.org.uk/collections/search/person/' . urlencode($searchTerm), self::oberbegriffsdatei => 'https://term.museum-digital.de/redir.php?search=' . urlencode($searchTerm) . '&kind=tag|oberbegriffsdatei', self::orcid => 'https://orcid.org/' . urlencode($searchTerm), self::osm => 'https://www.openstreetmap.org/relation/' . urlencode($searchTerm), self::pim => 'https://opac-nevter.pim.hu/en/record/-/results/' . urlencode($searchTerm), self::pleiades => 'https://pleiades.stoa.org/search?SearchableText=' . urlencode($searchTerm), self::rkd => 'https://rkd.nl/en/explore#query=' . urlencode($searchTerm), self::ulan => 'http://www.getty.edu/vow/ULANServlet?english=Y&find=' . urlencode($searchTerm) . '&role=&page=1&nation=', self::viaf => 'https://viaf.org/viaf/search?query=local.names+all+' . urlencode('"' . $searchTerm . '"') . '"&sortKeys=holdingscount&recordSchema=BriefVIAF', self::wikidata => 'https://www.wikidata.org/w/index.php?search=&search=' . urlencode($searchTerm) . '&ns0=1&ns120=1', self::wikipedia => 'https://en.wikipedia.org/w/index.php?search=' . urlencode($searchTerm), }; } /** * Validates a numeric ID, returning a string or false. * * @param string $id ID to validate. * @param string[] $prefixes Prefixes to strip off. * * @return string|false */ private static function validateNumericId(string $id, array $prefixes):string|false { if (filter_var($id, FILTER_VALIDATE_URL) !== false) { $toRemove = []; foreach ($prefixes as $prefix) { $toRemove[$prefix] = ""; } $id = strtr($id, $toRemove); } // FILTER_VALIDATE_INT fails on overly large IDs (e.g. VIAF IDs having // more than 20 digits). // In these cases, simply check for the existence of non-numeric characters. if (strlen($id) > 9) { if (empty(trim($id, '0123456789'))) { return $id; } } // Strings starting with 0 are quite often linked, notably with the NDL. // PHP's FILTER_VALIDATE_INT does not accept a leading 0 however, so it // is stripped before checking. if (filter_var(ltrim($id, '0'), FILTER_VALIDATE_INT) === false) { return false; } return $id; } /** * Validates a iconclass ID, returning a string or false. * * @param string $id ID to validate. * * @return string|false */ private static function validateIconclassId(string $id):string|false { if (filter_var($id, FILTER_VALIDATE_URL) !== false) { $id = strtr($id, ['http://iconclass.org/rkd/' => '', 'http://iconclass.org/' => '', 'https://iconclass.org/' => '']); } if (preg_match("/^[0-9a-z\/]*$/", $id) === false) return false; return $id; } /** * Validates a BNE ID, returning a string or false. The BNE is basically equalivalent to the * GND, just that the X character can be prepended to the number. * * @param string $id ID to validate. * @param string[] $prefixes Prefixes to strip off. * * @return string|false */ private static function validateBneId(string $id, array $prefixes):string|false { return self::validateGndId($id, $prefixes); } /** * Validates a GND ID, returning a string or false. * * @param string $id ID to validate. * @param string[] $prefixes Prefixes to strip off. * * @return string|false */ private static function validateGndId(string $id, array $prefixes):string|false { if (filter_var($id, FILTER_VALIDATE_URL) !== false) { $toRemove = []; foreach ($prefixes as $prefix) $toRemove[$prefix] = ""; $id = strtr($id, $toRemove); } // There is an issue with this regex if (preg_match("/^[0-9-X]*$/", $id) === false) { return false; } if (is_numeric(strtr($id, ['-' => '', 'X' => ''])) === false) { return false; } return $id; } /** * Validates a Library of Congress name ID, returning a string or false. * * @param string $id ID to validate. * * @return string|false */ private static function validateLocId(string $id):string|false { if (filter_var($id, FILTER_VALIDATE_URL) !== false) { $id = strtr($id, [ 'http://id.loc.gov/authorities/names/' => '', 'https://id.loc.gov/authorities/names/' => '', ]); } if (in_array(substr($id, 0, 2), ['nr', 'nb', 'no'], true)) { if (filter_var(trim(substr($id, 2), '0'), FILTER_VALIDATE_INT) === false) return false; } else if (substr($id, 0, 1) === 'n') { if (filter_var(trim(substr($id, 1), '0'), FILTER_VALIDATE_INT) === false) return false; } else if (substr($id, 0, 2) === 'sh') { throw new MDInvalidNodaLinkLocIdIsSh("The link to the Library of Congress authority files refers to the LOC Subject Headings. The subject headings are listed as a separate vocabulary."); } else throw new MDInvalidNodaLinkException("LOC IDs must start with n or nr or nb (provided: " . strip_tags($id) . ")"); return (string)$id; } /** * Validates a LCSH ID, returning a string or false. * * @param string $id ID to validate. * * @return string|false */ private static function validateLcshId(string $id):string|false { if (filter_var($id, FILTER_VALIDATE_URL) !== false) { $id = strtr($id, [ 'http://id.loc.gov/authorities/names/' => '', 'https://id.loc.gov/authorities/names/' => '', 'http://id.loc.gov/authorities/subjects/' => '', 'https://id.loc.gov/authorities/subjects/' => '', '.html' => '', ]); } if (substr($id, 0, 2) !== 'sh') { throw new MDInvalidNodaLinkException("LCSH IDs must start with sh"); } if (filter_var(ltrim(substr($id, 2), "0"), FILTER_VALIDATE_INT) === false) { return false; } return $id; } /** * Validates a PIM ID, returning a string or false. * * @param string $id ID to validate. * * @return string|false */ private static function validatePimId(string $id):string|false { if (filter_var($id, FILTER_VALIDATE_URL) !== false) { $toRemove = []; foreach ([ 'https://opac-nevter.pim.hu/en/record/-/record/', 'https://resolver.pim.hu/auth/', ] as $prefix) { $toRemove[$prefix] = ""; } $id = strtr($id, $toRemove); } // There is an issue with this regex if (preg_match("/^[0-9-PIM]*$/", $id) === false) { return false; } if (is_numeric(substr($id, 3)) === false) { return false; } return $id; } /** * Validates an NPG ID, returning a string or false. * * @param string $id ID to validate. * * @return string|false */ private static function validateNpgId(string $id):string|false { if (filter_var($id, FILTER_VALIDATE_URL) !== false) { $id = strtr($id, ['https://www.npg.org.uk/collections/search/person/' => '']); } if (substr($id, 0, 2) === 'mp' && is_numeric(substr($id, 2))) { return $id; } if (filter_var($id, FILTER_VALIDATE_INT) === false) { return false; } return $id; } /** * Validates a wikidata ID, returning a string or false. * * @param string $id ID to validate. * * @return string|false */ private static function validateWikidataId(string $id):string|false { if (filter_var($id, FILTER_VALIDATE_URL) !== false) { $id = strtr($id, ['https://www.wikidata.org/wiki/' => '']); } if (substr($id, 0, 1) !== 'Q') { throw new MDgenericInvalidInputsException("Wikidata IDs must be Q IDs - and start with that letter"); } if (filter_var(substr($id, 1), FILTER_VALIDATE_INT) === false) { return false; } return $id; } /** * Validates a BNF ID. BNF IDs are either fully numeric or end on a single non-numeric character. * * @param string $id ID to validate. * * @return string|false */ public static function validateBnfId(string $id):string|false { if (!is_numeric(substr($id, -1))) { $validation = self::validateNumericId(substr($id, 0, -1), ["https://catalogue.bnf.fr/ark:/12148/cb"]); } else $validation = self::validateNumericId($id, ["https://catalogue.bnf.fr/ark:/12148/cb"]); if ($validation === false) return false; return $id; } /** * Validates a Wikipedia link. * * @param string $id ID to validate. * * @return string|false */ public static function validateWikipediaId(string $id):string|false { $validation = strtr($id, [ 'http://de.wikipedia.org/wiki/' => '', 'https://de.wikipedia.org/wiki/' => '', 'http://en.wikipedia.org/wiki/' => '', 'https://en.wikipedia.org/wiki/' => '', 'http://fr.wikipedia.org/wiki/' => '', 'https://fr.wikipedia.org/wiki/' => '', 'http://nl.wikipedia.org/wiki/' => '', 'https://nl.wikipedia.org/wiki/' => '', 'http://sv.wikipedia.org/wiki/' => '', 'https://sv.wikipedia.org/wiki/' => '', 'http://ru.wikipedia.org/wiki/' => '', 'https://ru.wikipedia.org/wiki/' => '', ]); if (str_contains($validation, "/")) return false; return $validation; } /** * Validates an ID. * * @param string $id Identifier to link to. * * @return string|false */ public function validateId(string $id):string|false { return match($this) { self::allgemein => filter_var($id, FILTER_VALIDATE_URL), self::aat => self::validateNumericId($id, [ 'http://vocab.getty.edu/aat/', 'http://vocab.getty.edu/page/aat/', 'https://vocab.getty.edu/aat/', 'https://vocab.getty.edu/page/aat/', ]), self::ackerbau => self::validateNumericId($id, ['https://term.museum-digital.de/ackerbau/tag/']), self::bne => self::validateBneId($id, ['http://datos.bne.es/persona/']), self::bnf => self::validateBnfId($id), self::cona => self::validateNumericId($id, ['https://vocab.getty.edu/page/cona/']), self::editionhumboldtdigital => self::validateGndId($id, ['https://edition-humboldt.de/register/personen/detail.xql?normid=http://d-nb.info/gnd/']), self::gnd => self::validateGndId($id, ['http://d-nb.info/gnd/', 'https://d-nb.info/gnd/']), self::grobsystematik => self::validateNumericId($id, ['https://term.museum-digital.de/grobsystematik/tag/']), self::iconclass => self::validateIconclassId($id), self::klbb => self::validateNumericId($id, ['https://www.kl-bb.de/artist/', 'https://www.kl-bb.de/?page=actor&subPage=']), self::lcsh => self::validateLcshId($id), self::loc => self::validateLocId($id), self::mbl => self::validateNumericId($id, ['http://www.uni-magdeburg.de/mbl/PHP_Skripte/mbl_verwaltung/mbl_verw_anzeige_biog.php?auswahl=3&liste_biog_name=']), self::mindatorg => self::validateNumericId($id, ['https://www.mindat.org/min-', '.html']), self::moebeltypologie => self::validateNumericId($id, ['https://term.museum-digital.de/moebel/tag/']), self::ndb_adb => self::validateGndId($id, ['https://www.deutsche-biographie.de/pnd', '.html', '#adbcontent', '#ndbcontent']), self::ndl => self::validateNumericId($id, [ 'http://id.ndl.go.jp/auth/ndlna/', 'https://id.ndl.go.jp/auth/ndlna/', ]), self::ndp_ikmk => self::validateNumericId($id, ['https://ikmk.smb.museum/ndp/land/']), self::ndp_ikmk_persons => self::validateNumericId($id, ['https://ikmk.smb.museum/ndp/person/']), self::nomisma => str_replace('http://nomisma.org/id/', '', $id), self::npg => self::validateNpgId($id), self::oberbegriffsdatei => self::validateNumericId($id, ['https://term.museum-digital.de/oberbegriffsdatei/tag/']), self::orcid => preg_match('/^[0-9]{4}-[0-9]{4}-[0-9]{4}-[0-9]{4}$/', $id) ? $id : false, self::osm => self::validateNumericId($id, ['https://www.openstreetmap.org/relation/']), self::pim => self::validatePimId($id), self::pleiades => self::validateNumericId($id, ['https://pleiades.stoa.org/places/']), self::rkd => self::validateNumericId($id, ['http://rkd.nl/explore/artists/', 'https://rkd.nl/explore/artists/']), self::ulan => self::validateNumericId($id, [ 'http://vocab.getty.edu/ulan/', 'http://vocab.getty.edu/page/ulan/', 'https://vocab.getty.edu/page/ulan/', 'http://www.getty.edu/vow/ULANFullDisplay?find=&role=&nation=&subjectid=', 'https://www.getty.edu/vow/ULANFullDisplay?find=&role=&nation=&subjectid=', ]), self::viaf => self::validateNumericId($id, [ 'https://viaf.org/viaf/', 'http://viaf.org/viaf/', ]), self::wikidata => self::validateWikidataId($id), self::wikipedia => self::validateWikipediaId($id), }; } /** * Lists all available names. * * @return array */ public static function caseNames():array { $output = []; $cases = self::cases(); foreach ($cases as $case) { $output[] = $case->name; } return $output; } /** * Gets an unsorted list of the entries in a translated version. * * @param MDTlLoader $tlLoader Translation loader. * * @return array */ public static function getUnsortedList(MDTlLoader $tlLoader):array { return MDValueSet::getTlUnsortedList($tlLoader, self::caseNames(), "attendance_status_set", "attendance_status_set"); } /** * Gets a sorted list of the entries in a translated version. * * @param MDTlLoader $tlLoader Translation loader. * * @return array */ public static function getSortedList(MDTlLoader $tlLoader):array { return MDValueSet::getTlSortedList($tlLoader, self::caseNames(), "attendance_status_set", "attendance_status_set"); } /** * Returns the name of the current value in translation. * * @param MDTlLoader $tlLoader Translation loader. * * @return string */ public function getTledName(MDTlLoader $tlLoader):string { return $tlLoader->tl("attendance_status_set", "attendance_status_set", $this->name); } /** * Provides the option to serialize as a string during json_encode(). * * @return string */ public function jsonSerialize():string { return $this->name; } }