diff --git a/app/Filesystem/WebDAVAdapter.php b/app/Filesystem/WebDAVAdapter.php new file mode 100644 index 000000000..c0be9fd66 --- /dev/null +++ b/app/Filesystem/WebDAVAdapter.php @@ -0,0 +1,18 @@ +encodePath($path); + return parent::lastModified($path); + } +} \ No newline at end of file diff --git a/app/Importers/AbstractImporter.php b/app/Importers/AbstractImporter.php index b46230fa6..49a4def53 100644 --- a/app/Importers/AbstractImporter.php +++ b/app/Importers/AbstractImporter.php @@ -263,7 +263,7 @@ protected function getJp2Files( return $this->iipFilesMap[$import_record] ->filter( fn(SplFileInfo $file) => preg_match( - sprintf('#^%s\.jp2$#', $image_filename_format), + sprintf('#^%s\.jp[2f]$#', $image_filename_format), $file->getBasename() ) ) diff --git a/app/Importers/MmpImporter.php b/app/Importers/MmpImporter.php new file mode 100644 index 000000000..cb567e1dc --- /dev/null +++ b/app/Importers/MmpImporter.php @@ -0,0 +1,150 @@ + 'Inventární číslo', + 'title' => 'Titul', + 'dating' => 'Datace vzniku', + 'inscription' => 'Signatura', + ]; + + protected $defaults = [ + 'gallery:sk' => 'Múzeum Prahy, MP', + 'gallery:cs' => 'Muzeum Prahy, MP', + ]; + + private array $workTypeTranslationKeys; + private array $techniqueTranslationKeys; + private array $mediumTranslationKeys; + private array $topicTranslationKeys; + + protected function init(): void + { + $this->sanitizers[] = function ($value) { + return empty_to_null(trim($value)); + }; + + $this->workTypeTranslationKeys = array_flip(trans('item.work_types', locale: 'cs')); + $this->techniqueTranslationKeys = array_flip(trans('item.techniques', locale: 'cs')); + $this->mediumTranslationKeys = array_flip(trans('item.media', locale: 'cs')); + $this->topicTranslationKeys = array_flip(trans('item.topics', locale: 'cs')); + } + + protected function getItemId(array $record): string + { + return str($record['Inventární číslo']) + ->swap([ + ' ' => '_', + '/' => '-', + ]) + ->prepend('CZE:MP.'); + } + + protected function getItemImageFilenameFormat(array $record): string + { + return str($record['Inventární číslo']) + ->replace('/', '_') + ->append('(-.*)?'); + } + + protected function hydrateAuthor(array $record): string + { + if ($record['Autor'] === 'Anonym') { + return 'Neznámy autor'; + } + + return str($record['Autor']) + ->trim() + ->replaceMatches('/(.*?) /', '$1, ', 1); + } + + protected function hydrateWorkType(array $record, string $locale): ?string + { + $replacements = [ + 'malba' => 'malířství', + ]; + + return str($record['Výtvarný druh']) + ->split('/\s*;\s*/') + ->map(fn (string $workType) => $replacements[$workType] ?? $workType) + ->when($locale !== 'cs', fn ($workTypes) => $workTypes->map(function (string $workType) use ($locale) { + $key = $this->workTypeTranslationKeys[$workType] ?? null; + return $key ? trans("item.work_types.$key", locale: $locale) : null; + })) + ->filter() + ->join('; ') ?: null; + } + + protected function hydrateTechnique(array $record, string $locale): ?string + { + if ($locale === 'cs') { + return $record['Technika']; + } + + return str($record['Technika']) + ->split('/\s*;\s*/') + ->map(function (string $technique) use ($locale) { + $key = $this->techniqueTranslationKeys[$technique] ?? null; + return $key ? trans("item.techniques.$key", locale: $locale) : null; + }) + ->filter() + ->join('; ') ?: null; + } + + protected function hydrateMedium(array $record, string $locale): ?string + { + if ($locale === 'cs') { + return $record['Materiál']; + } + + return str($record['Materiál']) + ->split('/\s*;\s*/') + ->map(function (string $medium) use ($locale) { + $key = $this->mediumTranslationKeys[$medium] ?? null; + return $key ? trans("item.media.$key", locale: $locale) : null; + }) + ->filter() + ->join('; ') ?: null; + } + + protected function hydrateTopic(array $record, string $locale): ?string + { + if ($locale === 'cs') { + return $record['Námět/téma']; + } + + return str($record['Námět/téma']) + ->split('/\s*;\s*/') + ->map(function (string $topic) use ($locale) { + $key = $this->topicTranslationKeys[$topic] ?? null; + return $key ? trans("item.topics.$key", locale: $locale) : null; + }) + ->filter() + ->join('; ') ?: null; + } + + protected function hydrateMeasurement(array $record, $locale): ?string + { + if (empty($record['Rozměr'])) { + return null; + } + + $replacements = trans('item.measurement_replacements', [], $locale); + return strtr($record['Rozměr'], $replacements); + } + + protected function hydrateDateEarliest(array $record): int + { + return Date::createFromFormat('d.m.Y', $record['(n) Datace OD'])->year; + } + + protected function hydrateDateLatest(array $record): int + { + return Date::createFromFormat('d.m.Y', $record['(n) Datace DO'])->year; + } +} \ No newline at end of file diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 243d63348..e58cfe713 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -1,5 +1,6 @@ [ - 'a' => 'výška hlavní části', - 'a.' => 'výška hlavní části', - 'b' => 'výška vedlejší části', - 'b.' => 'výška vedlejší části', - 'čas' => 'čas', - 'd' => 'délka', - 'd.' => 'délka', - 'h' => 'hloubka/tloušťka', - 'h.' => 'hloubka/tloušťka', - 'hmot' => 'hmotnost', - 'hmot.' => 'hmotnost', - 'hr' => 'hloubka s rámem', - 'jiný' => 'jiný nespecifikovaný', - 'p' => 'průměr/ráže', - 'p.' => 'průměr/ráže', - 'r.' => 'ráže', - 'ryz' => 'ryzost', - 's' => 'šířka', - 's.' => 'šířka', - 'sd.' => 'šířka grafické desky', - 'sp' => 'šířka s paspartou', - 'sp.' => 'šířka s paspartou', - 'sr' => 'šířka s rámem', - 'v' => 'celková výška/délka', - 'v.' => 'celková výška/délka', - 'vd.' => 'výška grafické desky', - 'vp' => 'výška s paspartou', - 'vp.' => 'výška s paspartou', - 'vr' => 'výška s rámem', - '=' => ' ', + 'a=' => 'výška hlavní části ', + 'a.=' => 'výška hlavní části ', + 'b=' => 'výška vedlejší části ', + 'b.=' => 'výška vedlejší části ', + 'čas=' => 'čas ', + 'd=' => 'délka ', + 'd.=' => 'délka ', + 'h=' => 'hloubka/tloušťka ', + 'h.=' => 'hloubka/tloušťka ', + 'hmot=' => 'hmotnost ', + 'hmot.=' => 'hmotnost ', + 'hr=' => 'hloubka s rámem ', + 'jiný=' => 'jiný nespecifikovaný ', + 'p=' => 'průměr/ráže ', + 'p.=' => 'průměr/ráže ', + 'r.=' => 'ráže ', + 'ryz=' => 'ryzost ', + 's=' => 'šířka ', + 's.=' => 'šířka ', + 'sd.=' => 'šířka grafické desky ', + 'sp=' => 'šířka s paspartou ', + 'sp.=' => 'šířka s paspartou ', + 'sr=' => 'šířka s rámem ', + 'v=' => 'celková výška/délka ', + 'v.=' => 'celková výška/délka ', + 'vd.=' => 'výška grafické desky ', + 'vp=' => 'výška s paspartou ', + 'vp.=' => 'výška s paspartou ', + 'vr=' => 'výška s rámem ', + 'rv.=' => 'výška s rámem ', + 'rš.=' => 'šířka s rámem ', + 'v-cm=' => 'výška ', + 'š-cm=' => 'šířka ', ], 'untitled' => 'bez názvu', 'authority_roles' => [ diff --git a/lang/en/item.php b/lang/en/item.php index 486ab7b7a..3ed00cc25 100644 --- a/lang/en/item.php +++ b/lang/en/item.php @@ -105,36 +105,39 @@ ], ], 'measurement_replacements' => [ - 'a' => 'height of the main part', - 'a.' => 'height of the main part', - 'b' => 'height of the secondary part', - 'b.' => 'height of the secondary part', - 'čas' => 'time', - 'd' => 'length', - 'd.' => 'length', - 'h' => 'depth/thickness', - 'h.' => 'depth/thickness', - 'hmot' => 'mass', - 'hmot.' => 'mass', - 'hr' => 'depth with frame', - 'jiný' => 'other, unspecified', - 'p' => 'diameter, calibre/gauge', - 'p.' => 'diameter, calibre/gauge', - 'r.' => 'calibre/gauge', - 'ryz' => 'purity', - 's' => 'width', - 's.' => 'width', - 'sd.' => 'width of the printing plate', - 'sp' => 'width with mount', - 'sp.' => 'width with mount', - 'sr' => 'width with frame', - 'v' => 'overall height/length', - 'v.' => 'overall height/length', - 'vd.' => 'height of the printing plate', - 'vp' => 'height with mount', - 'vp.' => 'height with mount', - 'vr' => 'height with frame', - '=' => ' ', + 'a=' => 'height of the main part ', + 'a.=' => 'height of the main part ', + 'b=' => 'height of the secondary part ', + 'b.=' => 'height of the secondary part ', + 'čas=' => 'time ', + 'd=' => 'length ', + 'd.=' => 'length ', + 'h=' => 'depth/thickness ', + 'h.=' => 'depth/thickness ', + 'hmot=' => 'mass ', + 'hmot.=' => 'mass ', + 'hr=' => 'depth with frame ', + 'jiný=' => 'other, unspecified ', + 'p=' => 'diameter, calibre/gauge ', + 'p.=' => 'diameter, calibre/gauge ', + 'r.=' => 'calibre/gauge ', + 'ryz=' => 'purity ', + 's=' => 'width ', + 's.=' => 'width ', + 'sd.=' => 'width of the printing plate ', + 'sp=' => 'width with mount ', + 'sp.=' => 'width with mount ', + 'sr=' => 'width with frame ', + 'v=' => 'overall height/length ', + 'v.=' => 'overall height/length ', + 'vd.=' => 'height of the printing plate ', + 'vp=' => 'height with mount ', + 'vp.=' => 'height with mount ', + 'vr=' => 'height with frame ', + 'rv.=' => 'height with frame ', + 'rš.=' => 'width with frame ', + 'v-cm=' => 'height ', + 'š-cm=' => 'width ', ], 'untitled' => 'untitled', 'authority_roles' => [ diff --git a/lang/sk/item.php b/lang/sk/item.php index f15b18ba6..af7bd02f2 100644 --- a/lang/sk/item.php +++ b/lang/sk/item.php @@ -105,36 +105,39 @@ ], ], 'measurement_replacements' => [ - 'a' => 'výška hlavnej časti', - 'a.' => 'výška hlavnej časti', - 'b' => 'výška vedľajšej časti', - 'b.' => 'výška vedľajšej časti', - 'čas' => 'čas', - 'd' => 'dĺžka', - 'd.' => 'dĺžka', - 'h' => 'hĺbka/hrúbka', - 'h.' => 'hĺbka/hrúbka', - 'hmot' => 'hmotnosť', - 'hmot.' => 'hmotnosť', - 'hr' => 'hĺbka s rámom', - 'jiný' => 'nešpecifikované', - 'p' => 'priemer', - 'p.' => 'priemer', - 'r.' => 'ráž', - 'ryz' => 'rýdzosť', - 's' => 'šírka', - 's.' => 'šírka', - 'sd.' => 'šírka grafickej plochy', - 'sp' => 'šírka s paspartou', - 'sp.' => 'šírka s paspartou', - 'sr' => 'šírka s rámom', - 'v' => 'celková výška/dĺžka', - 'v.' => 'celková výška/dĺžka', - 'vd.' => 'výška grafickej dosky', - 'vp' => 'výška s paspartou', - 'vp.' => 'výška s paspartou', - 'vr' => 'výška s rámom', - '=' => ' ', + 'a=' => 'výška hlavnej časti ', + 'a.=' => 'výška hlavnej časti ', + 'b=' => 'výška vedľajšej časti ', + 'b.=' => 'výška vedľajšej časti ', + 'čas=' => 'čas ', + 'd=' => 'dĺžka ', + 'd.=' => 'dĺžka ', + 'h=' => 'hĺbka/hrúbka ', + 'h.=' => 'hĺbka/hrúbka ', + 'hmot=' => 'hmotnosť ', + 'hmot.=' => 'hmotnosť ', + 'hr=' => 'hĺbka s rámom' , + 'jiný=' => 'nešpecifikované ', + 'p=' => 'priemer ', + 'p.=' => 'priemer ', + 'r.=' => 'ráž ', + 'ryz=' => 'rýdzosť ', + 's=' => 'šírka ', + 's.=' => 'šírka ', + 'sd.=' => 'šírka grafickej plochy ', + 'sp=' => 'šírka s paspartou ', + 'sp.=' => 'šírka s paspartou ', + 'sr=' => 'šírka s rámom ', + 'v=' => 'celková výška/dĺžka ', + 'v.=' => 'celková výška/dĺžka ', + 'vd.=' => 'výška grafickej dosky ', + 'vp=' => 'výška s paspartou ', + 'vp.=' => 'výška s paspartou ', + 'vr=' => 'výška s rámom ', + 'rv.=' => 'výška s rámom ', + 'rš.=' => 'šírka s rámom ', + 'v-cm=' => 'výška ', + 'š-cm=' => 'šírka ', ], 'untitled' => 'bez názvu', 'authority_roles' => [ diff --git a/tests/Importers/MmpImporterTest.php b/tests/Importers/MmpImporterTest.php new file mode 100644 index 000000000..8f7fa329e --- /dev/null +++ b/tests/Importers/MmpImporterTest.php @@ -0,0 +1,96 @@ +repositoryMock = $this->createMock(CsvRepository::class); + $this->importer = new MmpImporter( + app(AuthorityMatcher::class), + $this->repositoryMock, + app(Translator::class) + ); + } + + public function testImport() + { + $this->importData(); + + $item = Item::find('CZE:MP.H_014_487'); + + $this->assertEquals('H 014 487', $item->identifier); + $this->assertEquals('Beisch, Josef Antonín', $item->author); + $this->assertEquals(1701, $item->date_earliest); + $this->assertEquals(1800, $item->date_latest); + $this->assertEquals('Panna Marie Karlovská', $item->title); + $this->assertEquals('počátek 18.stol.', $item->dating); + $this->assertEquals('maliarstvo', $item->translate('sk')->work_type); + $this->assertEquals('malířství', $item->translate('cs')->work_type); + $this->assertEquals('painting', $item->translate('en')->work_type); + $this->assertEquals('olej', $item->translate('sk')->technique); + $this->assertEquals('olej', $item->translate('cs')->technique); + $this->assertEquals('oil', $item->translate('en')->technique); + $this->assertEquals('drevo', $item->translate('sk')->medium); + $this->assertEquals('dřevo', $item->translate('cs')->medium); + $this->assertEquals('wood', $item->translate('en')->medium); + $this->assertEquals(null, $item->translate('sk')->topic); + $this->assertEquals('obraz náboženský', $item->translate('cs')->topic); + $this->assertEquals(null, $item->translate('en')->topic); + $this->assertEquals('výška s rámom 31cm; šírka s rámom 21,5cm; výška 24,5cm; šírka 14,5cm', $item->translate('sk')->measurement); + $this->assertEquals('výška s rámem 31cm; šířka s rámem 21,5cm; výška 24,5cm; šířka 14,5cm', $item->translate('cs')->measurement); + $this->assertEquals('height with frame 31cm; width with frame 21,5cm; height 24,5cm; width 14,5cm', $item->translate('en')->measurement); + } + + private function importData(array $data = []): ImportRecord + { + $data = $this->fakeData($data); + + $this->repositoryMock->method('getFiltered')->willReturn(new \ArrayIterator([$data])); + + $importRecord = ImportRecord::factory() + ->for(Import::factory()) + ->create(); + $this->importer->import($importRecord, stream: null); + return $importRecord; + } + + private function fakeData(array $overrides = []): array + { + return $overrides + [ + "Řada" => "H", + "Inventární číslo" => "H 014 487", + "Titul" => "Panna Marie Karlovská", + "Autor" => "Beisch Josef Antonín", + "Datace vzniku" => "počátek 18.stol.", + "(n) Datace OD" => "1.1.1701", + "(n) Datace DO" => "31.12.1800", + "Výtvarný druh" => "malba", + "Materiál" => "dřevo", + "Technika" => "olej", + "Rozměr" => "rv.=31cm; rš.=21,5cm; v-cm=24,5cm; š-cm=14,5cm", + "Námět/téma" => "obraz náboženský", + "Signatura" => "", + ]; + } +} \ No newline at end of file