├── tests ├── fixtures │ └── Base │ │ ├── config │ │ ├── basic │ │ │ ├── conf │ │ │ │ ├── articles.lst │ │ │ │ └── datasources.ini │ │ │ └── mappings │ │ │ │ ├── building_sub.map │ │ │ │ └── building.map │ │ ├── fieldmappertest │ │ │ ├── mappings │ │ │ │ ├── building_sub.map │ │ │ │ ├── building.map │ │ │ │ ├── building-regexp-no-default.map │ │ │ │ ├── building-regexp-multi.map │ │ │ │ ├── building-basic.map │ │ │ │ ├── building-regexp.map │ │ │ │ └── rights.map │ │ │ └── conf │ │ │ │ └── datasources.ini │ │ └── recorddrivertest │ │ │ └── conf │ │ │ └── articles.lst │ │ ├── marc_formats │ │ ├── legacy_v1.json │ │ ├── legacy_v3.json │ │ ├── marc_in_json.json │ │ └── legacy_v2.json │ │ ├── Enrichment │ │ ├── skosmos_author_results.json │ │ ├── skosmos_geographic_results.json │ │ ├── skosmos_authority_results.json │ │ ├── skosmos_exactmatch_results.json │ │ ├── skosmos_excluded_location_results.json │ │ ├── skosmos_multilang_results.json │ │ ├── music_brainz_results.json │ │ └── skosmos_results.json │ │ ├── record │ │ ├── qdc_skosmos.xml │ │ ├── marc_skosmos_3.xml │ │ ├── marc_relator.xml │ │ ├── marc_authority_1.xml │ │ ├── forward_skosmos.xml │ │ ├── marc_authority_skosmos.xml │ │ ├── marc_music_2.xml │ │ ├── marc_music_4.xml │ │ ├── marc_auth_no_ids.xml │ │ ├── ead3_skosmos.xml │ │ ├── marc_music_5.xml │ │ ├── marc_auth_1.xml │ │ ├── marc_skosmos_1.xml │ │ ├── marc_skosmos_2.xml │ │ ├── marc_skosmos_multilang.xml │ │ ├── marc_skosmos_exactmatch.xml │ │ ├── marc_skosmos_invalid_uri.xml │ │ ├── dc1.xml │ │ ├── marc_skosmos_excluded_location.xml │ │ ├── marc_auth_missing_authority.xml │ │ ├── lido3.xml │ │ ├── lido2.xml │ │ ├── marc_music_6.xml │ │ ├── lido_skosmos.xml │ │ ├── marc_empty_field.json │ │ ├── qdc1.xml │ │ └── doaj1.xml │ │ ├── Solr │ │ └── holdings_record.xml │ │ ├── utils │ │ └── LineBasedMarcFormatter │ │ │ ├── alma.txt │ │ │ ├── alma.xml │ │ │ └── genieplus.txt │ │ └── Controller │ │ └── CreatePreview │ │ ├── preview_marc.xml │ │ └── preview_result.json ├── phpunit.xml ├── phpstan.neon ├── phpmd.xml ├── phpcs.xml ├── psalm-defines.php ├── bootstrap.php ├── psalm-autoload.php ├── rector.php └── RecordManagerTest │ └── Base │ ├── Utils │ └── LcCallNumberTest.php │ └── Record │ ├── RecordTestBase.php │ └── EaccpfTest.php ├── conf ├── abbreviations.lst.sample ├── modules.config.php.sample ├── full-title-prefixes.lst.sample ├── articles.lst.sample ├── oai-pmh-sets.ini.sample ├── wikidataPlaceTypeExclude.lst.sample ├── mmlPlaceTypeExclude.lst.sample ├── oai-pmh-formats.ini.sample └── application.config.php ├── httpd-recman-oai-pmh.conf ├── httpd-recman-preview.conf ├── mappings ├── building_voyager.map.sample ├── dewey_hundreds.map ├── dc_type.map.sample ├── ead_level_to_format.map.sample ├── educational_audience.map.sample ├── callnumber.map.sample ├── forward_role.map.sample ├── educational_material_type.map.sample ├── lido_type_to_format_hierarchy.map.sample ├── forward_id_role.map.sample ├── format.map.sample ├── usage_rights.map.sample ├── iso639-1_to_iso639-2.map └── marc_format_to_hierarchy.map.sample ├── composer.local.json.dist ├── .gitignore ├── transformations ├── strip_namespaces.xsl ├── ese2ese.xsl ├── lido_normalization.xsl ├── sfx.xsl ├── sfx.properties ├── elka.properties ├── helmet.properties ├── metalib_ird.properties ├── lido_normalization.properties ├── marc2oai_dc.properties ├── koha.properties.sample ├── ese2ese_fng.properties ├── elka.xsl ├── marc2ese_raita.properties ├── koha.xsl.sample ├── helmet.xsl └── metalib_ird.xsl ├── dbscripts └── mongo.js ├── utils ├── update_skosmos_data.sh └── delete_ids.sh ├── psalm.xml ├── datasources.php ├── logs.php ├── import.php ├── oai-pmh.php ├── harvest.php ├── src └── RecordManager │ └── Base │ ├── Exception │ ├── HttpRequestException.php │ └── RequestException.php │ ├── Database │ ├── AbstractAuthorityDatabase.php │ ├── Regex.php │ ├── PDOResultIterator.php │ └── AbstractDatabaseFactory.php │ ├── Harvest │ ├── PluginManager.php │ └── AbstractBaseFactory.php │ ├── Enrichment │ └── PluginManager.php │ ├── Splitter │ ├── PluginManager.php │ ├── SplitterInterface.php │ ├── AbstractBase.php │ └── AbstractBaseFactory.php │ ├── Module.php │ ├── Command │ ├── PluginManager.php │ ├── Solr │ │ └── Optimize.php │ ├── Util │ │ └── IniFileTrait.php │ └── Records │ │ └── Dump.php │ ├── Utils │ ├── XmlSecurity.php │ ├── AbstractCallNumber.php │ ├── LoggerFactory.php │ ├── WorkerPoolManagerFactory.php │ ├── MetadataUtilsFactory.php │ ├── PerformanceCounter.php │ └── FieldMapperFactory.php │ ├── Solr │ └── PreviewCreator.php │ ├── ConsoleRunner.php │ ├── ConsoleRunnerFactory.php │ ├── Http │ └── HttpServiceFactory.php │ ├── Application.php │ └── Record │ └── AbstractRecordFactory.php ├── export.php ├── console ├── composer.json ├── manage.php └── .github └── workflows └── ci.yaml /tests/fixtures/Base/config/basic/conf/articles.lst: -------------------------------------------------------------------------------- 1 | 'The ' 2 | 'l'' 3 | -------------------------------------------------------------------------------- /tests/fixtures/Base/config/basic/mappings/building_sub.map: -------------------------------------------------------------------------------- 1 | ^(\d)$ = $1 2 | (.+) = 3 | -------------------------------------------------------------------------------- /tests/fixtures/Base/config/fieldmappertest/mappings/building_sub.map: -------------------------------------------------------------------------------- 1 | ^(\d)$ = $1 2 | (.+) = 3 | -------------------------------------------------------------------------------- /tests/fixtures/Base/config/recorddrivertest/conf/articles.lst: -------------------------------------------------------------------------------- 1 | 'The ' 2 | 'A ' 3 | 'An ' 4 | 'El ' 5 | 'Le ' 6 | -------------------------------------------------------------------------------- /tests/fixtures/Base/config/basic/mappings/building.map: -------------------------------------------------------------------------------- 1 | A1 = A 2 | A2 =A 3 | B1 = B 4 | C1 = 5 | ##default = DEF 6 | -------------------------------------------------------------------------------- /conf/abbreviations.lst.sample: -------------------------------------------------------------------------------- 1 | ; List of abbreviations in lower case 2 | 'ill.' 3 | 'col.' 4 | 'mr.' 5 | 'mrs.' 6 | 'ms.' 7 | -------------------------------------------------------------------------------- /tests/fixtures/Base/config/fieldmappertest/mappings/building.map: -------------------------------------------------------------------------------- 1 | A1 = A 2 | A2 =A 3 | B1 = B 4 | C1 = 5 | ##default = DEF 6 | -------------------------------------------------------------------------------- /tests/fixtures/Base/config/fieldmappertest/mappings/building-regexp-no-default.map: -------------------------------------------------------------------------------- 1 | ([a-z]+)(\d) = $1/$2 2 | ([a-z]+) = string 3 | ^\d+(.*)$ = $1 4 | -------------------------------------------------------------------------------- /conf/modules.config.php.sample: -------------------------------------------------------------------------------- 1 | 5 | 6 | Order allow,deny 7 | Allow from all 8 | 9 | 10 | Require all granted 11 | 12 | 13 | -------------------------------------------------------------------------------- /httpd-recman-preview.conf: -------------------------------------------------------------------------------- 1 | # Define Path 2 | Alias /preview /usr/local/RecordManager/preview.php 3 | 4 | 5 | 6 | Order allow,deny 7 | Allow from all 8 | 9 | 10 | Require all granted 11 | 12 | 13 | -------------------------------------------------------------------------------- /mappings/building_voyager.map.sample: -------------------------------------------------------------------------------- 1 | ; Map multiple main library locations into one facet location 100 2 | 1001 = 100 3 | 1002 = 100 4 | 1003 = 100 5 | 6 | ; Map branch library locations into one 7 | 1101 = 110 8 | 1102 = 110 9 | 10 | ; Map all other locations to a third one 11 | ##default = 120 12 | 13 | ; Map records with no location to their own 14 | ##emptyarray = 130 15 | -------------------------------------------------------------------------------- /mappings/dewey_hundreds.map: -------------------------------------------------------------------------------- 1 | 000 = 000 - Computer science, information & general works 2 | 100 = 100 - Philosophy & psychology 3 | 200 = 200 - Religion 4 | 300 = 300 - Social sciences 5 | 400 = 400 - Language 6 | 500 = 500 - Science 7 | 600 = 600 - Technology 8 | 700 = 700 - Arts & recreation 9 | 800 = 800 - Literature 10 | 900 = 900 - History & geography 11 | ##default = [Unassigned] 12 | -------------------------------------------------------------------------------- /composer.local.json.dist: -------------------------------------------------------------------------------- 1 | { 2 | "__comment__": [ 3 | "Rename this file from composer.local.json.dist to composer.local.json to" 4 | "manage your local dependencies without changing the core composer.json." 5 | "See https://github.com/wikimedia/composer-merge-plugin for more details." 6 | ], 7 | "require": { 8 | "example/dependency": "1.0.0" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tests/phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ../src 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /mappings/dc_type.map.sample: -------------------------------------------------------------------------------- 1 | = Other/Text 2 | Text = Other/Text 3 | Master's thesis = Thesis/Masters 4 | Sound = Sound/SoundRecording 5 | Image = Image/Image 6 | Bachelor's thesis = Thesis/Bachelors 7 | Doctoral thesis (article-based) = Thesis/Thesis 8 | Doctoral dissertation = Thesis/Thesis 9 | Series = Other/Series 10 | Pro Gradu = Thesis/Gradu 11 | Dataset = Other/ResearchData 12 | ##default = Other/Text 13 | -------------------------------------------------------------------------------- /tests/fixtures/Base/marc_formats/legacy_v3.json: -------------------------------------------------------------------------------- 1 | { 2 | "v": 3, 3 | "f": { 4 | "000": "00916ccm a22003254i 4500", 5 | "001": ["291103"], 6 | "008": ["000531q1967uuuufi ppz||||||||||||||fin||"], 7 | "245": [{ 8 | "i1": "1", 9 | "i2": "0", 10 | "s": [{ 11 | "a": "Tuhat tarinaa ;" 12 | }, { 13 | "b": "Jos muistelet mua ; Rakasta, k\u00e4rsi ja unhoita." 14 | }] 15 | }] 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /mappings/ead_level_to_format.map.sample: -------------------------------------------------------------------------------- 1 | collection = Document/ArchiveCollection 2 | series = Document/ArchiveSeries 3 | fonds = Document/ArchiveFonds 4 | item = Document/ArchiveItem 5 | digitized_collection = Document/DigitizedArchiveCollection 6 | digitized_series = Document/DigitizedArchiveSeries 7 | digitized_fonds = Document/DigitizedArchiveFonds 8 | digitized_item = Document/DigitizedArchiveItem 9 | ##default = Document/Other 10 | -------------------------------------------------------------------------------- /tests/fixtures/Base/marc_formats/marc_in_json.json: -------------------------------------------------------------------------------- 1 | { 2 | "leader": "00000ccm a22000004i 4500", 3 | "fields": [{ 4 | "001": "291103" 5 | }, { 6 | "008": "000531q1967uuuufi ppz||||||||||||||fin||" 7 | }, { 8 | "245": { 9 | "ind1": "1", 10 | "ind2": "0", 11 | "subfields": [{ 12 | "a": "Tuhat tarinaa ;" 13 | }, { 14 | "b": "Jos muistelet mua ; Rakasta, kärsi ja unhoita." 15 | }] 16 | } 17 | }] 18 | } 19 | -------------------------------------------------------------------------------- /tests/fixtures/Base/marc_formats/legacy_v2.json: -------------------------------------------------------------------------------- 1 | { 2 | "v": 2, 3 | "f": { 4 | "000": "00916ccm a22003254i 4500", 5 | "001": ["291103"], 6 | "008": ["000531q1967uuuufi ppz||||||||||||||fin||"], 7 | "245": [{ 8 | "i1": "1", 9 | "i2": "0", 10 | "s": [{ 11 | "c": "a", 12 | "v": "Tuhat tarinaa ;" 13 | }, { 14 | "c": "b", 15 | "v": "Jos muistelet mua ; Rakasta, k\u00e4rsi ja unhoita." 16 | }] 17 | }] 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tests/fixtures/Base/Enrichment/skosmos_author_results.json: -------------------------------------------------------------------------------- 1 | { 2 | "http://www.yso.fi/onto/yso/p99999": { 3 | "_id": "http://www.yso.fi/onto/yso/p99999", 4 | "data": { 5 | "prefLabel": { 6 | "en": "Enriched Author Name", 7 | "fi": "Rikastettu tekijän nimi" 8 | }, 9 | "altLabel": { 10 | "en": "Author Variant" 11 | } 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/fixtures/Base/Enrichment/skosmos_geographic_results.json: -------------------------------------------------------------------------------- 1 | { 2 | "http://www.yso.fi/onto/yso/p94426": { 3 | "_id": "http://www.yso.fi/onto/yso/p94426", 4 | "data": { 5 | "prefLabel": { 6 | "en": "Helsinki", 7 | "fi": "Helsinki", 8 | "sv": "Helsingfors" 9 | }, 10 | "latitude": "60.1699", 11 | "longitude": "24.9384" 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /conf/oai-pmh-formats.ini.sample: -------------------------------------------------------------------------------- 1 | [marc21] 2 | format = marc 3 | schema = http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd 4 | namespace = http://www.loc.gov/MARC21/slim 5 | 6 | [oai_dc] 7 | format = dc 8 | schema = http://www.openarchives.org/OAI/2.0/oai_dc.xsd 9 | namespace = http://www.openarchives.org/OAI/2.0/oai_dc/ 10 | 11 | [ese] 12 | format = ese 13 | schema = http://www.europeana.eu/schemas/ese/ESE-V3.4.xsd 14 | namespace = http://www.europeana.eu/schemas/ese/ 15 | 16 | -------------------------------------------------------------------------------- /tests/fixtures/Base/record/qdc_skosmos.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | Test QDC Document 5 | Test Subject 6 | This is a test QDC document for Skosmos enrichment testing. 7 | Text 8 | qdc-test-001 9 | 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OS Created Files 2 | 3 | .DS_Store* 4 | ehthumbs.db 5 | Icon? 6 | Thumbs.db 7 | 8 | # IDE Files 9 | .metadata/* 10 | .settings/* 11 | .project 12 | .buildpath 13 | .ExternalToolBuilders 14 | .idea 15 | .vscode 16 | 17 | # Local files 18 | conf/*.ini 19 | conf/*.lst 20 | .php_cs_cache 21 | .psalm_cache 22 | .phpstan_cache 23 | .rector 24 | *.log 25 | mappings/*.map 26 | mappings/*.php 27 | reports 28 | transformations/*.properties 29 | transformations/*.xsl 30 | vendor 31 | tests/.phpunit.cache 32 | tests/.phpunit.result.cache 33 | tests/phpcs.cache.json 34 | -------------------------------------------------------------------------------- /tests/phpstan.neon: -------------------------------------------------------------------------------- 1 | parameters: 2 | paths: 3 | - %currentWorkingDirectory%/src 4 | excludePaths: 5 | - %currentWorkingDirectory%/src/RecordManager/Base/Database/MongoDatabase.php 6 | bootstrapFiles: 7 | - %currentWorkingDirectory%/tests/bootstrap.php 8 | tmpDir: %currentWorkingDirectory%/.phpstan_cache 9 | parallel: 10 | processTimeout: 600.0 11 | level: 6 12 | ignoreErrors: 13 | - identifier: missingType.iterableValue 14 | - identifier: missingType.generics 15 | - '#PHPDoc tag @SuppressWarnings#' 16 | -------------------------------------------------------------------------------- /mappings/educational_audience.map.sample: -------------------------------------------------------------------------------- 1 | Asiantuntija tai ammattilainen = Professional 2 | Erityisopetus = Special Education 3 | Huoltaja = Parent 4 | Kansalainen = General Public 5 | Ohjaaja tai mentori = Mentor 6 | Opettaja = Teacher 7 | Opetuksen ja kasvatuksen johtaja = Administrator 8 | Oppija = Student 9 | Vertaistutor = Peer Tutor 10 | 11 | Administratör = Professional 12 | Allmänheten = General Public 13 | Elev = Student 14 | Expert = Professional 15 | Förälder = Parent 16 | Handledare = Mentor 17 | Jämbördig tutor = Peer Tutor 18 | Lärare = Teacher 19 | specialundervisning = Special Education 20 | -------------------------------------------------------------------------------- /mappings/callnumber.map.sample: -------------------------------------------------------------------------------- 1 | A = A - General Works 2 | B = B - Philosophy, Psychology, Religion 3 | C = C - Historical Sciences 4 | D = D - World History 5 | E = E - United States History 6 | F = F - General American History 7 | G = G - Geography, Anthropology, Recreation 8 | H = H - Social Science 9 | J = J - Political Science 10 | K = K - Law 11 | L = L - Education 12 | M = M - Music 13 | N = N - Fine Arts 14 | P = P - Language and Literature 15 | Q = Q - Science 16 | R = R - Medicine 17 | S = S - Agriculture 18 | T = T - Technology 19 | U = U - Military Science 20 | V = V - Naval Science 21 | Z = Z - Library Science 22 | -------------------------------------------------------------------------------- /mappings/forward_role.map.sample: -------------------------------------------------------------------------------- 1 | ; Map FORWARD (EN 15907) roles to RDA roles 2 | 3 | A00 = oth 4 | A01 = aus 5 | A02 = aus 6 | A03 = aus 7 | A05 = lyr 8 | A06 = cmp 9 | A08 = pht 10 | A09 = aut 11 | A10 = org 12 | A11 = dsr 13 | A12 = ill 14 | A13 = pht 15 | A31 = lyr 16 | A38 = org 17 | A43 = ivr 18 | A50 = aud 19 | A99 = oth 20 | B01 = flm 21 | B05 = arr 22 | B06 = trl 23 | B13 = flm 24 | B17 = org 25 | B19 = flm 26 | B24 = edt 27 | B25 = arr 28 | D01 = fmp 29 | D02 = drt 30 | D03 = cnd 31 | D99 = drt 32 | E01 = act 33 | E02 = dnc 34 | E03 = nrt 35 | E04 = cmm 36 | E05 = sng 37 | E06 = mus 38 | E08 = mus 39 | E10 = fmp 40 | F01 = cng 41 | F02 = edt 42 | F99 = rce 43 | -------------------------------------------------------------------------------- /tests/fixtures/Base/Solr/holdings_record.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | B1 4 | 5 | 6 | A1 7 | 2 8 | 9 | 10 | A1 11 | X 12 | 13 | 14 | C1 15 | 2 16 | 17 | 18 | D1 19 | 2 20 | 21 | 22 | -------------------------------------------------------------------------------- /transformations/strip_namespaces.xsl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /dbscripts/mongo.js: -------------------------------------------------------------------------------- 1 | db.record.createIndex({dedup_id: 1}, { partialFilterExpression: { dedup_id: { $exists: true } } }); 2 | db.record.createIndex({title_keys: 1}, {sparse: true}); 3 | db.record.createIndex({isbn_keys: 1}, {sparse: true}); 4 | db.record.createIndex({id_keys: 1}, {sparse: true}); 5 | db.record.createIndex({oai_id: 1}); 6 | db.record.createIndex({host_record_id: 1}); 7 | db.record.createIndex({updated: 1, deleted: 1}); 8 | db.record.createIndex({linking_id: 1}); 9 | db.record.createIndex({main_id: 1}, {sparse: true}); 10 | db.record.createIndex({source_id: 1, update_needed: 1}); 11 | db.dedup.createIndex({changed: 1}); 12 | // Only for OAI-PMH provider: db.record.createIndex({source_id: 1, updated: 1}); 13 | -------------------------------------------------------------------------------- /tests/fixtures/Base/record/marc_skosmos_3.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 01195cam a22004094i 4500 4 | skosmos_test_3 5 | 20251215000000.0 6 | 251215s2025 fi 000 0 fin d 7 | 8 | Test Author 9 | http://www.yso.fi/onto/yso/p99999 10 | 11 | 12 | Test Title for Author Enrichment 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /tests/fixtures/Base/utils/LineBasedMarcFormatter/alma.txt: -------------------------------------------------------------------------------- 1 | LDR 00936cam a22002654i 4500 2 | 001 9917651679506252 3 | 005 20211213124319.0 4 | 006 m d 5 | 007 cr#||||||||||| 6 | 008 200511s2020 fi |||||sm||||||||||fin|c 7 | 037 __ |b Oamk intra 8 | 040 __ |a FI-O |b fin |e rda 9 | 041 __ |a fin |b eng 10 | 100 1_ |a , |e kirjoittaja. 11 | 245 10 |a testitietue testaamiseen / |c . 12 | 264 _1 |a [Oulu] : |b Oulun ammattikorkeakoulu, |c kevät 2020. 13 | 300 __ |a 1 verkkoaineisto (30 sivua) 14 | 336 __ |a teksti |b txt |2 rdacontent 15 | 337 __ |a tietokonekäyttöinen |b c |2 rdamedia 16 | 338 __ |a verkkoaineisto |b cr |2 rdacarrier 17 | 538 __ |a Adobe Acrobat Reader. 18 | 567 __ |a . 19 | 650 _7 |a pystyviiva | |2 yso/fin 20 | -------------------------------------------------------------------------------- /tests/fixtures/Base/record/marc_relator.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 01168cam a22003254i 4500 4 | 1234 5 | 20200415114518.0 6 | 010727s2001 xxu|||||||||||000 ||eng|| 7 | 8 | Author 9 | aut 10 | 11 | 12 | Another 13 | https://id.loc.gov/vocabulary/relators/aut 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /transformations/ese2ese.xsl: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /tests/fixtures/Base/record/marc_authority_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 00000nz a2200000n 4500 4 | authority_001 5 | 20251215000000.0 6 | 251215n| azannaabn |a aaa 7 | 8 | Primary Author 9 | 10 | 11 | Alternative Name 1 12 | 13 | 14 | Alternative Name 2 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /tests/fixtures/Base/record/forward_skosmos.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | forward-test-001 5 | 6 | Test Archive 7 | 8 | 9 | Test Forward Document 10 | original 11 | 12 | Test Forward Document 13 | 14 | Test Subject 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /utils/update_skosmos_data.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ "$1" == "" ]; then 4 | echo "Usage: $0 " 5 | echo 6 | echo "Updates the linked data enrichment collection with data retrieved from a Skosmos server" 7 | echo 8 | echo "Example: $0 https://api.finto.fi/rest/v1/yso/data" 9 | echo 10 | exit 11 | fi 12 | 13 | set -e 14 | 15 | DIR=$(dirname "$0") 16 | URL=$1 17 | DATABASE=$2 18 | COLLECTION=$3 19 | QFILE=$4 20 | for TMPDIR in "$TMPDIR" "$TMP" /var/tmp /tmp 21 | do 22 | test -d "$TMPDIR" && break 23 | done 24 | 25 | curl -s -S -f -L -X GET -H 'Accept: text/turtle' ${URL} > ${TMPDIR}/ld_fetch_result.ttl 26 | 27 | ${DIR}/../console -q util:import-rdf ${TMPDIR}/ld_fetch_result.ttl 28 | rm ${TMPDIR}/ld_fetch_result.ttl 29 | -------------------------------------------------------------------------------- /tests/fixtures/Base/record/marc_authority_skosmos.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 00000nz a2200000n 4500 4 | authority_skosmos_test 5 | 20251215000000.0 6 | 251215n| azannaabn |a aaa 7 | 8 | Test Authority Name 9 | 10 | 11 | Test Occupation 12 | http://www.yso.fi/onto/yso/p11111 13 | yso 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /tests/fixtures/Base/record/marc_music_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 01195cjm a22004094i 4500 4 | 123 5 | FI-MELINDA 6 | 20160322194428.0 7 | 8 | 044006722320 9 | 10 | 140327s2013 fi 000 0 fin d 11 | 12 | Test string 13 | 961827 14 | Test parent string 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /tests/fixtures/Base/record/marc_music_4.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 01195cjm a22004094i 4500 4 | 123 5 | FI-MELINDA 6 | 20160322194428.0 7 | 8 | 4029759178200 9 | 10 | 140327s2013 fi 000 0 fin d 11 | 12 | Test string 13 | 961827 14 | Test parent string 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /tests/fixtures/Base/record/marc_auth_no_ids.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 00000nam a2200000 i 4500 4 | marc_auth_test_no_ids 5 | 20251215000000.0 6 | 251215s2025 fi 000 0 eng d 7 | 8 | Author Without ID 9 | 10 | 11 | Test Book Without Authority IDs 12 | 13 | 14 | Second Author Without ID 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /transformations/lido_normalization.xsl: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | Image 15 | PhysicalObject 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /tests/fixtures/Base/record/ead3_skosmos.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ead3-test-001 5 | 6 | 7 | Test EAD3 Document with Skosmos Subject 8 | ead3-test-001 9 | 10 | 11 | Test Repository 12 | 13 | 14 | 15 | 16 | 17 | Test Subject 18 | 19 | 20 | 21 | This is a test EAD3 document for Skosmos enrichment testing. 22 | 23 | 24 | -------------------------------------------------------------------------------- /tests/fixtures/Base/record/marc_music_5.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 01195cjm a22004094i 4500 4 | 123 5 | FI-MELINDA 6 | 20160322194428.0 7 | 8 | cba9c83f-4017-42eb-89ce-6110fd0dc10c 9 | musicb 10 | 11 | 140327s2013 fi 000 0 fin d 12 | 13 | Test string 14 | 961827 15 | Test parent string 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /tests/phpmd.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | PHPMD rules for RecordManager 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /tests/fixtures/Base/record/marc_auth_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 00000nam a2200000 i 4500 4 | marc_auth_test_1 5 | 20251215000000.0 6 | 251215s2025 fi 000 0 eng d 7 | 8 | Primary Author 9 | (FIN11)authority_001 10 | 11 | 12 | Test Book Title 13 | 14 | 15 | Secondary Author 16 | (FIN11)authority_001 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /tests/fixtures/Base/record/marc_skosmos_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 01195cam a22004094i 4500 4 | skosmos_test_1 5 | 20251215000000.0 6 | 251215s2025 fi 000 0 fin d 7 | 8 | Test Author. 9 | 10 | 11 | Test Title for Skosmos Enrichment 12 | 13 | 14 | Test Topic 15 | http://www.yso.fi/onto/yso/p12345 16 | yso 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /tests/fixtures/Base/record/marc_skosmos_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 01195cam a22004094i 4500 4 | skosmos_test_2 5 | 20251215000000.0 6 | 251215s2025 fi 000 0 fin d 7 | 8 | Test Author. 9 | 10 | 11 | Test Title for Geographic Enrichment 12 | 13 | 14 | Test Geographic Place 15 | http://www.yso.fi/onto/yso/p94426 16 | yso 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /tests/fixtures/Base/record/marc_skosmos_multilang.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 01195cam a22004094i 4500 4 | skosmos_test_multilang 5 | 20251215000000.0 6 | 251215s2025 fi 000 0 fin d 7 | 8 | Test Author. 9 | 10 | 11 | Test Title for Multilingual 12 | 13 | 14 | Multilang Topic 15 | http://www.yso.fi/onto/yso/p33333 16 | yso 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /tests/fixtures/Base/record/marc_skosmos_exactmatch.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 01195cam a22004094i 4500 4 | skosmos_test_exactmatch 5 | 20251215000000.0 6 | 251215s2025 fi 000 0 fin d 7 | 8 | Test Author. 9 | 10 | 11 | Test Title for Exact Match 12 | 13 | 14 | Exact Match Topic 15 | http://www.yso.fi/onto/yso/p22222 16 | yso 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /tests/fixtures/Base/record/marc_skosmos_invalid_uri.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 01195cam a22004094i 4500 4 | skosmos_test_invalid 5 | 20251215000000.0 6 | 251215s2025 fi 000 0 fin d 7 | 8 | Test Author. 9 | 10 | 11 | Test Title with Invalid URI 12 | 13 | 14 | Test Topic 15 | http://invalid.uri.example.com/p12345 16 | other 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /tests/fixtures/Base/record/dc1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Title : Sub 4 | Author, Primary 5 | Topic 6 | Testing 7 | RecordManager 8 | Long description 9 | https://localhost 10 | Publisher 11 | Author, Secondary 12 | 2025 13 | Text 14 | 345 pages 15 | 12345 16 | http://localhost/12345 17 | RecordManager 18 | eng 19 | http://localhost 20 | Finland 21 | http://localhost/cc0 22 | 1234 23 | 24 | -------------------------------------------------------------------------------- /tests/fixtures/Base/record/marc_skosmos_excluded_location.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 01195cam a22004094i 4500 4 | skosmos_test_excluded 5 | 20251215000000.0 6 | 251215s2025 fi 000 0 fin d 7 | 8 | Test Author. 9 | 10 | 11 | Test Title for Excluded Location 12 | 13 | 14 | Excluded Location 15 | http://www.yso.fi/onto/yso/p44444 16 | yso 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /transformations/sfx.xsl: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | cr 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /tests/fixtures/Base/Enrichment/skosmos_authority_results.json: -------------------------------------------------------------------------------- 1 | { 2 | "http://www.yso.fi/onto/yso/p11111": { 3 | "_id": "http://www.yso.fi/onto/yso/p11111", 4 | "data": { 5 | "@context": { 6 | "skos": "http://www.w3.org/2004/02/skos/core#", 7 | "uri": "@id", 8 | "type": "@type", 9 | "lang": "@language", 10 | "value": "@value", 11 | "graph": "@graph", 12 | "prefLabel": "skos:prefLabel" 13 | }, 14 | "graph": [ 15 | { 16 | "uri": "http://www.yso.fi/onto/yso/p11111", 17 | "type": "skos:Concept", 18 | "prefLabel": [ 19 | {"lang": "en", "value": "Test Occupation"} 20 | ] 21 | } 22 | ] 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /tests/fixtures/Base/Enrichment/skosmos_exactmatch_results.json: -------------------------------------------------------------------------------- 1 | { 2 | "http://www.yso.fi/onto/yso/p22222": { 3 | "_id": "http://www.yso.fi/onto/yso/p22222", 4 | "data": { 5 | "@context": { 6 | "skos": "http://www.w3.org/2004/02/skos/core#", 7 | "uri": "@id", 8 | "type": "@type", 9 | "lang": "@language", 10 | "value": "@value", 11 | "graph": "@graph", 12 | "prefLabel": "skos:prefLabel" 13 | }, 14 | "graph": [ 15 | { 16 | "uri": "http://www.yso.fi/onto/yso/p22222", 17 | "type": "skos:Concept", 18 | "prefLabel": [ 19 | {"lang": "en", "value": "Exact Match Enhanced Topic"} 20 | ] 21 | } 22 | ] 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /tests/fixtures/Base/record/marc_auth_missing_authority.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 00000nam a2200000 i 4500 4 | marc_auth_test_missing 5 | 20251215000000.0 6 | 251215s2025 fi 000 0 eng d 7 | 8 | Author With Missing Authority 9 | (FIN11)nonexistent_authority 10 | 11 | 12 | Test Book With Missing Authority 13 | 14 | 15 | Secondary Author With Missing Authority 16 | (FIN11)another_missing 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /psalm.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /transformations/sfx.properties: -------------------------------------------------------------------------------- 1 | ; XSLT normalization settings for SFX KB records 2 | [General] 3 | ; REQUIRED: Name of XSLT file to apply. Path is relative to the transformations directory 4 | ; of the RecordManager installation. 5 | xslt = sfx.xsl 6 | ; OPTIONAL: PHP function(s) to register for use within XSLT file. You may repeat 7 | ; this line to register multiple PHP functions. 8 | ;php_function[] = str_replace 9 | ;php_function[] = ucfirst 10 | ; OPTIONAL: PHP class filled with public static functions for use by the XSLT file. 11 | ; The class name must match the filename, and the file must exist in the transformations 12 | ; directory of the RecordManager installation. You may repeat this line to load multiple 13 | ; custom classes. 14 | ;custom_class[] = 15 | ;custom_class[] = 16 | 17 | ; XSLT parameters -- any key/value pairs set here will be passed as parameters to 18 | ; the XSLT file, allowing local values to be set without modifying XSLT code. 19 | [Parameters] 20 | -------------------------------------------------------------------------------- /transformations/elka.properties: -------------------------------------------------------------------------------- 1 | ; XSLT Import Settings for ELKA Dublin Core format 2 | [General] 3 | ; REQUIRED: Name of XSLT file to apply. Path is relative to the transformations directory 4 | ; of the RecordManager installation. 5 | xslt = elka.xsl 6 | ; OPTIONAL: PHP function(s) to register for use within XSLT file. You may repeat 7 | ; this line to register multiple PHP functions. 8 | ;php_function[] = str_replace 9 | ;php_function[] = ucfirst 10 | ; OPTIONAL: PHP class filled with public static functions for use by the XSLT file. 11 | ; The class name must match the filename, and the file must exist in the transformations 12 | ; directory of the RecordManager installation. You may repeat this line to load multiple 13 | ; custom classes. 14 | ;custom_class[] = 15 | ;custom_class[] = 16 | 17 | ; XSLT parameters -- any key/value pairs set here will be passed as parameters to 18 | ; the XSLT file, allowing local values to be set without modifying XSLT code. 19 | [Parameters] 20 | -------------------------------------------------------------------------------- /transformations/helmet.properties: -------------------------------------------------------------------------------- 1 | ; XSLT Import Settings for HelMet Dublin Core format 2 | [General] 3 | ; REQUIRED: Name of XSLT file to apply. Path is relative to the transformations directory 4 | ; of the RecordManager installation. 5 | xslt = helmet.xsl 6 | ; OPTIONAL: PHP function(s) to register for use within XSLT file. You may repeat 7 | ; this line to register multiple PHP functions. 8 | ;php_function[] = str_replace 9 | ;php_function[] = ucfirst 10 | ; OPTIONAL: PHP class filled with public static functions for use by the XSLT file. 11 | ; The class name must match the filename, and the file must exist in the transformations 12 | ; directory of the RecordManager installation. You may repeat this line to load multiple 13 | ; custom classes. 14 | ;custom_class[] = 15 | ;custom_class[] = 16 | 17 | ; XSLT parameters -- any key/value pairs set here will be passed as parameters to 18 | ; the XSLT file, allowing local values to be set without modifying XSLT code. 19 | [Parameters] 20 | -------------------------------------------------------------------------------- /transformations/metalib_ird.properties: -------------------------------------------------------------------------------- 1 | ; XSLT normalization settings for MetaLib IRDs 2 | [General] 3 | ; REQUIRED: Name of XSLT file to apply. Path is relative to the transformations directory 4 | ; of the RecordManager installation. 5 | xslt = metalib_ird.xsl 6 | ; OPTIONAL: PHP function(s) to register for use within XSLT file. You may repeat 7 | ; this line to register multiple PHP functions. 8 | ;php_function[] = str_replace 9 | ;php_function[] = ucfirst 10 | ; OPTIONAL: PHP class filled with public static functions for use by the XSLT file. 11 | ; The class name must match the filename, and the file must exist in the transformations 12 | ; directory of the RecordManager installation. You may repeat this line to load multiple 13 | ; custom classes. 14 | ;custom_class[] = 15 | ;custom_class[] = 16 | 17 | ; XSLT parameters -- any key/value pairs set here will be passed as parameters to 18 | ; the XSLT file, allowing local values to be set without modifying XSLT code. 19 | [Parameters] 20 | -------------------------------------------------------------------------------- /transformations/lido_normalization.properties: -------------------------------------------------------------------------------- 1 | ; XSLT Import Settings for LIDO format 2 | [General] 3 | ; REQUIRED: Name of XSLT file to apply. Path is relative to the transformations directory 4 | ; of the RecordManager installation. 5 | xslt = lido_normalization.xsl 6 | ; OPTIONAL: PHP function(s) to register for use within XSLT file. You may repeat 7 | ; this line to register multiple PHP functions. 8 | ;php_function[] = str_replace 9 | ;php_function[] = ucfirst 10 | ; OPTIONAL: PHP class filled with public static functions for use by the XSLT file. 11 | ; The class name must match the filename, and the file must exist in the transformations 12 | ; directory of the RecordManager installation. You may repeat this line to load multiple 13 | ; custom classes. 14 | ;custom_class[] = 15 | ;custom_class[] = 16 | 17 | ; XSLT parameters -- any key/value pairs set here will be passed as parameters to 18 | ; the XSLT file, allowing local values to be set without modifying XSLT code. 19 | [Parameters] 20 | -------------------------------------------------------------------------------- /transformations/marc2oai_dc.properties: -------------------------------------------------------------------------------- 1 | ; XSLT Export Settings for Dublin Core format 2 | [General] 3 | ; REQUIRED: Name of XSLT file to apply. Path is relative to the transformations directory 4 | ; of the RecordManager installation. 5 | xslt = MARC21slim2OAIDC.xsl 6 | ; OPTIONAL: PHP function(s) to register for use within XSLT file. You may repeat 7 | ; this line to register multiple PHP functions. 8 | ;php_function[] = str_replace 9 | ;php_function[] = ucfirst 10 | ; OPTIONAL: PHP class filled with public static functions for use by the XSLT file. 11 | ; The class name must match the filename, and the file must exist in the transformations 12 | ; directory of the RecordManager installation. You may repeat this line to load multiple 13 | ; custom classes. 14 | ;custom_class[] = 15 | ;custom_class[] = 16 | 17 | ; XSLT parameters -- any key/value pairs set here will be passed as parameters to 18 | ; the XSLT file, allowing local values to be set without modifying XSLT code. 19 | [Parameters] 20 | -------------------------------------------------------------------------------- /transformations/koha.properties.sample: -------------------------------------------------------------------------------- 1 | ; XSLT normalization settings for Koha records containing item information 2 | [General] 3 | ; REQUIRED: Name of XSLT file to apply. Path is relative to the transformations directory 4 | ; of the RecordManager installation. 5 | xslt = koha.xsl 6 | ; OPTIONAL: PHP function(s) to register for use within XSLT file. You may repeat 7 | ; this line to register multiple PHP functions. 8 | ;php_function[] = str_replace 9 | ;php_function[] = ucfirst 10 | ; OPTIONAL: PHP class filled with public static functions for use by the XSLT file. 11 | ; The class name must match the filename, and the file must exist in the transformations 12 | ; directory of the RecordManager installation. You may repeat this line to load multiple 13 | ; custom classes. 14 | ;custom_class[] = 15 | ;custom_class[] = 16 | 17 | ; XSLT parameters -- any key/value pairs set here will be passed as parameters to 18 | ; the XSLT file, allowing local values to be set without modifying XSLT code. 19 | [Parameters] 20 | -------------------------------------------------------------------------------- /conf/application.config.php: -------------------------------------------------------------------------------- 1 | array_unique($modules), 15 | 'module_listener_options' => [ 16 | 'config_glob_paths' => [ 17 | 'config/autoload/{,*.}{global,local}.php', 18 | ], 19 | 'config_cache_enabled' => false, 20 | 'module_map_cache_enabled' => false, 21 | 'check_dependencies' => getenv('APPLICATION_ENV') == 'development', 22 | 'module_paths' => [ 23 | './src/RecordManager', 24 | './vendor', 25 | ], 26 | ], 27 | 'service_manager' => [ 28 | 'use_defaults' => true, 29 | 'factories' => [], 30 | ], 31 | ]; 32 | -------------------------------------------------------------------------------- /transformations/ese2ese_fng.properties: -------------------------------------------------------------------------------- 1 | ; XSLT Export Settings for ESE format 2 | [General] 3 | ; REQUIRED: Name of XSLT file to apply. Path is relative to the transformations directory 4 | ; of the RecordManager installation. 5 | xslt = ese2ese.xsl 6 | ; OPTIONAL: PHP function(s) to register for use within XSLT file. You may repeat 7 | ; this line to register multiple PHP functions. 8 | ;php_function[] = str_replace 9 | ;php_function[] = ucfirst 10 | ; OPTIONAL: PHP class filled with public static functions for use by the XSLT file. 11 | ; The class name must match the filename, and the file must exist in the transformations 12 | ; directory of the RecordManager installation. You may repeat this line to load multiple 13 | ; custom classes. 14 | ;custom_class[] = 15 | ;custom_class[] = 16 | 17 | ; XSLT parameters -- any key/value pairs set here will be passed as parameters to 18 | ; the XSLT file, allowing local values to be set without modifying XSLT code. 19 | [Parameters] 20 | provider = "National Library of Finland" 21 | -------------------------------------------------------------------------------- /tests/fixtures/Base/record/lido3.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 12345 5 | 6 | 7 | 8 | 9 | Maalaus 10 | 11 | 12 | 13 | 14 | 15 | 16 | Maalaus 17 | 18 | 19 | 20 | 21 | Maisema 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /tests/phpcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Coding standards for RecordManager. 4 | ../src 5 | ../tests 6 | src/RecordManager/[^/]+/config/* 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /utils/delete_ids.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # A simple utility script that deletes records from Solr using an ID list file 4 | # containing one record ID per line. 5 | # Doesn't escape the IDs, so make sure the input file is clean. 6 | 7 | if [ -z "$2" ]; then 8 | # Usage 9 | echo 'Usage: delete_ids.sh ' 10 | exit 1; 11 | fi 12 | 13 | SOLR_URL=$1 14 | IDFILE=$2 15 | 16 | IDLIST="" 17 | IDCOUNT=0 18 | LISTCOUNT=0 19 | 20 | while read -r line; do 21 | IDCOUNT=$[$IDCOUNT+1] 22 | LISTCOUNT=$[$LISTCOUNT+1] 23 | IDLIST="${IDLIST}$line" 24 | if [ ${LISTCOUNT} -ge 1000 ]; then 25 | curl -X POST ${SOLR_URL} -H "Content-Type: text/xml" --data-binary "${IDLIST}" 26 | IDLIST="" 27 | LISTCOUNT=0 28 | echo "${IDCOUNT} IDs deleted" 29 | fi 30 | done < "${IDFILE}" 31 | 32 | if [ ${#IDLIST} -gt 0 ]; then 33 | curl -X POST ${SOLR_URL} -H "Content-Type: text/xml" --data-binary "${IDLIST}" 34 | IDLIST="" 35 | echo "${IDCOUNT} IDs deleted" 36 | fi 37 | 38 | echo "All done." 39 | -------------------------------------------------------------------------------- /transformations/elka.xsl: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | MotionPicture 17 | Unknown 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /tests/fixtures/Base/Enrichment/skosmos_excluded_location_results.json: -------------------------------------------------------------------------------- 1 | { 2 | "http://www.yso.fi/onto/yso/p44444": { 3 | "_id": "http://www.yso.fi/onto/yso/p44444", 4 | "data": { 5 | "@context": { 6 | "skos": "http://www.w3.org/2004/02/skos/core#", 7 | "wgs84": "http://www.w3.org/2003/01/geo/wgs84_pos#", 8 | "uri": "@id", 9 | "type": "@type", 10 | "lang": "@language", 11 | "value": "@value", 12 | "graph": "@graph", 13 | "prefLabel": "skos:prefLabel" 14 | }, 15 | "graph": [ 16 | { 17 | "uri": "http://www.yso.fi/onto/yso/p44444", 18 | "type": "skos:Concept", 19 | "prefLabel": [ 20 | {"lang": "en", "value": "Excluded Location"} 21 | ], 22 | "wgs84:lat": "61.4978", 23 | "wgs84:long": "23.7610" 24 | } 25 | ] 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /tests/fixtures/Base/record/lido2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 12345 5 | 6 | 7 | 8 | 9 | Kirja 10 | 11 | 12 | 13 | 14 | 15 | 16 | Kitchen tool 17 | Scissors 18 | 19 | 20 | Sakset 21 | Keittiövälineet 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /tests/fixtures/Base/Enrichment/skosmos_multilang_results.json: -------------------------------------------------------------------------------- 1 | { 2 | "http://www.yso.fi/onto/yso/p33333": { 3 | "_id": "http://www.yso.fi/onto/yso/p33333", 4 | "data": { 5 | "@context": { 6 | "skos": "http://www.w3.org/2004/02/skos/core#", 7 | "uri": "@id", 8 | "type": "@type", 9 | "lang": "@language", 10 | "value": "@value", 11 | "graph": "@graph", 12 | "prefLabel": "skos:prefLabel" 13 | }, 14 | "graph": [ 15 | { 16 | "uri": "http://www.yso.fi/onto/yso/p33333", 17 | "type": "skos:Concept", 18 | "prefLabel": [ 19 | {"lang": "en", "value": "Multilingual Topic English"}, 20 | {"lang": "fi", "value": "Monikielinen aihe suomeksi"}, 21 | {"lang": "sv", "value": "Flerspråkigt ämne på svenska"}, 22 | {"lang": "de", "value": "Mehrsprachiges Thema auf Deutsch"} 23 | ] 24 | } 25 | ] 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /tests/psalm-defines.php: -------------------------------------------------------------------------------- 1 | 26 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 27 | * @link https://vufind.org/wiki/development:testing:unit_tests Wiki 28 | */ 29 | 30 | define('RECMAN_BASE_PATH', realpath(__DIR__ . '/..')); 31 | -------------------------------------------------------------------------------- /tests/fixtures/Base/record/marc_music_6.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 01195cjm a22004094i 4500 4 | 123 5 | FI-MELINDA 6 | 20160322194428.0 7 | 8 | A1288986 9 | 10 | 11 | TEMPSCD02 12 | 13 | 14 | tempscd 02 15 | temps 16 | 17 | 18 | ANI / 19 | Sirkka Hirsjärvi, Pirkko Remes, Paula Sajavaara. 20 | 21 | 140327s2013 fi 000 0 fin d 22 | 23 | Test string 24 | 961827 25 | Test parent string 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /transformations/marc2ese_raita.properties: -------------------------------------------------------------------------------- 1 | ; XSLT Export Settings for ESE format 2 | [General] 3 | ; REQUIRED: Name of XSLT file to apply. Path is relative to the transformations directory 4 | ; of the RecordManager installation. 5 | xslt = marc2ese.xsl 6 | ; OPTIONAL: PHP function(s) to register for use within XSLT file. You may repeat 7 | ; this line to register multiple PHP functions. 8 | ;php_function[] = str_replace 9 | ;php_function[] = ucfirst 10 | ; OPTIONAL: PHP class filled with public static functions for use by the XSLT file. 11 | ; The class name must match the filename, and the file must exist in the transformations 12 | ; directory of the RecordManager installation. You may repeat this line to load multiple 13 | ; custom classes. 14 | ;custom_class[] = 15 | ;custom_class[] = 16 | 17 | ; XSLT parameters -- any key/value pairs set here will be passed as parameters to 18 | ; the XSLT file, allowing local values to be set without modifying XSLT code. 19 | [Parameters] 20 | source = "National Library of Finland, Raita collection" 21 | record_address = "https://viola.linneanet.fi/vwebv/holdingsInfo?bibId=[001]" 22 | id_prefix = "FI-Viola:" 23 | provider = "National Library of Finland" 24 | data_provider = "National Library of Finland" -------------------------------------------------------------------------------- /tests/bootstrap.php: -------------------------------------------------------------------------------- 1 | 26 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 27 | * @link https://vufind.org/wiki/development:testing:unit_tests Wiki 28 | */ 29 | 30 | define('RECMAN_BASE_PATH', __DIR__ . '/fixtures/Base/config/basic'); 31 | -------------------------------------------------------------------------------- /tests/psalm-autoload.php: -------------------------------------------------------------------------------- 1 | 26 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 27 | * @link https://vufind.org/wiki/development:testing:unit_tests Wiki 28 | */ 29 | 30 | require 'psalm-defines.php'; 31 | require RECMAN_BASE_PATH . '/vendor/autoload.php'; 32 | -------------------------------------------------------------------------------- /tests/fixtures/Base/Controller/CreatePreview/preview_marc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 01195cam a22004094i 4500 4 | 123 5 | 20160322194428.0 6 | 140327s2013 fi 000 0 fin d 7 | 8 | 978-951-31-4836-2 9 | 10 | 11 | Hirsjärvi, Sirkka. 12 | (TEST)1 13 | 14 | 15 | Tutki ja kirjoita / 16 | Sirkka Hirsjärvi, Pirkko Remes, Paula Sajavaara. 17 | 18 | 19 | 2013 20 | 21 | 22 | E 23 | 150 24 | 38 Hir 25 | 18. p. 2013 26 | Test 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /mappings/educational_material_type.map.sample: -------------------------------------------------------------------------------- 1 | audio = audio 2 | blogi = weblog 3 | datasetti = dataset 4 | esitys = presentation 5 | harjoitus = exercise 6 | kaavio = diagram 7 | kartta = map 8 | kokeellinen työskentely = activity 9 | kuva = picture 10 | luentotallenne = lecture 11 | opas = guide 12 | peli = game 13 | projekti = project 14 | sanasto = glossary 15 | simulaatio = simulation 16 | sovellus = application 17 | teksti = text 18 | työkalu = tool 19 | video = video 20 | wiki = wiki 21 | 22 | aktivitet = activity 23 | applikation = application 24 | bild = picture 25 | dataset = dataset 26 | diagram = diagram 27 | föreläsning = lecture 28 | guide = guide 29 | karta = map 30 | ljud = audio 31 | ordlista = glossary 32 | övning = exercise 33 | presentation = presentation 34 | projekt = project 35 | simulering = simulation 36 | spel = game 37 | text = text 38 | verktyg = tool 39 | video = video 40 | web blogg = weblog 41 | wiki = wiki 42 | 43 | activity = activity 44 | application = application 45 | audio = audio 46 | dataset = dataset 47 | diagram = diagram 48 | exercise = exercise 49 | game = game 50 | glossary = glossary 51 | guide = guide 52 | lecture = lecture 53 | map = map 54 | picture = picture 55 | presentation = presentation 56 | project = project 57 | simulation = simulation 58 | text = text 59 | tool = tool 60 | video = video 61 | weblog = weblog 62 | wiki = wiki 63 | -------------------------------------------------------------------------------- /datasources.php: -------------------------------------------------------------------------------- 1 | 25 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 26 | * @link https://github.com/NatLibFi/RecordManager 27 | */ 28 | require_once __DIR__ . '/cmdline.php'; 29 | 30 | convertOptions( 31 | [ 32 | 'search' => [ 33 | 'command' => 'sources:search', 34 | 'arg' => 1 35 | ] 36 | ] 37 | ); 38 | 39 | include __DIR__ . '/console'; 40 | -------------------------------------------------------------------------------- /logs.php: -------------------------------------------------------------------------------- 1 | 25 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 26 | * @link https://github.com/NatLibFi/RecordManager 27 | */ 28 | require_once __DIR__ . '/cmdline.php'; 29 | 30 | convertOptions( 31 | [ 32 | 'func' => [], 33 | 'email' => [ 34 | 'command' => 'logs:send', 35 | 'arg' => 1, 36 | ] 37 | ], 38 | ); 39 | 40 | include __DIR__ . '/console'; 41 | -------------------------------------------------------------------------------- /mappings/lido_type_to_format_hierarchy.map.sample: -------------------------------------------------------------------------------- 1 | arkeologinen kohde = Other/ArchaeologicalSite 2 | arkisto = Document/Archive 3 | arkistoaineisto = Document/ArchiveMaterial 4 | Arkistoaineisto = Document/ArchiveMaterial 5 | auktorisoitu dokumentti = Document/Authorized 6 | esine = PhysicalObject/Other 7 | Esine = PhysicalObject/Other 8 | esineteos = WorkOfArt/Physical 9 | fotomekaaniset menetelmät = Image/PhotoMechanic 10 | grafiikka = WorkOfArt/Graphic 11 | installaatio = WorkOfArt/Installation 12 | kartta = Map/Map 13 | kirja = Book/Book 14 | kulttuurihistoriallinen esine = PhysicalObject/CultureHistoricalObject 15 | kuva = Image/Image 16 | Kuva = Image/Image 17 | käsikirjoitus = Other/Manuscript 18 | liikkuva kuva = Video/MotionPicture 19 | maalaus = WorkOfArt/Painting 20 | mediataide = WorkOfArt/MediaArt 21 | mosaiikki = WorkOfArt/Mosaic 22 | nuotti = MusicalScore 23 | painettu tekstijulkaisu = Other/Print 24 | painotuote = Other/Print 25 | piirustus = WorkOfArt/Drawing 26 | Piirustus = WorkOfArt/Drawing 27 | rakennetun ympäristön kohde = Other/Building 28 | rakennus = Other/Building 29 | taideteollisuus = WorkOfArt/ArtIndustry 30 | taideteollisuusesine = PhysicalObject/ArtIndustry 31 | taiteilijan työvälineet = PhysicalObject/ArtistsTool 32 | tekstiiliteos = WorkOfArt/Textile 33 | työkalut = PhysicalObject/Tool 34 | veistos = WorkOfArt/Sculpture 35 | valokuva = Image/Photo 36 | ympäristötaide = WorkOfArt/Environment 37 | ympäristöteos = WorkOfArt/Environment 38 | -------------------------------------------------------------------------------- /import.php: -------------------------------------------------------------------------------- 1 | 25 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 26 | * @link https://github.com/NatLibFi/RecordManager 27 | */ 28 | require_once __DIR__ . '/cmdline.php'; 29 | 30 | convertOptions( 31 | [ 32 | 'file' => [ 33 | 'command' => 'records:import', 34 | 'arg' => 2, 35 | ], 36 | 'source' => [ 37 | 'arg' => 1 38 | ] 39 | ], 40 | ); 41 | 42 | include __DIR__ . '/console'; 43 | -------------------------------------------------------------------------------- /oai-pmh.php: -------------------------------------------------------------------------------- 1 | 25 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 26 | * @link https://github.com/NatLibFi/RecordManager 27 | */ 28 | 29 | /** 30 | * OAI-PMH Provider Front-End 31 | */ 32 | require_once __DIR__ . '/vendor/autoload.php'; 33 | 34 | define('RECMAN_BASE_PATH', getenv('RECMAN_BASE_PATH') ?: __DIR__); 35 | $app = Laminas\Mvc\Application::init( 36 | include RECMAN_BASE_PATH . '/conf/application.config.php' 37 | ); 38 | $sm = $app->getServiceManager(); 39 | $provider = $sm->get(\RecordManager\Base\Controller\OaiPmhProvider::class); 40 | $provider->launch(); 41 | -------------------------------------------------------------------------------- /tests/fixtures/Base/record/lido_skosmos.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | lido-test-001 5 | 6 | 7 | 8 | 9 | Test LIDO Document with Skosmos Subject 10 | 11 | 12 | 13 | 14 | 15 | 16 | Test Museum 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | http://www.yso.fi/onto/yso/p12345 28 | Test Subject 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | lido-test-001 38 | 39 | Archive 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /harvest.php: -------------------------------------------------------------------------------- 1 | 25 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 26 | * @link https://github.com/NatLibFi/RecordManager 27 | */ 28 | require_once __DIR__ . '/cmdline.php'; 29 | 30 | convertOptions( 31 | [ 32 | 'source' => [ 33 | 'command' => 'records:harvest', 34 | 'opt' => 'source', 35 | ], 36 | 'override' => [ 37 | 'opt' => 'start-position' 38 | ], 39 | 'lockfile' => [ 40 | 'opt' => 'lock' 41 | ], 42 | ], 43 | ); 44 | 45 | include __DIR__ . '/console'; 46 | -------------------------------------------------------------------------------- /src/RecordManager/Base/Exception/HttpRequestException.php: -------------------------------------------------------------------------------- 1 | 26 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 27 | * @link https://github.com/NatLibFi/RecordManager 28 | */ 29 | 30 | namespace RecordManager\Base\Exception; 31 | 32 | /** 33 | * HTTP Request Exception Class 34 | * 35 | * @category DataManagement 36 | * @package RecordManager 37 | * @author Ere Maijala 38 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 39 | * @link https://github.com/NatLibFi/RecordManager 40 | */ 41 | class HttpRequestException extends RequestException 42 | { 43 | } 44 | -------------------------------------------------------------------------------- /tests/fixtures/Base/record/marc_empty_field.json: -------------------------------------------------------------------------------- 1 | { 2 | "v": 3, 3 | "f": { 4 | "000": " as a a ", 5 | "001": ["1020470"], 6 | "008": [" s2015 fi |||p|r|||||||||||swe|| "], 7 | "245": [{ 8 | "i1": "0", 9 | "i2": "0", 10 | "s": [{ 11 | "a": "Femina." 12 | }, { 13 | "n": "2015" 14 | }] 15 | }], 16 | "260": [{ 17 | "i1": " ", 18 | "i2": " ", 19 | "s": [{ 20 | "a": "Stockholm :" 21 | }, { 22 | "b": "Allers F\u00f6rlag Ab," 23 | }, { 24 | "c": "2015" 25 | }] 26 | }], 27 | "760": [{ 28 | "i1": "0", 29 | "i2": " ", 30 | "s": [{ 31 | "w": "1020467" 32 | }] 33 | }], 34 | "762": [{ 35 | "i1": "0", 36 | "i2": " ", 37 | "s": [{ 38 | "w": "1020471" 39 | }] 40 | }, { 41 | "i1": "0", 42 | "i2": " ", 43 | "s": [{ 44 | "w": "1020472" 45 | }] 46 | }, { 47 | "i1": "0", 48 | "i2": " ", 49 | "s": [{ 50 | "w": "1020473" 51 | }] 52 | }, { 53 | "i1": "0", 54 | "i2": " " 55 | }, { 56 | "i1": "0", 57 | "i2": " ", 58 | "s": [{ 59 | "w": "1028245" 60 | }] 61 | }] 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/RecordManager/Base/Database/AbstractAuthorityDatabase.php: -------------------------------------------------------------------------------- 1 | 26 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 27 | * @link https://github.com/NatLibFi/RecordManager 28 | */ 29 | 30 | namespace RecordManager\Base\Database; 31 | 32 | /** 33 | * Abstract database access class 34 | * 35 | * @category DataManagement 36 | * @package RecordManager 37 | * @author Ere Maijala 38 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 39 | * @link https://github.com/NatLibFi/RecordManager 40 | */ 41 | abstract class AbstractAuthorityDatabase extends AbstractDatabase 42 | { 43 | } 44 | -------------------------------------------------------------------------------- /tests/fixtures/Base/Enrichment/music_brainz_results.json: -------------------------------------------------------------------------------- 1 | { 2 | "barcode:\"044006722320\"": { 3 | "_id": "barcode:\"044006722320\"", 4 | "data": { 5 | "releases": [ 6 | { 7 | "id": "5a323542-6431-48c2-89ed-f0cef6f17b85" 8 | }, 9 | { 10 | "id": "b3eb127e-75ec-4167-93aa-7c1cfcfa52d6" 11 | }, 12 | { 13 | "id": "cba9c83f-4017-42eb-89ce-6110fd0dc10c" 14 | }, 15 | { 16 | "id": "093baef2-31e5-408b-979e-e90ba8f2394f" 17 | } 18 | ] 19 | } 20 | }, 21 | "barcode:\"4029759178200\"": { 22 | "_id": "barcode:\"4029759178200\"", 23 | "data": { 24 | "releases": [ 25 | { 26 | "id": "b2022feb-88fe-4e4a-94cc-1f0eae644b9b" 27 | } 28 | ] 29 | } 30 | }, 31 | "reid:\"cba9c83f-4017-42eb-89ce-6110fd0dc10c\"": { 32 | "_id": "reid:\"cba9c83f-4017-42eb-89ce-6110fd0dc10c\"", 33 | "data": { 34 | "releases": [ 35 | { 36 | "id": "cba9c83f-4017-42eb-89ce-6110fd0dc10c" 37 | } 38 | ] 39 | } 40 | }, 41 | "catno:\"TEMPSCD02\" AND releaseaccent:\"ANI\"": { 42 | "_id": "catno:\"TEMPSCD02\" AND releaseaccent:\"ANI\"", 43 | "data": { 44 | "releases": [ 45 | { 46 | "id": "065e298f-a73f-4399-89b9-e2bb36606931" 47 | } 48 | ] 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/RecordManager/Base/Harvest/PluginManager.php: -------------------------------------------------------------------------------- 1 | 26 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 27 | * @link https://github.com/NatLibFi/RecordManager 28 | */ 29 | 30 | namespace RecordManager\Base\Harvest; 31 | 32 | /** 33 | * Harvest plugin manager 34 | * 35 | * @category DataManagement 36 | * @package RecordManager 37 | * @author Ere Maijala 38 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 39 | * @link https://github.com/NatLibFi/RecordManager 40 | * 41 | * @psalm-suppress MissingTemplateParam 42 | */ 43 | class PluginManager extends \Laminas\ServiceManager\AbstractPluginManager 44 | { 45 | } 46 | -------------------------------------------------------------------------------- /src/RecordManager/Base/Enrichment/PluginManager.php: -------------------------------------------------------------------------------- 1 | 26 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 27 | * @link https://github.com/NatLibFi/RecordManager 28 | */ 29 | 30 | namespace RecordManager\Base\Enrichment; 31 | 32 | /** 33 | * Enrichment plugin manager 34 | * 35 | * @category DataManagement 36 | * @package RecordManager 37 | * @author Ere Maijala 38 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 39 | * @link https://github.com/NatLibFi/RecordManager 40 | * 41 | * @psalm-suppress MissingTemplateParam 42 | */ 43 | class PluginManager extends \Laminas\ServiceManager\AbstractPluginManager 44 | { 45 | } 46 | -------------------------------------------------------------------------------- /src/RecordManager/Base/Splitter/PluginManager.php: -------------------------------------------------------------------------------- 1 | 26 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 27 | * @link https://github.com/NatLibFi/RecordManager 28 | */ 29 | 30 | namespace RecordManager\Base\Splitter; 31 | 32 | /** 33 | * Record splitter plugin manager 34 | * 35 | * @category DataManagement 36 | * @package RecordManager 37 | * @author Ere Maijala 38 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 39 | * @link https://github.com/NatLibFi/RecordManager 40 | * 41 | * @psalm-suppress MissingTemplateParam 42 | */ 43 | class PluginManager extends \Laminas\ServiceManager\AbstractPluginManager 44 | { 45 | } 46 | -------------------------------------------------------------------------------- /export.php: -------------------------------------------------------------------------------- 1 | 25 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 26 | * @link https://github.com/NatLibFi/RecordManager 27 | */ 28 | require_once __DIR__ . '/cmdline.php'; 29 | 30 | convertOptions( 31 | [ 32 | 'file' => [ 33 | 'command' => 'records:export', 34 | 'arg' => 1 35 | ], 36 | 'createdfrom' => [ 37 | 'opt' => 'created-from' 38 | ], 39 | 'createduntil' => [ 40 | 'opt' => 'created-until' 41 | ], 42 | 'sortdedup' => [ 43 | 'opt' => 'sort-dedup' 44 | ], 45 | 'dedupid' => [ 46 | 'opt' => 'dedup-id' 47 | ], 48 | ], 49 | ); 50 | 51 | include __DIR__ . '/console'; 52 | -------------------------------------------------------------------------------- /src/RecordManager/Base/Module.php: -------------------------------------------------------------------------------- 1 | 26 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 27 | * @link https://github.com/NatLibFi/RecordManager 28 | */ 29 | 30 | namespace RecordManager\Base; 31 | 32 | /** 33 | * RecordManager base module 34 | * 35 | * @category DataManagement 36 | * @package RecordManager 37 | * @author Ere Maijala 38 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 39 | * @link https://github.com/NatLibFi/RecordManager 40 | */ 41 | class Module 42 | { 43 | /** 44 | * Get module configuration 45 | * 46 | * @return array 47 | */ 48 | public function getConfig() 49 | { 50 | return include __DIR__ . '/config/module.config.php'; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /tests/rector.php: -------------------------------------------------------------------------------- 1 | 26 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 27 | * @link https://github.com/NatLibFi/RecordManager 28 | */ 29 | 30 | declare(strict_types=1); 31 | 32 | use Rector\Caching\ValueObject\Storage\FileCacheStorage; 33 | use Rector\Config\RectorConfig; 34 | use Rector\PHPUnit\Set\PHPUnitSetList; 35 | 36 | return RectorConfig::configure() 37 | ->withCache( 38 | cacheClass: FileCacheStorage::class, 39 | cacheDirectory: __DIR__ . '/../.rector' 40 | )->withPaths([ 41 | __DIR__ . '/../src', 42 | __DIR__ . '/../tests', 43 | ]) 44 | ->withSets([ 45 | PHPUnitSetList::PHPUNIT_110, 46 | PHPUnitSetList::ANNOTATIONS_TO_ATTRIBUTES, 47 | ]) 48 | ->withTypeCoverageLevel(0) 49 | ->withDeadCodeLevel(6) 50 | ->withCodeQualityLevel(22); 51 | -------------------------------------------------------------------------------- /src/RecordManager/Base/Command/PluginManager.php: -------------------------------------------------------------------------------- 1 | 26 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 27 | * @link https://github.com/NatLibFi/RecordManager 28 | */ 29 | 30 | namespace RecordManager\Base\Command; 31 | 32 | /** 33 | * Command plugin manager 34 | * 35 | * @category DataManagement 36 | * @package RecordManager 37 | * @author Ere Maijala 38 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 39 | * @link https://github.com/NatLibFi/RecordManager 40 | * 41 | * @psalm-suppress MissingTemplateParam 42 | */ 43 | class PluginManager extends \Laminas\ServiceManager\AbstractPluginManager 44 | { 45 | /** 46 | * Get a list of all available commands in the plugin manager. 47 | * 48 | * @return array 49 | */ 50 | public function getCommandList() 51 | { 52 | return array_keys((array)$this->factories); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /mappings/forward_id_role.map.sample: -------------------------------------------------------------------------------- 1 | ; Map FORWARD (EN 15907) roles to RDA roles 2 | 3 | (.(^###))*###a00 = ${1}###oth 4 | (.(^###))*###a01 = ${1}###aus 5 | (.(^###))*###a02 = ${1}###aus 6 | (.(^###))*###a03 = ${1}###aus 7 | (.(^###))*###a05 = ${1}###lyr 8 | (.(^###))*###a06 = ${1}###cmp 9 | (.(^###))*###a08 = ${1}###pht 10 | (.(^###))*###a09 = ${1}###aut 11 | (.(^###))*###a10 = ${1}###org 12 | (.(^###))*###a11 = ${1}###dsr 13 | (.(^###))*###a12 = ${1}###ill 14 | (.(^###))*###a13 = ${1}###pht 15 | (.(^###))*###a31 = ${1}###lyr 16 | (.(^###))*###a38 = ${1}###org 17 | (.(^###))*###a43 = ${1}###ivr 18 | (.(^###))*###a50 = ${1}###aud 19 | (.(^###))*###a99 = ${1}###oth 20 | (.(^###))*###b01 = ${1}###flm 21 | (.(^###))*###b05 = ${1}###arr 22 | (.(^###))*###b06 = ${1}###trl 23 | (.(^###))*###b13 = ${1}###flm 24 | (.(^###))*###b17 = ${1}###org 25 | (.(^###))*###b19 = ${1}###flm 26 | (.(^###))*###b24 = ${1}###edt 27 | (.(^###))*###b25 = ${1}###arr 28 | (.(^###))*###d01 = ${1}###fmp 29 | (.(^###))*###d02 = ${1}###drt 30 | (.(^###))*###d03 = ${1}###cnd 31 | (.(^###))*###d99 = ${1}###drt 32 | (.(^###))*###e01 = ${1}###act 33 | (.(^###))*###e02 = ${1}###dnc 34 | (.(^###))*###e03 = ${1}###nrt 35 | (.(^###))*###e04 = ${1}###cmm 36 | (.(^###))*###e05 = ${1}###sng 37 | (.(^###))*###e06 = ${1}###mus 38 | (.(^###))*###e08 = ${1}###mus 39 | (.(^###))*###e10 = ${1}###fmp 40 | (.(^###))*###f01 = ${1}###cng 41 | (.(^###))*###f02 = ${1}###edt 42 | (.(^###))*###f99 = ${1}###rce 43 | 44 | (.(^###))*###dialogi = ${1}###aud, 45 | (.(^###))*###kuvaaja = ${1}###cng, 46 | (.(^###))*###lavastus = ${1}###std, 47 | (.(^###))*###lavastaja = ${1}###std, 48 | (.(^###))*###puvustus = ${1}###cst, 49 | (.(^###))*###tuotannon suunnittelu = ${1}###prs, 50 | (.(^###))*###tuotantopäällikkö = ${1}###pmn, 51 | (.(^###))*###muusikko = ${1}###mus, 52 | (.(^###))*###selostaja = ${1}###spk, 53 | (.(^###))*###valokuvaaja = ${1}###pht, 54 | (.(^###))*###valonmääritys = ${1}###lgd, 55 | (.(^###))*###vastaava tuottaja = ${1}###pro, 56 | (.(^###))*###äänitys = ${1}###rce 57 | -------------------------------------------------------------------------------- /src/RecordManager/Base/Exception/RequestException.php: -------------------------------------------------------------------------------- 1 | 26 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 27 | * @link https://github.com/NatLibFi/RecordManager 28 | */ 29 | 30 | namespace RecordManager\Base\Exception; 31 | 32 | use function intval; 33 | 34 | /** 35 | * Request Exception Class 36 | * 37 | * @category DataManagement 38 | * @package RecordManager 39 | * @author Ere Maijala 40 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 41 | * @link https://github.com/NatLibFi/RecordManager 42 | */ 43 | class RequestException extends \Exception 44 | { 45 | /** 46 | * Create a new exception based on a previous exception 47 | * 48 | * @param \Exception $e Previous exception 49 | * 50 | * @return RequestException 51 | */ 52 | public static function fromException(\Exception $e): RequestException 53 | { 54 | $className = static::class; 55 | return new $className($e->getMessage(), intval($e->getCode()), $e); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/RecordManager/Base/Utils/XmlSecurity.php: -------------------------------------------------------------------------------- 1 | 26 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 27 | * @link https://github.com/NatLibFi/RecordManager 28 | */ 29 | 30 | namespace RecordManager\Base\Utils; 31 | 32 | /** 33 | * XML Security Class 34 | * 35 | * This class contains XML security functions 36 | * 37 | * @category DataManagement 38 | * @package RecordManager 39 | * @author Ere Maijala 40 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 41 | * @link https://github.com/NatLibFi/RecordManager 42 | */ 43 | class XmlSecurity extends \Laminas\Xml\Security 44 | { 45 | /** 46 | * Heuristic scan to detect entity in XML 47 | * 48 | * @param string $xml XML 49 | * 50 | * @return void 51 | * @throws \RuntimeException If entity expansion or external entity declaration 52 | * was discovered. 53 | */ 54 | public static function heuristicScanString($xml) 55 | { 56 | static::heuristicScan($xml); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /tests/fixtures/Base/utils/LineBasedMarcFormatter/alma.xml: -------------------------------------------------------------------------------- 1 | 00936cam a22002654i 4500991765167950625220211213124319.0m dcr#|||||||||||200511s2020 fi |||||sm||||||||||fin|cOamk intraFI-O fin rdafin eng, kirjoittaja.testitietue testaamiseen / .[Oulu] : Oulun ammattikorkeakoulu, kevät 2020.1 verkkoaineisto (30 sivua)teksti txt rdacontenttietokonekäyttöinen c rdamediaverkkoaineisto cr rdacarrierAdobe Acrobat Reader..pystyviiva | yso/fin 2 | -------------------------------------------------------------------------------- /tests/fixtures/Base/Controller/CreatePreview/preview_result.json: -------------------------------------------------------------------------------- 1 | { 2 | "record_format": "marc", 3 | "building": [ 4 | "150" 5 | ], 6 | "fullrecord": "{\"leader\":\"00000cam a22000004i 4500\",\"fields\":[{\"001\":\"123\"},{\"005\":\"20160322194428.0\"},{\"008\":\"140327s2013 fi 000 0 fin d\"},{\"020\":{\"ind1\":\" \",\"ind2\":\" \",\"subfields\":[{\"a\":\"978-951-31-4836-2\"}]}},{\"100\":{\"ind1\":\"1\",\"ind2\":\" \",\"subfields\":[{\"a\":\"Hirsjärvi, Sirkka.\"},{\"0\":\"(TEST)1\"}]}},{\"245\":{\"ind1\":\"1\",\"ind2\":\"0\",\"subfields\":[{\"a\":\"Tutki ja kirjoita \\/\"},{\"c\":\"Sirkka Hirsjärvi, Pirkko Remes, Paula Sajavaara.\"}]}},{\"264\":{\"ind1\":\" \",\"ind2\":\"1\",\"subfields\":[{\"c\":\"2013\"}]}},{\"852\":{\"ind1\":\"8\",\"ind2\":\" \",\"subfields\":[{\"a\":\"E\"},{\"b\":\"150\"},{\"h\":\"38 Hir\"},{\"z\":\"18. p. 2013\"},{\"9\":\"Test\"}]}}]}", 7 | "allfields": [ 8 | "Hirsj\u00e4rvi, Sirkka", 9 | "Tutki ja kirjoita", 10 | "Sirkka Hirsj\u00e4rvi, Pirkko Remes, Paula Sajavaara", 11 | "2013" 12 | ], 13 | "language": [ 14 | "fin" 15 | ], 16 | "format": ["Book"], 17 | "author": [ 18 | "Hirsj\u00e4rvi, Sirkka" 19 | ], 20 | "author_variant": ["s h sh"], 21 | "author_sort": "Hirsj\u00e4rvi, Sirkka", 22 | "title": "Tutki ja kirjoita", 23 | "title_short": "Tutki ja kirjoita", 24 | "title_full": "Tutki ja kirjoita \/ Sirkka Hirsj\u00e4rvi, Pirkko Remes, Paula Sajavaara", 25 | "title_sort": "tutki ja kirjoita sirkka hirsj\u00e4rvi pirkko remes paula sajavaara", 26 | "publishDateSort": "2013", 27 | "publishDate": [ 28 | "2013" 29 | ], 30 | "publishDateRange": [ 31 | "2013" 32 | ], 33 | "isbn": [ 34 | "9789513148362" 35 | ], 36 | "illustrated": "Not Illustrated", 37 | "id": "test.123", 38 | "work_keys_str_mv": [ 39 | "AT hirsjarvisirkka tutkijakirjoita" 40 | ], 41 | "institution": "Test", 42 | "first_indexed": "1970-01-01T00:00:00Z", 43 | "last_indexed": "1970-01-01T00:00:00Z" 44 | } 45 | -------------------------------------------------------------------------------- /src/RecordManager/Base/Database/Regex.php: -------------------------------------------------------------------------------- 1 | 26 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 27 | * @link https://github.com/NatLibFi/RecordManager 28 | */ 29 | 30 | namespace RecordManager\Base\Database; 31 | 32 | /** 33 | * Regular expression class 34 | * 35 | * @category DataManagement 36 | * @package RecordManager 37 | * @author Ere Maijala 38 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 39 | * @link https://github.com/NatLibFi/RecordManager 40 | */ 41 | class Regex 42 | { 43 | /** 44 | * Regular expression 45 | * 46 | * @var string 47 | */ 48 | protected $regex; 49 | 50 | /** 51 | * Constructor 52 | * 53 | * @param string $regex Regular expression 54 | */ 55 | public function __construct(string $regex) 56 | { 57 | $this->regex = $regex; 58 | } 59 | 60 | /** 61 | * Return regex as a string 62 | * 63 | * @return string 64 | */ 65 | public function __toString(): string 66 | { 67 | return $this->regex; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /tests/fixtures/Base/record/qdc1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Urine : The potential, value chain and its sustainable management 4 | Viskari, Eeva-Liisa 5 | Lehtoranta, Suvi 6 | Malila, Riikka 7 | urine 8 | fertilizer 9 | value chain 10 | agriculture 11 | nutrient recovery 12 | virtsa 13 | lannoitteet 14 | ravinteet 15 | uudelleenkäyttö 16 | maatalous 17 | 2021-06-16T06:31:44Z 18 | 2021 19 | Article 20 | okm_type 21 | okm_type_2 22 | other_type 23 | Eeva-Liisa Viskari, Suvi Lehtoranta, Riikka Malila. Urine : The potential, value chain and its sustainable management. Sanitation Value Chain (2021) 5, 1, pages 10-12. https://doi.org/10.34416/svc.00029 24 | 2432-5058 25 | http://hdl.handle.net/10138/331330 26 | https://doi.org/10.34416/svc.00029 27 | en 28 | Sanitation Value Chain 5:1 29 | CC BY-NC-ND 4.0 30 | Sanitation Project, Research Institute for Humanity and Nature 31 | http://dx.doi.org/https://doi.org/10.34416/svc.00029 32 | 10138_331330 33 | 34 | -------------------------------------------------------------------------------- /src/RecordManager/Base/Solr/PreviewCreator.php: -------------------------------------------------------------------------------- 1 | 27 | * @author Eero Heikkinen 28 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 29 | * @link https://github.com/NatLibFi/RecordManager 30 | */ 31 | 32 | namespace RecordManager\Base\Solr; 33 | 34 | /** 35 | * Preview Creator 36 | * 37 | * This is a class for getting realtime previews of metadata normalization. 38 | * 39 | * @category DataManagement 40 | * @package RecordManager 41 | * @author Ere Maijala 42 | * @author Eero Heikkinen 43 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 44 | * @link https://github.com/NatLibFi/RecordManager 45 | */ 46 | class PreviewCreator extends SolrUpdater 47 | { 48 | /** 49 | * Create a preview of the given record 50 | * 51 | * @param array $record Record 52 | * 53 | * @return array Solr record fields 54 | */ 55 | public function create($record) 56 | { 57 | $components = 0; 58 | return $this->createSolrArray($record, $components) ?: []; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /tests/RecordManagerTest/Base/Utils/LcCallNumberTest.php: -------------------------------------------------------------------------------- 1 | 26 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 27 | * @link https://github.com/NatLibFi/RecordManager 28 | */ 29 | 30 | namespace RecordManagerTest\Base\Utils; 31 | 32 | use RecordManager\Base\Utils\LcCallNumber; 33 | 34 | /** 35 | * LcCallNumber tests 36 | * 37 | * @category DataManagement 38 | * @package RecordManager 39 | * @author Ere Maijala 40 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 41 | * @link https://github.com/NatLibFi/RecordManager 42 | */ 43 | class LcCallNumberTest extends \PHPUnit\Framework\TestCase 44 | { 45 | /** 46 | * Tests for call number handling 47 | * 48 | * @return void 49 | */ 50 | public function testCallNumber() 51 | { 52 | $cn = new LcCallNumber('AC901.M5 vol. 1013, no. 8'); 53 | $this->assertTrue($cn->isValid()); 54 | $this->assertEquals( 55 | 'AC 3901 M15', 56 | $cn->getSortKey() 57 | ); 58 | 59 | $cn = new LcCallNumber('GV1101 .D7 1980'); 60 | $this->assertTrue($cn->isValid()); 61 | $this->assertEquals( 62 | 'GV 41101 D17', 63 | $cn->getSortKey() 64 | ); 65 | 66 | $cn = new LcCallNumber('XV1101 .D7 1980'); 67 | $this->assertFalse($cn->isValid()); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /console: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | start(); 19 | } 20 | 21 | // Register a signal handler so that any shutdown functions run if execution is 22 | // interrupted 23 | $signalHandler = function ($signo) { 24 | exit(255); 25 | }; 26 | if (function_exists('pcntl_signal')) { 27 | pcntl_signal(SIGINT, $signalHandler); 28 | pcntl_signal(SIGTERM, $signalHandler); 29 | } 30 | 31 | // Handle basepath and config overrides ("--config.Section.parameter = value"): 32 | $basepath = null; 33 | $overrides = []; 34 | $remainingArgs = []; 35 | foreach ($_SERVER['argv'] as $parameter) { 36 | if (!str_starts_with($parameter, '--') || !str_contains($parameter, '=')) { 37 | $remainingArgs[] = $parameter; 38 | continue; 39 | } 40 | $parsed = @parse_ini_string(substr($parameter, 2)); 41 | if (false === $parsed) { 42 | $remainingArgs[] = $parameter; 43 | continue; 44 | } 45 | if (isset($parsed['basepath'])) { 46 | $basepath = $parsed['basepath']; 47 | } else { 48 | reset($parsed); 49 | $key = key($parsed); 50 | if (preg_match('/^config\.([^.]+)\.(.+)/', $key, $matches)) { 51 | $overrides[$matches[1]][$matches[2]] = $parsed[$key]; 52 | } else { 53 | $remainingArgs[] = $parameter; 54 | } 55 | } 56 | } 57 | $_SERVER['argv'] = $remainingArgs; 58 | $_SERVER['argc'] = count($remainingArgs); 59 | 60 | define('RECMAN_BASE_PATH', $basepath ?: getenv('RECMAN_BASE_PATH') ?: __DIR__); 61 | 62 | $app = Laminas\Mvc\Application::init(require 'conf/application.config.php'); 63 | $sm = $app->getServiceManager(); 64 | if ($overrides) { 65 | $configReader = $sm->get(\RecordManager\Base\Settings\Ini::class); 66 | $configReader->addOverrides('recordmanager.ini', $overrides); 67 | } 68 | return $sm->get(\RecordManager\Base\ConsoleRunner::class)->run(); 69 | -------------------------------------------------------------------------------- /mappings/format.map.sample: -------------------------------------------------------------------------------- 1 | Article = Article 2 | Atlas = Map 3 | Book = Book 4 | BookComponentPart = Book Chapter 5 | Braille = Braille 6 | BRDisc = Blu-ray Disc 7 | CDROM = Software 8 | Chart = Photo 9 | ChipCartridge = Software 10 | Collage = Photo 11 | ConferenceProceeding= Conference Proceeding 12 | DataSet = Data Set 13 | DiscCartridge = Software 14 | Drawing = Photo 15 | DVD = DVD 16 | eBook = eBook 17 | eJournal = Journal 18 | Electronic = Electronic 19 | ElectronicResource = Software 20 | Filmstrip = Video 21 | FlashCard = Photo 22 | FloppyDisk = Software 23 | Font = Software 24 | Globe = Globe 25 | GovernmentDocument = Government Document 26 | Image = Image 27 | InteractiveMultimedia = Software 28 | Journal = Journal 29 | Kit = Kit 30 | LaserDisc = Laser Disc 31 | Manuscript = Manuscript 32 | Map = Map 33 | Microfilm = Microfilm 34 | MotionPicture = Video 35 | MusicalScore = Musical Score 36 | MusicRecording = Audio 37 | Newspaper = Newspaper 38 | OnlineIntegratingResource = Database 39 | Painting = Photo 40 | Photonegative = Photo 41 | Photo = Photo 42 | PhysicalIntegratingResource = Reference Material 43 | PhysicalObject = Physical Object 44 | Postcard = Postcard 45 | Poster = Poster 46 | Print = Photo 47 | ProjectedMedium = Slide 48 | SensorImage = Sensor Image 49 | SerialComponentPart = Article 50 | Serial = Serial 51 | Slide = Slide 52 | Software = Software 53 | SoundCassette = Cassette 54 | SoundDisc = CD 55 | SoundRecording = Audio 56 | TapeCartridge = Software 57 | TapeCassette = Software 58 | TapeReel = Software 59 | Text = Text 60 | Thesis = Thesis 61 | Transparency = Slide 62 | Unknown = Unknown 63 | VideoCartridge = Video 64 | VideoCassette = VHS 65 | VideoDisc = Videodisc 66 | VideoGame = Video Game 67 | VideoOnline = Video 68 | VideoReel = Video 69 | Video = Video 70 | Website = Website 71 | -------------------------------------------------------------------------------- /src/RecordManager/Base/Splitter/SplitterInterface.php: -------------------------------------------------------------------------------- 1 | 26 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 27 | * @link https://github.com/NatLibFi/RecordManager 28 | */ 29 | 30 | namespace RecordManager\Base\Splitter; 31 | 32 | /** 33 | * Splitter interface 34 | * 35 | * @category DataManagement 36 | * @package RecordManager 37 | * @author Ere Maijala 38 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 39 | * @link https://github.com/NatLibFi/RecordManager 40 | */ 41 | interface SplitterInterface 42 | { 43 | /** 44 | * Initializer 45 | * 46 | * @param array $params Splitter configuration 47 | * 48 | * @return void 49 | */ 50 | public function init(array $params); 51 | 52 | /** 53 | * Set metadata 54 | * 55 | * @param string $data Record metadata 56 | * 57 | * @return void 58 | */ 59 | public function setData($data); 60 | 61 | /** 62 | * Check whether EOF has been encountered 63 | * 64 | * @return bool 65 | */ 66 | public function getEOF(); 67 | 68 | /** 69 | * Get next record 70 | * 71 | * Returns false on EOF or an associative array with the following keys: 72 | * - string metadata Actual metadata 73 | * - array additionalData Any additional data 74 | * 75 | * @return array|bool 76 | */ 77 | public function getNextRecord(); 78 | } 79 | -------------------------------------------------------------------------------- /tests/fixtures/Base/utils/LineBasedMarcFormatter/genieplus.txt: -------------------------------------------------------------------------------- 1 | LDR‡02558cmm 2200529Ii 4500^ 2 | 001‡on1287119441^ 3 | 003‡OCoLC^ 4 | 005‡20220208124506.0^ 5 | 006‡m o d ^ 6 | 007‡cr mn|||||||||^ 7 | 008‡211203s2021 inu o 000 0 eng d^ 8 | 035 ‡a(OCoLC)1287119441^ 9 | 040 ‡aHLR‡beng‡erda‡cHLR‡dYLS‡dHUL‡dOCL‡dOCLCO^ 10 | 043 ‡an-us---^ 11 | 24504‡aThe COVID crisis in legal education :‡b2021 Annual survey results /‡cLSSSE, Law School Survey of Student Engagement.^ 12 | 24617‡aLaw School Survey of Student Engagement :‡b2021 annual survey results^ 13 | 260 ‡aBloomington, IN :‡bCenter for Postsecondary Research, School of Education, Indiana University Bloomington,‡c[2021]^ 14 | 300 ‡a1 online resource (17 pages ):‡bdigital, PDF file^ 15 | 336 ‡atext‡btxt‡2rdacontent^ 16 | 337 ‡acomputer‡bc‡2rdamedia^ 17 | 338 ‡aonline resource‡bcr‡2rdacarrier^ 18 | 347 ‡atext file‡bPDF‡2rda^ 19 | 520 ‡aProvides public access to an open-access annual report to reveal structural inequalities that had previously created disparities based on race, ethnicity, gender, socioeconomic status, and other markers exploded due to the COVID-19 pandemic in legal education.^ 20 | 5880 ‡aContents viewed December 3, 2021; title from home page.^ 21 | 647 7‡aCOVID-19 Pandemic‡d(2020-)‡2fast‡0(OCoLC)fst02024716^ 22 | 650 0‡aLaw‡xStudy and teaching‡zUnited States.^ 23 | 650 0‡aLaw students‡zUnited States‡xAttitudes.^ 24 | 650 0‡aLaw schools‡zUnited States.^ 25 | 650 0‡aCOVID-19 (Disease)‡xSocial aspects‡zUnited States.^ 26 | 650 0‡aCOVID-19 Pandemic, 2020-‡zUnited States‡xInfluence.^ 27 | 650 0‡aPublic health‡xSocial aspects‡zUnited States.^ 28 | 650 0‡aEpidemics‡xSocial aspects‡zUnited States.^ 29 | 650 7‡aInfluence (Literary, artistic, etc.)‡2fast‡0(OCoLC)fst00972484^ 30 | 650 7‡aLaw‡xStudy and teaching.‡2fast‡0(OCoLC)fst00993829^ 31 | 650 7‡aLaw students‡xAttitudes.‡2fast‡0(OCoLC)fst00994147^ 32 | 650 7‡aLaw schools.‡2fast‡0(OCoLC)fst00994121^ 33 | 650 7‡aCOVID-19 (Disease)‡xSocial aspects.‡2fast‡0(OCoLC)fst01984649^ 34 | 650 7‡aPublic health‡xSocial aspects.‡2fast‡0(OCoLC)fst01082307^ 35 | 650 7‡aEpidemics‡xSocial aspects.‡2fast‡0(OCoLC)fst00914088^ 36 | 651 7‡aUnited States.‡2fast‡0(OCoLC)fst01204155^ 37 | 655 4‡aElectronic books.^ 38 | 7102 ‡aIndiana University, Bloomington.‡bCenter for Postsecondary Research,‡eissuing body.^ 39 | 85640‡uhttps://lssse.indiana.edu/wp-content/uploads/2015/12/COVID-Crisis-in-Legal-Education-Final-10.28.21.pdf^ 40 | 948 ‡hNO HOLDINGS IN VLA - 15 OTHER HOLDINGS^ 41 | 994 ‡aZ0‡bVLA^ 42 | 998 ‡ainter^ -------------------------------------------------------------------------------- /src/RecordManager/Base/Command/Solr/Optimize.php: -------------------------------------------------------------------------------- 1 | 26 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 27 | * @link https://github.com/NatLibFi/RecordManager 28 | */ 29 | 30 | namespace RecordManager\Base\Command\Solr; 31 | 32 | use RecordManager\Base\Command\AbstractBase; 33 | use Symfony\Component\Console\Command\Command; 34 | use Symfony\Component\Console\Input\InputInterface; 35 | use Symfony\Component\Console\Output\OutputInterface; 36 | 37 | /** 38 | * Solr Optimization 39 | * 40 | * @category DataManagement 41 | * @package RecordManager 42 | * @author Ere Maijala 43 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 44 | * @link https://github.com/NatLibFi/RecordManager 45 | */ 46 | class Optimize extends AbstractBase 47 | { 48 | use CommandWithSolrUpdaterTrait; 49 | 50 | /** 51 | * Configure the command. 52 | * 53 | * @return void 54 | */ 55 | protected function configure() 56 | { 57 | $this->setDescription('Optimize Solr index'); 58 | } 59 | 60 | /** 61 | * Optimize the Solr index 62 | * 63 | * @param InputInterface $input Console input 64 | * @param OutputInterface $output Console output 65 | * 66 | * @return int 0 if everything went fine, or an exit code 67 | */ 68 | protected function doExecute(InputInterface $input, OutputInterface $output) 69 | { 70 | $this->solrUpdater->optimizeIndex(); 71 | return Command::SUCCESS; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "natlibfi/recordmanager", 3 | "description": "Record management utility for VuFind", 4 | "authors": [ 5 | { 6 | "name": "Ere Maijala", 7 | "email": "ere.maijala@helsinki.fi" 8 | } 9 | ], 10 | "license": "GPL-2.0", 11 | "config": { 12 | "platform": { 13 | "php": "8.2.4" 14 | }, 15 | "allow-plugins": { 16 | "composer/package-versions-deprecated": true, 17 | "wikimedia/composer-merge-plugin": true 18 | } 19 | }, 20 | "autoload": { 21 | "psr-4": { 22 | "RecordManager\\": "src/RecordManager/" 23 | } 24 | }, 25 | "autoload-dev": { 26 | "psr-4": { 27 | "RecordManagerTest\\": "tests/RecordManagerTest/" 28 | } 29 | }, 30 | "provide": { 31 | "ext-mongodb": "*" 32 | }, 33 | "require": { 34 | "php": ">=8.2.4", 35 | "cash/lrucache": "1.0.0", 36 | "guzzlehttp/guzzle": "7.10.0", 37 | "laminas/laminas-mvc": "3.8.0", 38 | "laminas/laminas-router": "3.16.0", 39 | "laminas/laminas-servicemanager": "3.23.0", 40 | "laminas/laminas-xml": "1.7.0", 41 | "league/mime-type-detection": "1.16.0", 42 | "ml/json-ld": "1.2.1", 43 | "mongodb/mongodb": "2.1.2", 44 | "pcrov/jsonreader": "1.0.4", 45 | "phayes/geophp": "1.2", 46 | "pietercolpaert/hardf": "0.5.0", 47 | "symfony/console": "6.4.25", 48 | "symfony/lock": "6.4.26", 49 | "vufind-org/vufind-marc": "1.2.0", 50 | "wikimedia/composer-merge-plugin": "2.1.0" 51 | }, 52 | "require-dev": { 53 | "friendsofphp/php-cs-fixer": "3.89.2", 54 | "phing/phing": "3.1.0", 55 | "phpstan/phpstan": "2.1.32", 56 | "phpunit/phpunit": "11.5.43", 57 | "rector/rector": "2.2.7", 58 | "squizlabs/php_codesniffer": "4.0.1", 59 | "vimeo/psalm": "6.5.0" 60 | }, 61 | "scripts": { 62 | "fix": "phing fix-php", 63 | "qa": "phing qa-tasks" 64 | }, 65 | "extra": { 66 | "merge-plugin": { 67 | "include": [ 68 | "composer.local.json" 69 | ], 70 | "recurse": true, 71 | "replace": true, 72 | "ignore-duplicates": false, 73 | "merge-dev": true, 74 | "merge-extra": false, 75 | "merge-extra-deep": false, 76 | "merge-scripts": true 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/RecordManager/Base/Command/Util/IniFileTrait.php: -------------------------------------------------------------------------------- 1 | 26 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 27 | * @link https://github.com/NatLibFi/RecordManager 28 | */ 29 | 30 | namespace RecordManager\Base\Command\Util; 31 | 32 | /** 33 | * Ini file handling utility trait 34 | * 35 | * @category DataManagement 36 | * @package RecordManager 37 | * @author Ere Maijala 38 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 39 | * @link https://github.com/NatLibFi/RecordManager 40 | */ 41 | trait IniFileTrait 42 | { 43 | /** 44 | * Check if a line is a comment line (contains a comment and nothing else) 45 | * 46 | * @param string $line Line to check 47 | * 48 | * @return bool 49 | */ 50 | protected function isCommentLine(string $line): bool 51 | { 52 | $line = trim($line); 53 | return strncmp($line, ';', 1) === 0; 54 | } 55 | 56 | /** 57 | * Get section name from a string 58 | * 59 | * @param string $line Line to check 60 | * 61 | * @return string Section name or empty string if not a section 62 | */ 63 | protected function getSectionFromLine(string $line): string 64 | { 65 | if ( 66 | $line 67 | && str_starts_with($line, '[') 68 | && str_ends_with($line, ']') 69 | && $line !== '[]' 70 | ) { 71 | return substr($line, 1, -1); 72 | } 73 | return ''; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /transformations/koha.xsl.sample: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /mappings/usage_rights.map.sample: -------------------------------------------------------------------------------- 1 | ; Regexp map. Note: the order is important since first match will rule over others. 2 | 3 | ^CC0$[] = usage_A 4 | ^CC0$[] = usage_B 5 | ^CC0$[] = usage_C 6 | ^CC0$[] = usage_D 7 | ^CC0$[] = usage_E 8 | 9 | ^CC[ -]*BY[ -]*NC[ -]*ND.*[] = usage_E 10 | ^https?://creativecommons\.org/licenses/by-nc-nd/.*[] = usage_E 11 | 12 | ^CC[ -]*BY[ -]*NC[ -]*SA.*[] = usage_D 13 | ^CC[ -]*BY[ -]*NC[ -]*SA.*[] = usage_E 14 | ^https?://creativecommons\.org/licenses/by-nc-sa/.*[] = usage_D 15 | ^https?://creativecommons\.org/licenses/by-nc-sa/.*[] = usage_E 16 | 17 | ^CC[ -]*BY[ -]*SA.*[] = usage_B 18 | ^CC[ -]*BY[ -]*SA.*[] = usage_C 19 | ^CC[ -]*BY[ -]*SA.*[] = usage_D 20 | ^CC[ -]*BY[ -]*SA.*[] = usage_E 21 | ^https?://creativecommons\.org/licenses/by-sa/.*[] = usage_B 22 | ^https?://creativecommons\.org/licenses/by-sa/.*[] = usage_C 23 | ^https?://creativecommons\.org/licenses/by-sa/.*[] = usage_D 24 | ^https?://creativecommons\.org/licenses/by-sa/.*[] = usage_E 25 | 26 | ^CC[ -]*BY[ -]*ND.*[] = usage_C 27 | ^CC[ -]*BY[ -]*ND.*[] = usage_E 28 | ^https?://creativecommons\.org/licenses/by-nd/.*[] = usage_C 29 | ^https?://creativecommons\.org/licenses/by-nd/.*[] = usage_E 30 | 31 | ^CC[ -]*BY[ -]*NC.*[] = usage_D 32 | ^https?://creativecommons\.org/licenses/by-nc/.*[] = usage_D 33 | 34 | ^CC[ -]*BY[ \.\d]*[] = usage_B 35 | ^CC[ -]*BY[ \.\d]*[] = usage_C 36 | ^CC[ -]*BY[ \.\d]*[] = usage_D 37 | ^CC[ -]*BY[ \.\d]*[] = usage_E 38 | ^https?://creativecommons\.org/licenses/by/.*[] = usage_B 39 | ^https?://creativecommons\.org/licenses/by/.*[] = usage_C 40 | ^https?://creativecommons\.org/licenses/by/.*[] = usage_D 41 | ^https?://creativecommons\.org/licenses/by/.*[] = usage_E 42 | 43 | ^No known copyright restrictions$[] = usage_B 44 | ^No known copyright restrictions$[] = usage_C 45 | ^No known copyright restrictions$[] = usage_D 46 | ^No known copyright restrictions$[] = usage_E 47 | 48 | ^Public [Dd]omain.*[] = usage_A 49 | ^Public [Dd]omain.*[] = usage_B 50 | ^Public [Dd]omain.*[] = usage_C 51 | ^Public [Dd]omain.*[] = usage_D 52 | ^Public [Dd]omain.*[] = usage_E 53 | 54 | ^https?://creativecommons\.org/publicdomain/.*[] = usage_A 55 | ^https?://creativecommons\.org/publicdomain/.*[] = usage_B 56 | ^https?://creativecommons\.org/publicdomain/.*[] = usage_C 57 | ^https?://creativecommons\.org/publicdomain/.*[] = usage_D 58 | ^https?://creativecommons\.org/publicdomain/.*[] = usage_E 59 | 60 | ^restricted$[] = usage_F 61 | 62 | ; By default map to empty value: 63 | ##default = 64 | ; If mappings of all values results in empty, use the following: 65 | ##mappedemptyarray = usage_F 66 | -------------------------------------------------------------------------------- /src/RecordManager/Base/ConsoleRunner.php: -------------------------------------------------------------------------------- 1 | 26 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 27 | * @link https://vufind.org/wiki/development Wiki 28 | */ 29 | 30 | namespace RecordManager\Base; 31 | 32 | use RecordManager\Base\Command\PluginManager as CommandPluginManager; 33 | 34 | /** 35 | * Console runner. 36 | * 37 | * @category DataManagement 38 | * @package RecordManager 39 | * @author Demian Katz 40 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 41 | * @link https://vufind.org/wiki/development Wiki 42 | */ 43 | class ConsoleRunner 44 | { 45 | /** 46 | * List of commands 47 | * 48 | * @var array 49 | */ 50 | protected $commands; 51 | 52 | /** 53 | * Plugin manager (to retrieve commands) 54 | * 55 | * @var CommandPluginManager 56 | */ 57 | protected $pluginManager; 58 | 59 | /** 60 | * Constructor 61 | * 62 | * @param CommandPluginManager $pm Plugin manager (to retrieve commands) 63 | */ 64 | public function __construct(CommandPluginManager $pm) 65 | { 66 | $this->pluginManager = $pm; 67 | } 68 | 69 | /** 70 | * Run the console action 71 | * 72 | * @return mixed 73 | */ 74 | public function run() 75 | { 76 | $consoleApp = new Application('RecordManager'); 77 | foreach ($this->pluginManager->getCommandList() as $command) { 78 | $consoleApp->add($this->pluginManager->get($command)); 79 | } 80 | 81 | return $consoleApp->run(); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /transformations/helmet.xsl: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | Book 17 | Map 18 | SoundDisc 19 | SoundCassette 20 | SoundRecording 21 | MusicalScore 22 | Journal 23 | Image 24 | Slide 25 | Drawing 26 | CDROM 27 | DVDROM 28 | VideoCassette 29 | DVD 30 | BluRay 31 | Microfilm 32 | Manuscript 33 | Braille 34 | FloppyDisk 35 | Software 36 | PhysicalObject 37 | BoardGame 38 | DVDAudio 39 | Electronic 40 | eBook 41 | Other 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /src/RecordManager/Base/Utils/AbstractCallNumber.php: -------------------------------------------------------------------------------- 1 | 26 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 27 | * @link https://github.com/NatLibFi/RecordManager 28 | */ 29 | 30 | namespace RecordManager\Base\Utils; 31 | 32 | use function intval; 33 | use function strlen; 34 | 35 | /** 36 | * Call number base class 37 | * 38 | * @category DataManagement 39 | * @package RecordManager 40 | * @author Ere Maijala 41 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 42 | * @link https://github.com/NatLibFi/RecordManager 43 | */ 44 | abstract class AbstractCallNumber 45 | { 46 | /** 47 | * Constructor 48 | * 49 | * @param string $callnumber Call Number 50 | */ 51 | abstract public function __construct($callnumber); 52 | 53 | /** 54 | * Check if the call number is valid 55 | * 56 | * @return bool 57 | */ 58 | abstract public function isValid(); 59 | 60 | /** 61 | * Create a sort key 62 | * 63 | * @return string 64 | */ 65 | abstract public function getSortKey(); 66 | 67 | /** 68 | * Make a string numerically sortable 69 | * 70 | * @param string $str String 71 | * 72 | * @return ?string 73 | */ 74 | protected function createSortableString($str) 75 | { 76 | $str = preg_replace_callback( 77 | '/(\d+)/', 78 | function ($matches) { 79 | return strlen((string)(intval($matches[1]))) . $matches[1]; 80 | }, 81 | mb_strtoupper($str, 'UTF-8') 82 | ); 83 | return preg_replace('/\s{2,}/', ' ', $str); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /mappings/iso639-1_to_iso639-2.map: -------------------------------------------------------------------------------- 1 | aa = aar 2 | ab = abk 3 | af = afr 4 | ak = aka 5 | sq = alb 6 | am = amh 7 | ar = ara 8 | an = arg 9 | hy = arm 10 | as = asm 11 | av = ava 12 | ae = ave 13 | ay = aym 14 | az = aze 15 | ba = bak 16 | bm = bam 17 | eu = baq 18 | be = bel 19 | bn = ben 20 | bh = bih 21 | bi = bis 22 | bs = bos 23 | br = bre 24 | bg = bul 25 | my = bur 26 | ca = cat 27 | ch = cha 28 | ce = che 29 | zh = chi 30 | cu = chu 31 | cv = chv 32 | kw = cor 33 | co = cos 34 | cr = cre 35 | cs = cze 36 | da = dan 37 | dv = div 38 | nl = dut 39 | dz = dzo 40 | en = eng 41 | eo = epo 42 | et = est 43 | ee = ewe 44 | fo = fao 45 | fj = fij 46 | fi = fin 47 | fr = fre 48 | fy = fry 49 | ff = ful 50 | ka = geo 51 | de = ger 52 | gd = gla 53 | ga = gle 54 | gl = glg 55 | gv = glv 56 | el = gre 57 | gn = grn 58 | gu = guj 59 | ht = hat 60 | ha = hau 61 | he = heb 62 | hz = her 63 | hi = hin 64 | ho = hmo 65 | hr = hrv 66 | hu = hun 67 | ig = ibo 68 | is = ice 69 | io = ido 70 | ii = iii 71 | iu = iku 72 | ie = ile 73 | ia = ina 74 | id = ind 75 | ik = ipk 76 | it = ita 77 | jv = jav 78 | ja = jpn 79 | kl = kal 80 | kn = kan 81 | ks = kas 82 | kr = kau 83 | kk = kaz 84 | km = khm 85 | ki = kik 86 | rw = kin 87 | ky = kir 88 | kv = kom 89 | kg = kon 90 | ko = kor 91 | kj = kua 92 | ku = kur 93 | lo = lao 94 | la = lat 95 | lv = lav 96 | li = lim 97 | ln = lin 98 | lt = lit 99 | lb = ltz 100 | lu = lub 101 | lg = lug 102 | mk = mac 103 | mh = mah 104 | ml = mal 105 | mi = mao 106 | mr = mar 107 | ms = may 108 | mg = mlg 109 | mt = mlt 110 | mn = mon 111 | na = nau 112 | nv = nav 113 | nr = nbl 114 | nd = nde 115 | ng = ndo 116 | ne = nep 117 | nn = nno 118 | nb = nob 119 | no = nor 120 | ny = nya 121 | oc = oci 122 | oj = oji 123 | or = ori 124 | om = orm 125 | os = oss 126 | pa = pan 127 | fa = per 128 | pi = pli 129 | pl = pol 130 | pt = por 131 | ps = pus 132 | qu = que 133 | rm = roh 134 | ro = rum 135 | rn = run 136 | ru = rus 137 | sg = sag 138 | sa = san 139 | si = sin 140 | sk = slo 141 | sl = slv 142 | se = sme 143 | sm = smo 144 | sn = sna 145 | sd = snd 146 | so = som 147 | st = sot 148 | es = spa 149 | sc = srd 150 | sr = srp 151 | ss = ssw 152 | su = sun 153 | sw = swa 154 | sv = swe 155 | ty = tah 156 | ta = tam 157 | tt = tat 158 | te = tel 159 | tg = tgk 160 | tl = tgl 161 | th = tha 162 | bo = tib 163 | ti = tir 164 | to = ton 165 | tn = tsn 166 | ts = tso 167 | tk = tuk 168 | tr = tur 169 | tw = twi 170 | ug = uig 171 | uk = ukr 172 | ur = urd 173 | uz = uzb 174 | ve = ven 175 | vi = vie 176 | vo = vol 177 | cy = wel 178 | wa = wln 179 | wo = wol 180 | xh = xho 181 | yi = yid 182 | yo = yor 183 | za = zha 184 | zu = zul 185 | -------------------------------------------------------------------------------- /transformations/metalib_ird.xsl: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | nai a22 ua 4500 15 | 16 | 17 | 18 | Database 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | Database Interface 30 | 31 | 32 | 33 | 34 | 35 | Database Guide 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | cr|||||||||||| 48 | 49 | uuuuuuuuuxx|||||o||||||||||||||| 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /src/RecordManager/Base/Splitter/AbstractBase.php: -------------------------------------------------------------------------------- 1 | 26 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 27 | * @link https://github.com/NatLibFi/RecordManager 28 | */ 29 | 30 | namespace RecordManager\Base\Splitter; 31 | 32 | use RecordManager\Base\Utils\MetadataUtils; 33 | 34 | /** 35 | * Splitter base class 36 | * 37 | * @category DataManagement 38 | * @package RecordManager 39 | * @author Ere Maijala 40 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 41 | * @link https://github.com/NatLibFi/RecordManager 42 | */ 43 | abstract class AbstractBase 44 | { 45 | /** 46 | * Metadata utilities 47 | * 48 | * @var MetadataUtils 49 | */ 50 | protected $metadataUtils; 51 | 52 | /** 53 | * Record count 54 | * 55 | * @var int 56 | */ 57 | protected $recordCount; 58 | 59 | /** 60 | * Current position 61 | * 62 | * @var int 63 | */ 64 | protected $currentPos; 65 | 66 | /** 67 | * Constructor 68 | * 69 | * @param MetadataUtils $metadataUtils Metadata utilities 70 | */ 71 | public function __construct(MetadataUtils $metadataUtils) 72 | { 73 | $this->metadataUtils = $metadataUtils; 74 | } 75 | 76 | /** 77 | * Initializer 78 | * 79 | * @param array $params Splitter configuration 80 | * 81 | * @return void 82 | */ 83 | public function init(array $params): void 84 | { 85 | } 86 | 87 | /** 88 | * Check whether EOF has been encountered 89 | * 90 | * @return bool 91 | */ 92 | public function getEOF() 93 | { 94 | return $this->currentPos >= $this->recordCount; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /tests/fixtures/Base/record/doaj1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | ger 4 | Verlag Krause und Pachernegg GmbH 5 | Journal für Mineralstoffwechsel 6 | 1023-7763 7 | 1680-9408 8 | 1998-01-01 9 | 5 10 | 1 11 | 25 12 | 29 13 | 648 14 | Leitfaden zur medikamentösen Standardtherapie in der Osteoporose 15 | 16 | 17 | Stevo Popovic 18 | 0 19 | https://orcid.org/0000-0001-1234-1234 20 | 21 | 22 | Dusko Bjelica 23 | 1 24 | 25 | 26 | Gabriela Doina Tanase 27 | 2 28 | https://orcid.org/0000-0001-1111-2222 29 | 30 | 31 | Rajko Milašinović 32 | 3 33 | 34 | 35 | 36 | University of Montenegro, Faculty for Sport and Physical Education, Nikšić, Montenegro 37 | University of Montenegro, Faculty for Sport and Physical Education, Nikšić, Montenegro 38 | University of Montenegro, Faculty for Sport and Physical Education, Nikšić, Montenegro 39 | University of Novi Sad, ACIMSR, Novi Sad, Serbia 40 | 41 | http://www.kup.at/kup/pdf/648.pdf 42 | 43 | Empfehlung 44 | Mineralstoffwechsel 45 | Osteoporose 46 | Richtlinie 47 | Therapie 48 | 49 | 50 | -------------------------------------------------------------------------------- /tests/RecordManagerTest/Base/Record/RecordTestBase.php: -------------------------------------------------------------------------------- 1 | 26 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 27 | * @link https://github.com/NatLibFi/RecordManager 28 | */ 29 | 30 | namespace RecordManagerTest\Base\Record; 31 | 32 | use RecordManagerTest\Base\Feature\FixtureTrait; 33 | 34 | use function array_key_exists; 35 | 36 | /** 37 | * Generic Record Driver Test Class 38 | * 39 | * @category DataManagement 40 | * @package RecordManager 41 | * @author Eero Heikkinen 42 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 43 | * @link https://github.com/NatLibFi/RecordManager 44 | */ 45 | abstract class RecordTestBase extends \PHPUnit\Framework\TestCase 46 | { 47 | use FixtureTrait; 48 | use CreateSampleRecordTrait; 49 | 50 | /** 51 | * Compare two arrays 52 | * 53 | * This makes any errors easier to understand than using assertEquals on the 54 | * arrays. 55 | * 56 | * @param array $expected Expected values 57 | * @param array $provided Provided values 58 | * @param string $method Method tested (for output messages) 59 | * 60 | * @return void 61 | */ 62 | protected function compareArray($expected, $provided, $method) 63 | { 64 | foreach ($expected as $key => $value) { 65 | $this->assertEquals( 66 | $value, 67 | $provided[$key] ?? null, 68 | "[$method] Compare expected field $key" 69 | ); 70 | } 71 | foreach ($provided as $key => $value) { 72 | $this->assertTrue( 73 | array_key_exists($key, $expected) !== false, 74 | "[$method] Unexpected field $key: " . var_export($value, true) 75 | ); 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /manage.php: -------------------------------------------------------------------------------- 1 | 25 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 26 | * @link https://github.com/NatLibFi/RecordManager 27 | */ 28 | require_once __DIR__ . '/cmdline.php'; 29 | 30 | convertOptions( 31 | [ 32 | 'func' => [ 33 | 'valueMap' => [ 34 | 'renormalize' => 'records:renormalize', 35 | 'deduplicate' => 'records:deduplicate', 36 | 'updatesolr' => 'solr:update-index', 37 | 'dump' => 'records:dump', 38 | 'dumpsolr' => 'solr:dump-records', 39 | 'markdeleted' => 'records:mark-deleted', 40 | 'deletesource' => 'records:delete-source', 41 | 'optimizesolr' => 'solr:optimize', 42 | 'count' => 'records:count', 43 | 'checkdedup' => 'records:check-dedup', 44 | 'checksolr' => 'solr:check-index', 45 | 'comparesolr' => 'solr:compare-records', 46 | 'purgedeleted' => 'records:purge-deleted', 47 | 'markforupdate' => 'records:mark-for-update', 48 | 'suppress' => 'records:suppress', 49 | 'unsuppress' => 'records:unsuppress', 50 | ] 51 | ], 52 | 'nocommit' => [ 53 | 'opt' => 'no-commit' 54 | ], 55 | 'field' => [ 56 | 'arg' => 1, 57 | ], 58 | 'lockfile' => [ 59 | 'opt' => 'lock' 60 | ], 61 | 'comparelog' => [ 62 | 'opt' => 'log' 63 | ], 64 | 'dumpprefix' => [ 65 | 'opt' => 'file-prefix' 66 | ], 67 | 'daystokeep' => [ 68 | 'opt' => 'days-to-keep' 69 | ], 70 | 'dateperserver' => [ 71 | 'opt' => 'date-per-server' 72 | ] 73 | ], 74 | ); 75 | 76 | include __DIR__ . '/console'; 77 | 78 | -------------------------------------------------------------------------------- /src/RecordManager/Base/Database/PDOResultIterator.php: -------------------------------------------------------------------------------- 1 | 26 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 27 | * @link https://github.com/NatLibFi/RecordManager 28 | */ 29 | 30 | namespace RecordManager\Base\Database; 31 | 32 | /** 33 | * PDO result iterator class that adds any attributes to each returned record 34 | * 35 | * @category DataManagement 36 | * @package RecordManager 37 | * @author Ere Maijala 38 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 39 | * @link https://github.com/NatLibFi/RecordManager 40 | * 41 | * @psalm-suppress MissingTemplateParam 42 | */ 43 | class PDOResultIterator extends \IteratorIterator 44 | { 45 | /** 46 | * Database 47 | * 48 | * @var PDODatabase 49 | */ 50 | protected $db; 51 | 52 | /** 53 | * Collection 54 | * 55 | * @var string 56 | */ 57 | protected $collection; 58 | 59 | /** 60 | * Constructor 61 | * 62 | * @param \Traversable $iterator Iterator 63 | * @param PDODatabase $db Database 64 | * @param string $collection Collection 65 | */ 66 | public function __construct( 67 | \Traversable $iterator, 68 | PDODatabase $db, 69 | string $collection 70 | ) { 71 | parent::__construct($iterator); 72 | 73 | $this->db = $db; 74 | $this->collection = $collection; 75 | } 76 | 77 | /** 78 | * Get the current value 79 | * 80 | * @return mixed 81 | */ 82 | #[\ReturnTypeWillChange] 83 | public function current() 84 | { 85 | $result = parent::current(); 86 | if ($result) { 87 | $result += $this->db->getRecordAttrs($this->collection, $result['_id']); 88 | } 89 | return $result; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/RecordManager/Base/Command/Records/Dump.php: -------------------------------------------------------------------------------- 1 | 26 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 27 | * @link https://github.com/NatLibFi/RecordManager 28 | */ 29 | 30 | namespace RecordManager\Base\Command\Records; 31 | 32 | use RecordManager\Base\Command\AbstractBase; 33 | use Symfony\Component\Console\Command\Command; 34 | use Symfony\Component\Console\Input\InputArgument; 35 | use Symfony\Component\Console\Input\InputInterface; 36 | use Symfony\Component\Console\Output\OutputInterface; 37 | 38 | /** 39 | * Dump a record 40 | * 41 | * @category DataManagement 42 | * @package RecordManager 43 | * @author Ere Maijala 44 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 45 | * @link https://github.com/NatLibFi/RecordManager 46 | */ 47 | class Dump extends AbstractBase 48 | { 49 | /** 50 | * Configure the command. 51 | * 52 | * @return void 53 | */ 54 | protected function configure() 55 | { 56 | $this 57 | ->setDescription('Dump a record from the database') 58 | ->setHelp('Dumps a single record from the database') 59 | ->addArgument( 60 | 'id', 61 | InputArgument::REQUIRED, 62 | 'Record id' 63 | ); 64 | } 65 | 66 | /** 67 | * Dump a single record to console 68 | * 69 | * @param InputInterface $input Console input 70 | * @param OutputInterface $output Console output 71 | * 72 | * @return int 0 if everything went fine, or an exit code 73 | */ 74 | protected function doExecute(InputInterface $input, OutputInterface $output) 75 | { 76 | $recordId = $input->getArgument('id'); 77 | if ($record = $this->db->getRecord($recordId)) { 78 | print_r($record); 79 | } 80 | return Command::SUCCESS; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/RecordManager/Base/Splitter/AbstractBaseFactory.php: -------------------------------------------------------------------------------- 1 | 26 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 27 | * @link https://github.com/NatLibFi/RecordManager 28 | */ 29 | 30 | namespace RecordManager\Base\Splitter; 31 | 32 | use Laminas\ServiceManager\Exception\ServiceNotCreatedException; 33 | use Laminas\ServiceManager\Exception\ServiceNotFoundException; 34 | use Psr\Container\ContainerExceptionInterface as ContainerException; 35 | use Psr\Container\ContainerInterface; 36 | 37 | /** 38 | * Splitter factory 39 | * 40 | * @category DataManagement 41 | * @package RecordManager 42 | * @author Ere Maijala 43 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 44 | * @link https://github.com/NatLibFi/RecordManager 45 | */ 46 | class AbstractBaseFactory implements \Laminas\ServiceManager\Factory\FactoryInterface 47 | { 48 | /** 49 | * Create an object 50 | * 51 | * @param ContainerInterface $container Service manager 52 | * @param string $requestedName Service being created 53 | * @param null|array $options Extra options (optional) 54 | * 55 | * @return object 56 | * 57 | * @throws ServiceNotFoundException if unable to resolve the service. 58 | * @throws ServiceNotCreatedException if an exception is raised when 59 | * creating a service. 60 | * @throws ContainerException&\Throwable if any other error occurs 61 | * 62 | * @SuppressWarnings(PHPMD.UnusedFormalParameter) 63 | * 64 | * @psalm-suppress UndefinedDocblockClass 65 | */ 66 | public function __invoke( 67 | ContainerInterface $container, 68 | $requestedName, 69 | ?array $options = null 70 | ) { 71 | return new $requestedName( 72 | $container->get(\RecordManager\Base\Utils\MetadataUtils::class) 73 | ); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /mappings/marc_format_to_hierarchy.map.sample: -------------------------------------------------------------------------------- 1 | Article = Journal/Article 2 | Atlas = Map/Atlas 3 | BachelorsThesis = Thesis/Bachelors 4 | BachelorsThesisPolytechnic = Thesis/BachelorsPolytechnic 5 | BluRay = Video/BluRay 6 | BoardGame = Game/BoardGame 7 | Book = Book/Book 8 | BookSection = Book/BookSection 9 | Braille = Book/Braille 10 | CD = Sound/CD 11 | CDROM = Other/CDROM 12 | Chart = Map/Map 13 | ChipCartridge = Other/ChipCartridge 14 | Collage = WorkOfArt/Collage 15 | Collection = Other/Collection 16 | ContinuouslyUpdatedResource = Other/ContinuouslyUpdatedResource 17 | Database = Database 18 | DVD = Video/DVD 19 | DVDROM = Other/DVDROM 20 | DVDAudio = Sound/DVDAudio 21 | DiscCartridge = Other/DiscCartridge 22 | Dissertation = Thesis/Thesis 23 | Drawing = WorkOfArt/Drawing 24 | Electronic = Other/Electronic 25 | Filmstrip = Image/Filmstrip 26 | FlashCard = Image/FlashCard 27 | FloppyDisk = Other/FloppyDisk 28 | Globe = Map/Globe 29 | Image = Image/Image 30 | Journal = Journal/Journal 31 | Kit = Other/Kit 32 | LaudaturThesis = Thesis/Laudatur 33 | LicentiateThesis = Thesis/Licentiate 34 | Manuscript = OtherText/Manuscript 35 | Map = Map/Map 36 | MastersThesis = Thesis/Masters 37 | MastersThesisPolytechnic = Thesis/MastersPolytechnic 38 | Microfilm = Other/Microfilm 39 | MotionPicture = Video/MotionPicture 40 | MusicRecording = Sound/MusicRecording 41 | MusicalScore = MusicalScore 42 | Newspaper = Journal/Newspaper 43 | NonmusicalCD = Sound/NonmusicalCD 44 | NonmusicalCassette = Sound/NonmusicalCassette 45 | NonmusicalDisc = Sound/NonmusicalDisc 46 | NonmusicalRecording = Sound/NonmusicalRecording 47 | NonmusicalRecordingOnline = Sound/NonmusicalRecordingOnline 48 | OnlineVideo = Video/Online 49 | Other = Other/Other 50 | Painting = WorkOfArt/Painting 51 | Photo = Image/Photo 52 | Photonegative = Image/Photonegative 53 | PhysicalObject = PhysicalObject 54 | Print = Other/Print 55 | ProGradu = Thesis/Gradu 56 | SensorImage = Image/SensorImage 57 | Serial = Journal/Serial 58 | Slide = Image/Slide 59 | Software = Other/Software 60 | SoundCassette = Sound/SoundCassette 61 | SoundDisc = Sound/SoundDisc 62 | SoundRecording = Sound/SoundRecording 63 | SoundRecordingOnline = Sound/SoundRecordingOnline 64 | SubUnit = Other/SubUnit 65 | TapeCartridge = Other/TapeCartridge 66 | TapeCassette = Other/TapeCassette 67 | TapeReel = Other/TapeReel 68 | TechnicalDrawing = Image/Drawing 69 | Thesis = Thesis/Other 70 | Transparency = Image/Transparency 71 | Video = Video/Video 72 | VideoCartridge = Video/VideoCartridge 73 | VideoCassette = Video/VideoCassette 74 | VideoCompilation = Video/Compilation 75 | VideoDisc = Video/VideoDisc 76 | VideoFeature = Video/Feature 77 | VideoGame = Game/VideoGame 78 | VideoReel = Video/VideoReel 79 | VideoShort = Video/Short 80 | eArticle = Journal/eArticle 81 | eBook = Book/eBook 82 | eBookSection = Book/eBookSection 83 | eJournal = Journal/eJournal 84 | eNewspaper = Journal/eNewspaper 85 | eSerial = Journal/eSerial 86 | -------------------------------------------------------------------------------- /src/RecordManager/Base/Utils/LoggerFactory.php: -------------------------------------------------------------------------------- 1 | 26 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 27 | * @link https://github.com/NatLibFi/RecordManager 28 | */ 29 | 30 | namespace RecordManager\Base\Utils; 31 | 32 | use Laminas\ServiceManager\Exception\ServiceNotCreatedException; 33 | use Laminas\ServiceManager\Exception\ServiceNotFoundException; 34 | use Psr\Container\ContainerExceptionInterface as ContainerException; 35 | use Psr\Container\ContainerInterface; 36 | 37 | /** 38 | * Logger Factory 39 | * 40 | * @category DataManagement 41 | * @package RecordManager 42 | * @author Ere Maijala 43 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 44 | * @link https://github.com/NatLibFi/RecordManager 45 | */ 46 | class LoggerFactory implements \Laminas\ServiceManager\Factory\FactoryInterface 47 | { 48 | /** 49 | * Create an object 50 | * 51 | * @param ContainerInterface $container Service manager 52 | * @param string $requestedName Service being created 53 | * @param null|array $options Extra options (optional) 54 | * 55 | * @return object 56 | * 57 | * @throws ServiceNotFoundException if unable to resolve the service. 58 | * @throws ServiceNotCreatedException if an exception is raised when 59 | * creating a service. 60 | * @throws ContainerException&\Throwable if any other error occurs 61 | * 62 | * @SuppressWarnings(PHPMD.UnusedFormalParameter) 63 | * 64 | * @psalm-suppress UndefinedDocblockClass 65 | */ 66 | public function __invoke( 67 | ContainerInterface $container, 68 | $requestedName, 69 | ?array $options = null 70 | ) { 71 | $configReader = $container->get(\RecordManager\Base\Settings\Ini::class); 72 | return new $requestedName($configReader->get('recordmanager.ini')); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/RecordManager/Base/Utils/WorkerPoolManagerFactory.php: -------------------------------------------------------------------------------- 1 | 26 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 27 | * @link https://github.com/NatLibFi/RecordManager 28 | */ 29 | 30 | namespace RecordManager\Base\Utils; 31 | 32 | use Laminas\ServiceManager\Exception\ServiceNotCreatedException; 33 | use Laminas\ServiceManager\Exception\ServiceNotFoundException; 34 | use Psr\Container\ContainerExceptionInterface as ContainerException; 35 | use Psr\Container\ContainerInterface; 36 | 37 | /** 38 | * WorkerPoolManager Factory 39 | * 40 | * @category DataManagement 41 | * @package RecordManager 42 | * @author Ere Maijala 43 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 44 | * @link https://github.com/NatLibFi/RecordManager 45 | */ 46 | class WorkerPoolManagerFactory implements \Laminas\ServiceManager\Factory\FactoryInterface 47 | { 48 | /** 49 | * Create an object 50 | * 51 | * @param ContainerInterface $container Service manager 52 | * @param string $requestedName Service being created 53 | * @param null|array $options Extra options (optional) 54 | * 55 | * @return object 56 | * 57 | * @throws ServiceNotFoundException if unable to resolve the service. 58 | * @throws ServiceNotCreatedException if an exception is raised when 59 | * creating a service. 60 | * @throws ContainerException&\Throwable if any other error occurs 61 | * 62 | * @SuppressWarnings(PHPMD.UnusedFormalParameter) 63 | * 64 | * @psalm-suppress UndefinedDocblockClass 65 | */ 66 | public function __invoke( 67 | ContainerInterface $container, 68 | $requestedName, 69 | ?array $options = null 70 | ) { 71 | return new $requestedName( 72 | $container->get(\RecordManager\Base\Utils\Logger::class) 73 | ); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/RecordManager/Base/ConsoleRunnerFactory.php: -------------------------------------------------------------------------------- 1 | 26 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 27 | * @link https://vufind.org/wiki/development Wiki 28 | */ 29 | 30 | namespace RecordManager\Base; 31 | 32 | use Laminas\ServiceManager\Exception\ServiceNotCreatedException; 33 | use Laminas\ServiceManager\Exception\ServiceNotFoundException; 34 | use Laminas\ServiceManager\Factory\FactoryInterface; 35 | use Psr\Container\ContainerExceptionInterface as ContainerException; 36 | use Psr\Container\ContainerInterface; 37 | 38 | /** 39 | * Console runner factory. 40 | * 41 | * @category VuFind 42 | * @package Console 43 | * @author Demian Katz 44 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 45 | * @link https://vufind.org/wiki/development Wiki 46 | */ 47 | class ConsoleRunnerFactory implements FactoryInterface 48 | { 49 | /** 50 | * Create an object 51 | * 52 | * @param ContainerInterface $container Service manager 53 | * @param string $requestedName Service being created 54 | * @param null|array $options Extra options (optional) 55 | * 56 | * @return object 57 | * 58 | * @throws ServiceNotFoundException if unable to resolve the service. 59 | * @throws ServiceNotCreatedException if an exception is raised when 60 | * creating a service. 61 | * @throws ContainerException&\Throwable if any other error occurs 62 | * 63 | * @psalm-suppress UndefinedDocblockClass 64 | */ 65 | public function __invoke( 66 | ContainerInterface $container, 67 | $requestedName, 68 | ?array $options = null 69 | ) { 70 | if (!empty($options)) { 71 | throw new \Exception('Unexpected options sent to factory.'); 72 | } 73 | return new $requestedName( 74 | $container->get(\RecordManager\Base\Command\PluginManager::class) 75 | ); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/RecordManager/Base/Http/HttpServiceFactory.php: -------------------------------------------------------------------------------- 1 | 26 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 27 | * @link https://github.com/NatLibFi/RecordManager 28 | */ 29 | 30 | namespace RecordManager\Base\Http; 31 | 32 | use Laminas\ServiceManager\Exception\ServiceNotCreatedException; 33 | use Laminas\ServiceManager\Exception\ServiceNotFoundException; 34 | use Psr\Container\ContainerExceptionInterface as ContainerException; 35 | use Psr\Container\ContainerInterface; 36 | 37 | /** 38 | * HTTP service factory 39 | * 40 | * @category DataManagement 41 | * @package RecordManager 42 | * @author Ere Maijala 43 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 44 | * @link https://github.com/NatLibFi/RecordManager 45 | */ 46 | class HttpServiceFactory implements \Laminas\ServiceManager\Factory\FactoryInterface 47 | { 48 | /** 49 | * Create an object 50 | * 51 | * @param ContainerInterface $container Service manager 52 | * @param string $requestedName Service being created 53 | * @param null|array $options Extra options (optional) 54 | * 55 | * @return object 56 | * 57 | * @throws ServiceNotFoundException if unable to resolve the service. 58 | * @throws ServiceNotCreatedException if an exception is raised when 59 | * creating a service. 60 | * @throws ContainerException&\Throwable if any other error occurs 61 | * 62 | * @SuppressWarnings(PHPMD.UnusedFormalParameter) 63 | * 64 | * @psalm-suppress UndefinedDocblockClass 65 | */ 66 | public function __invoke( 67 | ContainerInterface $container, 68 | $requestedName, 69 | ?array $options = null 70 | ) { 71 | $configReader = $container->get(\RecordManager\Base\Settings\Ini::class); 72 | 73 | return new $requestedName( 74 | $configReader->get('recordmanager.ini') 75 | ); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /.github/workflows/ci.yaml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | run-tests: 7 | name: Tests with PHP ${{ matrix.php-version }} 8 | runs-on: ubuntu-latest 9 | env: 10 | VUFIND_HOME: $GITHUB_WORKSPACE 11 | VUFIND_LOCAL_DIR: $GITHUB_WORKSPACE/local 12 | strategy: 13 | matrix: 14 | php-version: ['8.2', '8.3', '8.4', '8.4-no-mongo'] 15 | include: 16 | - php-version: 8.2 17 | phing_tasks: "qa-tasks" 18 | php-extensions: intl, xsl, mongodb 19 | - php-version: 8.3 20 | phing_tasks: "qa-tasks" 21 | php-extensions: intl, xsl, mongodb 22 | - php-version: 8.4 23 | phing_tasks: "qa-tasks" 24 | php-extensions: intl, xsl, mongodb 25 | - php-version: 8.4-no-mongo 26 | phing_tasks: "qa-tasks" 27 | php-extensions: intl, xsl 28 | 29 | steps: 30 | - name: Setup PHP 31 | uses: shivammathur/setup-php@v2 32 | with: 33 | php-version: ${{ matrix.php-version }} 34 | extensions: ${{ matrix.php-extensions }} 35 | 36 | - name: Checkout 37 | uses: actions/checkout@v4 38 | 39 | - name: Get composer cache directory 40 | id: composer-cache 41 | run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT 42 | 43 | - name: Cache composer dependencies 44 | uses: actions/cache@v4 45 | with: 46 | path: ${{ steps.composer-cache.outputs.dir }} 47 | key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} 48 | restore-keys: ${{ runner.os }}-composer- 49 | 50 | - name: Cache php-cs-fixer data 51 | uses: actions/cache@v4 52 | with: 53 | path: .php_cs_cache 54 | key: "php-${{ matrix.php-version }}-php-cs-fixer-${{ github.sha }}" 55 | restore-keys: "php-${{ matrix.php-version }}-php-cs-fixer-" 56 | 57 | - name: Cache php-stan data 58 | uses: actions/cache@v4 59 | with: 60 | path: .phpstan_cache 61 | key: "php-${{ matrix.php-version }}-phpstan-${{ github.sha }}" 62 | restore-keys: "php-${{ matrix.php-version }}-phpstan-" 63 | 64 | - name: Cache PHP_CodeSniffer data 65 | uses: actions/cache@v4 66 | with: 67 | path: tests/phpcs.cache.json 68 | key: "php-${{ matrix.php-version }}-phpcs-${{ github.sha }}" 69 | restore-keys: "php-${{ matrix.php-version }}-phpcs-" 70 | 71 | - name: Cache rector data 72 | uses: actions/cache@v4 73 | with: 74 | path: .rector 75 | key: "php-${{ matrix.php-version }}-rector-${{ github.sha }}" 76 | restore-keys: "php-${{ matrix.php-version }}-rector-" 77 | 78 | - name: Install composer dependencies 79 | run: composer install 80 | 81 | - name: Run tests 82 | run: PHP_CS_FIXER_IGNORE_ENV=1 vendor/bin/phing ${{ matrix.phing_tasks }} 83 | -------------------------------------------------------------------------------- /src/RecordManager/Base/Application.php: -------------------------------------------------------------------------------- 1 | 26 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 27 | * @link https://github.com/NatLibFi/RecordManager 28 | */ 29 | 30 | namespace RecordManager\Base; 31 | 32 | use Symfony\Component\Console\Application as ConsoleApplication; 33 | use Symfony\Component\Console\Input\InputDefinition; 34 | use Symfony\Component\Console\Input\InputOption; 35 | 36 | /** 37 | * RecordManager Application 38 | * 39 | * @category DataManagement 40 | * @package RecordManager 41 | * @author Ere Maijala 42 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 43 | * @link https://github.com/NatLibFi/RecordManager 44 | */ 45 | class Application extends ConsoleApplication 46 | { 47 | /** 48 | * Gets the default input definition. 49 | * 50 | * @return InputDefinition An InputDefinition instance 51 | */ 52 | protected function getDefaultInputDefinition(): InputDefinition 53 | { 54 | $result = parent::getDefaultInputDefinition(); 55 | $result->addOption( 56 | new InputOption( 57 | 'basepath', 58 | null, 59 | InputOption::VALUE_REQUIRED, 60 | 'Set base path for configuration files, mappings and' 61 | . ' transformations' 62 | ) 63 | ); 64 | $result->addOption( 65 | new InputOption( 66 | 'config.Section.parameter', 67 | null, 68 | InputOption::VALUE_REQUIRED, 69 | 'Override any configuration parameter in recordmanager.ini' 70 | ) 71 | ); 72 | $result->addOption( 73 | new InputOption( 74 | 'lock', 75 | null, 76 | InputOption::VALUE_OPTIONAL, 77 | 'Lock the process to prevent it from running multiple times in' 78 | . ' parallel', 79 | false 80 | ) 81 | ); 82 | return $result; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/RecordManager/Base/Utils/MetadataUtilsFactory.php: -------------------------------------------------------------------------------- 1 | 26 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 27 | * @link https://github.com/NatLibFi/RecordManager 28 | */ 29 | 30 | namespace RecordManager\Base\Utils; 31 | 32 | use Laminas\ServiceManager\Exception\ServiceNotCreatedException; 33 | use Laminas\ServiceManager\Exception\ServiceNotFoundException; 34 | use Psr\Container\ContainerExceptionInterface as ContainerException; 35 | use Psr\Container\ContainerInterface; 36 | 37 | /** 38 | * MetadataUtils Factory 39 | * 40 | * @category DataManagement 41 | * @package RecordManager 42 | * @author Ere Maijala 43 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 44 | * @link https://github.com/NatLibFi/RecordManager 45 | */ 46 | class MetadataUtilsFactory implements \Laminas\ServiceManager\Factory\FactoryInterface 47 | { 48 | /** 49 | * Create an object 50 | * 51 | * @param ContainerInterface $container Service manager 52 | * @param string $requestedName Service being created 53 | * @param null|array $options Extra options (optional) 54 | * 55 | * @return object 56 | * 57 | * @throws ServiceNotFoundException if unable to resolve the service. 58 | * @throws ServiceNotCreatedException if an exception is raised when 59 | * creating a service. 60 | * @throws ContainerException&\Throwable if any other error occurs 61 | * 62 | * @SuppressWarnings(PHPMD.UnusedFormalParameter) 63 | * 64 | * @psalm-suppress UndefinedDocblockClass 65 | */ 66 | public function __invoke( 67 | ContainerInterface $container, 68 | $requestedName, 69 | ?array $options = null 70 | ) { 71 | $configReader = $container->get(\RecordManager\Base\Settings\Ini::class); 72 | return new $requestedName( 73 | RECMAN_BASE_PATH, 74 | $configReader->get('recordmanager.ini'), 75 | $container->get(\RecordManager\Base\Utils\Logger::class) 76 | ); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/RecordManager/Base/Record/AbstractRecordFactory.php: -------------------------------------------------------------------------------- 1 | 26 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 27 | * @link https://github.com/NatLibFi/RecordManager 28 | */ 29 | 30 | namespace RecordManager\Base\Record; 31 | 32 | use Laminas\ServiceManager\Exception\ServiceNotCreatedException; 33 | use Laminas\ServiceManager\Exception\ServiceNotFoundException; 34 | use Psr\Container\ContainerExceptionInterface as ContainerException; 35 | use Psr\Container\ContainerInterface; 36 | 37 | /** 38 | * Record factory 39 | * 40 | * @category DataManagement 41 | * @package RecordManager 42 | * @author Ere Maijala 43 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 44 | * @link https://github.com/NatLibFi/RecordManager 45 | */ 46 | class AbstractRecordFactory implements \Laminas\ServiceManager\Factory\FactoryInterface 47 | { 48 | /** 49 | * Create an object 50 | * 51 | * @param ContainerInterface $container Service manager 52 | * @param string $requestedName Service being created 53 | * @param null|array $options Extra options (optional) 54 | * 55 | * @return object 56 | * 57 | * @throws ServiceNotFoundException if unable to resolve the service. 58 | * @throws ServiceNotCreatedException if an exception is raised when 59 | * creating a service. 60 | * @throws ContainerException&\Throwable if any other error occurs 61 | * 62 | * @SuppressWarnings(PHPMD.UnusedFormalParameter) 63 | * 64 | * @psalm-suppress UndefinedDocblockClass 65 | */ 66 | public function __invoke( 67 | ContainerInterface $container, 68 | $requestedName, 69 | ?array $options = null 70 | ) { 71 | $configReader = $container->get(\RecordManager\Base\Settings\Ini::class); 72 | 73 | return new $requestedName( 74 | $configReader->get('recordmanager.ini'), 75 | $configReader->get('datasources.ini'), 76 | $container->get(\RecordManager\Base\Utils\Logger::class), 77 | $container->get(\RecordManager\Base\Utils\MetadataUtils::class) 78 | ); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/RecordManager/Base/Utils/PerformanceCounter.php: -------------------------------------------------------------------------------- 1 | 26 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 27 | * @link https://github.com/NatLibFi/RecordManager 28 | */ 29 | 30 | namespace RecordManager\Base\Utils; 31 | 32 | use function count; 33 | 34 | /** 35 | * PerformanceCounter 36 | * 37 | * This class provides average speed estimation for different processes 38 | * 39 | * @category DataManagement 40 | * @package RecordManager 41 | * @author Ere Maijala 42 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 43 | * @link https://github.com/NatLibFi/RecordManager 44 | */ 45 | class PerformanceCounter 46 | { 47 | /** 48 | * Array of previous counts 49 | * 50 | * @var array 51 | */ 52 | protected $counts = []; 53 | 54 | /** 55 | * Constructor 56 | */ 57 | public function __construct() 58 | { 59 | $this->reset(); 60 | } 61 | 62 | /** 63 | * Reset counter 64 | * 65 | * @return void 66 | */ 67 | public function reset() 68 | { 69 | $this->counts = [['t' => microtime(true), 'c' => 0]]; 70 | } 71 | 72 | /** 73 | * Add the current count 74 | * 75 | * @param int $count Current progress 76 | * 77 | * @return void 78 | */ 79 | public function add($count) 80 | { 81 | $this->counts[] = ['t' => microtime(true), 'c' => $count]; 82 | if (count($this->counts) > 10) { 83 | array_shift($this->counts); 84 | } 85 | } 86 | 87 | /** 88 | * Get the speed as units / second 89 | * 90 | * @return int 91 | */ 92 | public function getSpeed() 93 | { 94 | if (count($this->counts) < 2) { 95 | return 0; 96 | } 97 | $first = $this->counts[0]; 98 | $last = end($this->counts); 99 | $count = $last['c'] - $first['c']; 100 | $time = $last['t'] - $first['t']; 101 | if ($time > 0) { 102 | return (int)round($count / $time); 103 | } 104 | return 0; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/RecordManager/Base/Database/AbstractDatabaseFactory.php: -------------------------------------------------------------------------------- 1 | 26 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 27 | * @link https://github.com/NatLibFi/RecordManager 28 | */ 29 | 30 | namespace RecordManager\Base\Database; 31 | 32 | use Laminas\ServiceManager\Exception\ServiceNotCreatedException; 33 | use Laminas\ServiceManager\Exception\ServiceNotFoundException; 34 | use Psr\Container\ContainerExceptionInterface as ContainerException; 35 | use Psr\Container\ContainerInterface; 36 | 37 | /** 38 | * Database factory 39 | * 40 | * @category DataManagement 41 | * @package RecordManager 42 | * @author Ere Maijala 43 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 44 | * @link https://github.com/NatLibFi/RecordManager 45 | */ 46 | class AbstractDatabaseFactory implements \Laminas\ServiceManager\Factory\FactoryInterface 47 | { 48 | /** 49 | * Create an object 50 | * 51 | * @param ContainerInterface $container Service manager 52 | * @param string $requestedName Service being created 53 | * @param null|array $options Extra options (optional) 54 | * 55 | * @return object 56 | * 57 | * @throws ServiceNotFoundException if unable to resolve the service. 58 | * @throws ServiceNotCreatedException if an exception is raised when 59 | * creating a service. 60 | * @throws ContainerException&\Throwable if any other error occurs 61 | * 62 | * @SuppressWarnings(PHPMD.UnusedFormalParameter) 63 | * 64 | * @psalm-suppress UndefinedDocblockClass 65 | */ 66 | public function __invoke( 67 | ContainerInterface $container, 68 | $requestedName, 69 | ?array $options = null 70 | ) { 71 | $configReader = $container->get(\RecordManager\Base\Settings\Ini::class); 72 | $config = $configReader->get('recordmanager.ini'); 73 | $backend = $config['Database']['backend'] ?? 'Mongo'; 74 | if (empty($config[$backend])) { 75 | throw new \Exception("Configuration section $backend missing"); 76 | } 77 | $dbClass = __NAMESPACE__ . '\\' . $backend . 'Database'; 78 | return new $dbClass($config[$backend]); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /tests/RecordManagerTest/Base/Record/EaccpfTest.php: -------------------------------------------------------------------------------- 1 | 26 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 27 | * @link https://github.com/NatLibFi/RecordManager 28 | */ 29 | 30 | namespace RecordManagerTest\Base\Record; 31 | 32 | use RecordManager\Base\Record\Eaccpf; 33 | 34 | /** 35 | * EAC-CPF Record Driver Test Class 36 | * 37 | * @category DataManagement 38 | * @package RecordManager 39 | * @author Minna Rönkä 40 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 41 | * @link https://github.com/NatLibFi/RecordManager 42 | */ 43 | class EaccpfTest extends RecordTestBase 44 | { 45 | /** 46 | * Test EAC-CPF record handling 47 | * 48 | * @return void 49 | */ 50 | public function testEaccpf1() 51 | { 52 | $record = $this->createRecord( 53 | Eaccpf::class, 54 | 'eaccpf1.xml', 55 | [], 56 | 'Base', 57 | [$this->createMock(\RecordManager\Base\Http\HttpService::class)] 58 | ); 59 | $fields = $record->toSolrArray(); 60 | unset($fields['fullrecord']); 61 | 62 | $expected = [ 63 | 'record_format' => 'eaccpf', 64 | 'allfields' => [ 65 | 'Kansallisarkisto', 66 | 'Tietoa kirjailijan elämästä', 67 | 'Sukunimi Etunimi', 68 | 'Toinensuku Toinennimi', 69 | ], 70 | 'source' => 'Kansallisarkisto', 71 | 'record_type' => 'person', 72 | 'heading' => 'Sukunimi Etunimi', 73 | 'use_for' => [ 74 | 'Toinensuku Toinennimi', 75 | ], 76 | 'birth_date' => '1950', 77 | 'death_date' => '2000', 78 | 'birth_place' => 'Tampere', 79 | 'death_place' => 'Joensuu', 80 | 'related_place' => [ 81 | 'Helsinki', 82 | 'Oulu', 83 | ], 84 | 'field_of_activity' => [], 85 | 'occupation' => [ 86 | 'runoilija', 87 | 'kirjailija', 88 | ], 89 | 'language' => 'fin', 90 | ]; 91 | 92 | $this->compareArray($expected, $fields, 'toSolrArray'); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /tests/fixtures/Base/Enrichment/skosmos_results.json: -------------------------------------------------------------------------------- 1 | { 2 | "http://www.yso.fi/onto/yso/p12345": { 3 | "_id": "http://www.yso.fi/onto/yso/p12345", 4 | "data": { 5 | "@context": { 6 | "skos": "http://www.w3.org/2004/02/skos/core#", 7 | "uri": "@id", 8 | "type": "@type", 9 | "lang": "@language", 10 | "value": "@value", 11 | "graph": "@graph", 12 | "prefLabel": "skos:prefLabel", 13 | "altLabel": "skos:altLabel" 14 | }, 15 | "graph": [ 16 | { 17 | "uri": "http://www.yso.fi/onto/yso/p12345", 18 | "type": "skos:Concept", 19 | "prefLabel": [ 20 | {"lang": "en", "value": "Enhanced Topic"}, 21 | {"lang": "sv", "value": "Förbättrat ämne"} 22 | ], 23 | "altLabel": [ 24 | {"lang": "en", "value": "Alternative Topic"} 25 | ] 26 | } 27 | ] 28 | } 29 | }, 30 | "http://www.yso.fi/onto/yso/p94426": { 31 | "_id": "http://www.yso.fi/onto/yso/p94426", 32 | "data": { 33 | "@context": { 34 | "skos": "http://www.w3.org/2004/02/skos/core#", 35 | "wgs84": "http://www.w3.org/2003/01/geo/wgs84_pos#", 36 | "uri": "@id", 37 | "type": "@type", 38 | "lang": "@language", 39 | "value": "@value", 40 | "graph": "@graph", 41 | "prefLabel": "skos:prefLabel" 42 | }, 43 | "graph": [ 44 | { 45 | "uri": "http://www.yso.fi/onto/yso/p94426", 46 | "type": "skos:Concept", 47 | "prefLabel": [ 48 | {"lang": "en", "value": "Helsinki"}, 49 | {"lang": "sv", "value": "Helsingfors"} 50 | ], 51 | "wgs84:lat": "60.1699", 52 | "wgs84:long": "24.9384" 53 | } 54 | ] 55 | } 56 | }, 57 | "http://www.yso.fi/onto/yso/p99999": { 58 | "_id": "http://www.yso.fi/onto/yso/p99999", 59 | "data": { 60 | "@context": { 61 | "skos": "http://www.w3.org/2004/02/skos/core#", 62 | "uri": "@id", 63 | "type": "@type", 64 | "lang": "@language", 65 | "value": "@value", 66 | "graph": "@graph", 67 | "prefLabel": "skos:prefLabel", 68 | "altLabel": "skos:altLabel" 69 | }, 70 | "graph": [ 71 | { 72 | "uri": "http://www.yso.fi/onto/yso/p99999", 73 | "type": "skos:Concept", 74 | "prefLabel": [ 75 | {"lang": "en", "value": "Enriched Author Name"} 76 | ], 77 | "altLabel": [ 78 | {"lang": "en", "value": "Author Variant"} 79 | ] 80 | } 81 | ] 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/RecordManager/Base/Harvest/AbstractBaseFactory.php: -------------------------------------------------------------------------------- 1 | 26 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 27 | * @link https://github.com/NatLibFi/RecordManager 28 | */ 29 | 30 | namespace RecordManager\Base\Harvest; 31 | 32 | use Laminas\ServiceManager\Exception\ServiceNotCreatedException; 33 | use Laminas\ServiceManager\Exception\ServiceNotFoundException; 34 | use Psr\Container\ContainerExceptionInterface as ContainerException; 35 | use Psr\Container\ContainerInterface; 36 | 37 | /** 38 | * Harvester factory 39 | * 40 | * @category DataManagement 41 | * @package RecordManager 42 | * @author Ere Maijala 43 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 44 | * @link https://github.com/NatLibFi/RecordManager 45 | */ 46 | class AbstractBaseFactory implements \Laminas\ServiceManager\Factory\FactoryInterface 47 | { 48 | /** 49 | * Create an object 50 | * 51 | * @param ContainerInterface $container Service manager 52 | * @param string $requestedName Service being created 53 | * @param null|array $options Extra options (optional) 54 | * 55 | * @return object 56 | * 57 | * @throws ServiceNotFoundException if unable to resolve the service. 58 | * @throws ServiceNotCreatedException if an exception is raised when 59 | * creating a service. 60 | * @throws ContainerException&\Throwable if any other error occurs 61 | * 62 | * @SuppressWarnings(PHPMD.UnusedFormalParameter) 63 | * 64 | * @psalm-suppress UndefinedDocblockClass 65 | */ 66 | public function __invoke( 67 | ContainerInterface $container, 68 | $requestedName, 69 | ?array $options = null 70 | ) { 71 | $configReader = $container->get(\RecordManager\Base\Settings\Ini::class); 72 | 73 | return new $requestedName( 74 | $configReader->get('recordmanager.ini'), 75 | $configReader->get('datasources.ini'), 76 | $container->get(\RecordManager\Base\Database\AbstractDatabase::class), 77 | $container->get(\RecordManager\Base\Utils\Logger::class), 78 | $container->get(\RecordManager\Base\Http\HttpService::class), 79 | $container->get(\RecordManager\Base\Utils\MetadataUtils::class) 80 | ); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/RecordManager/Base/Utils/FieldMapperFactory.php: -------------------------------------------------------------------------------- 1 | 26 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 27 | * @link https://github.com/NatLibFi/RecordManager 28 | */ 29 | 30 | namespace RecordManager\Base\Utils; 31 | 32 | use Laminas\ServiceManager\Exception\ServiceNotCreatedException; 33 | use Laminas\ServiceManager\Exception\ServiceNotFoundException; 34 | use Psr\Container\ContainerExceptionInterface as ContainerException; 35 | use Psr\Container\ContainerInterface; 36 | 37 | /** 38 | * Field mapper Factory 39 | * 40 | * @category DataManagement 41 | * @package RecordManager 42 | * @author Ere Maijala 43 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License 44 | * @link https://github.com/NatLibFi/RecordManager 45 | */ 46 | class FieldMapperFactory implements \Laminas\ServiceManager\Factory\FactoryInterface 47 | { 48 | /** 49 | * Create an object 50 | * 51 | * @param ContainerInterface $container Service manager 52 | * @param string $requestedName Service being created 53 | * @param null|array $options Extra options (optional) 54 | * 55 | * @return object 56 | * 57 | * @throws ServiceNotFoundException if unable to resolve the service. 58 | * @throws ServiceNotCreatedException if an exception is raised when 59 | * creating a service. 60 | * @throws ContainerException&\Throwable if any other error occurs 61 | * 62 | * @SuppressWarnings(PHPMD.UnusedFormalParameter) 63 | * 64 | * @psalm-suppress UndefinedDocblockClass 65 | */ 66 | public function __invoke( 67 | ContainerInterface $container, 68 | $requestedName, 69 | ?array $options = null 70 | ) { 71 | $configReader = $container->get(\RecordManager\Base\Settings\Ini::class); 72 | $config = $configReader->get('recordmanager.ini'); 73 | $className = !empty($config['Solr']['field_mapper']) ? 74 | $config['Solr']['field_mapper'] : $requestedName; 75 | 76 | return new $className( 77 | RECMAN_BASE_PATH, 78 | array_merge( 79 | $config['DefaultMappings'] ?? [], 80 | $config['Default Mappings'] ?? [] 81 | ), 82 | $configReader->get('datasources.ini') 83 | ); 84 | } 85 | } 86 | --------------------------------------------------------------------------------
This is a test EAD3 document for Skosmos enrichment testing.