diff --git a/src/classes/MDNodaLink.php b/src/classes/MDNodaLink.php new file mode 100644 index 0000000..fd0f72e --- /dev/null +++ b/src/classes/MDNodaLink.php @@ -0,0 +1,34 @@ + + */ +declare(strict_types = 1); + +/** + * Describes a reference to an external norm data repository. + */ +final class MDNodaLink { + + public readonly MDNodaRepository $source; + public readonly string $id; + + /** + * Constructor. + * + * @param MDNodaRepository $source Source repository. + * @param string $id ID. + * + * @return void + */ + public function __construct(MDNodaRepository $source, string $id) { + + $this->source = $source; + if (($validatedId = $this->source->validateId(trim($id))) === false) { + throw new MDInvalidNodaLink("Invalid noda ID / link: " . $id . " [Repository: " . $this->source->toDbName() . "]"); + } + $this->id = $validatedId; + + } +} diff --git a/src/classes/README.md b/src/classes/README.md new file mode 100644 index 0000000..c2e68d4 --- /dev/null +++ b/src/classes/README.md @@ -0,0 +1 @@ +# Full-scale data types that provide further functionality but end up representing base data types diff --git a/src/enums/MDNodaRepository.php b/src/enums/MDNodaRepository.php new file mode 100644 index 0000000..9e15ca6 --- /dev/null +++ b/src/enums/MDNodaRepository.php @@ -0,0 +1,426 @@ + + */ +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 lcsh; + case loc; // Duplicate? + case mbl; + case mindatorg; + case moebeltypologie; + case ndb_adb; + case ndl; + case ndp_ikmk; + 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, + 'grobsystematik' => self::grobsystematik, + 'iconclass' => self::iconclass, + '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, + 'ndl' => self::ndl, + 'ndp-ikmk' => self::ndp_ikmk, + '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, + 'viaf' => self::viaf, + 'wikidata' => self::wikidata, + 'Wikidata' => 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::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::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 => 'Wikidata', + }; + + } + + /** + * 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::allgemein => $id, + self::aat => 'https://vocab.getty.edu/page/aat/' . $id, + self::ackerbau => 'https://term.museum-digital.de/ackerbau/tag/' . $id, + self::bne => 'http://datos.bne.es/persona/' . $id, + self::bnf => "https://catalogue.bnf.fr/ark:/12148/cb" . $id, + self::cona => 'https://vocab.getty.edu/page/cona/' . $id, + self::editionhumboldtdigital => 'https://edition-humboldt.de/register/personen/detail.xql?normid=http://d-nb.info/gnd/' . $id, + self::gnd => 'https://d-nb.info/gnd/' . $id, + self::grobsystematik => 'https://term.museum-digital.de/grobsystematik/tag/' . $id, + self::iconclass => 'http://iconclass.org/rkd/' . $id, + self::lcsh => 'http://id.loc.gov/authorities/names/' . $id, + self::loc => 'http://id.loc.gov/authorities/names/' . $id, + self::mbl => 'http://www.uni-magdeburg.de/mbl/PHP_Skripte/mbl_verwaltung/mbl_verw_anzeige_biog.php?auswahl=3&liste_biog_name=' . $id, + self::mindatorg => 'https://www.mindat.org/min-' . $id . '.html', + self::moebeltypologie => 'https://term.museum-digital.de/moebel/tag/' . $id, + self::ndb_adb => 'https://www.deutsche-biographie.de/pnd' . $id . '.html', + self::ndl => 'https://id.ndl.go.jp/auth/ndlna/' . $id, + self::ndp_ikmk => 'https://ikmk.smb.museum/ndp/land/' . $id, + self::nomisma => 'http://nomisma.org/id/' . $id, + self::npg => 'https://www.npg.org.uk/collections/search/person/' . $id, + self::oberbegriffsdatei => 'https://term.museum-digital.de/oberbegriffsdatei/tag/' . $id, + self::orcid => 'https://orcid.org/' . $id, + self::osm => 'https://www.openstreetmap.org/relation/' . $id, + self::pim => 'https://opac-nevter.pim.hu/en/record/-/record/' . $id, + self::pleiades => 'https://pleiades.stoa.org/places/' . $id, + self::rkd => 'https://rkd.nl/explore/artists/' . $id, + self::ulan => 'https://vocab.getty.edu/page/ulan/' . $id, + self::viaf => 'https://viaf.org/viaf/' . $id, + self::wikidata => 'https://www.wikidata.org/wiki/' . $id, + self::wikipedia => 'https://de.wikipedia.org/wiki/' . $id, + }; + + } + + /** + * 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); + } + + if (filter_var($id, 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 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); + } + + if (preg_match("/^[0-9-X]*$/", $id) === 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/' => '']); + } + + if (substr($id, 0, 1) !== 'n') { + throw new MDgenericInvalidInputsException("LOC IDs must start with n"); + } + + if (filter_var(substr($id, 1), FILTER_VALIDATE_INT) === false) { + return false; + } + + return $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/' => '']); + } + + if (substr($id, 0, 2) !== 'sh') { + throw new MDgenericInvalidInputsException("LCSH IDs must start with sh"); + } + + if (filter_var(ltrim(substr($id, 2), "0"), 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 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, ['https://vocab.getty.edu/page/aat/']), + self::ackerbau => self::validateNumericId($id, ['https://term.museum-digital.de/ackerbau/tag/']), + self::bne => self::validateNumericId($id, ['http://datos.bne.es/persona/']), + self::bnf => self::validateNumericId($id, ["https://catalogue.bnf.fr/ark:/12148/cb"]), + 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, ['https://d-nb.info/gnd/']), + self::grobsystematik => self::validateNumericId($id, ['https://term.museum-digital.de/grobsystematik/tag/']), + self::iconclass => self::validateIconclassId($id), + 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']), + self::ndl => self::validateNumericId($id, ['https://id.ndl.go.jp/auth/ndlna/']), + self::ndp_ikmk => self::validateNumericId($id, ['https://ikmk.smb.museum/ndp/land/']), + self::nomisma => self::validateNumericId($id, ['http://nomisma.org/id/']), + self::npg => self::validateNumericId($id, ['https://www.npg.org.uk/collections/search/person/']), + 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::validateNumericId($id, ['https://opac-nevter.pim.hu/en/record/-/record/']), + 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/']), + self::viaf => self::validateNumericId($id, ['https://viaf.org/viaf/']), + self::wikidata => self::validateWikidataId($id), + self::wikipedia => str_replace('https://de.wikipedia.org/wiki/', '', $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; + + } +}