diff --git a/app/Importers/AbstractMgImporter.php b/app/Importers/AbstractMgImporter.php new file mode 100644 index 000000000..b7330e611 --- /dev/null +++ b/app/Importers/AbstractMgImporter.php @@ -0,0 +1,75 @@ + ';', + 'enclosure' => '"', + 'escape' => '\\', + 'newline' => "\r\n", + 'input_encoding' => 'CP1250', + ]; + + protected $defaults = [ + 'author' => 'neurčený autor', // todo translatable author + 'gallery:sk' => 'Moravská galerie, MG', + 'gallery:cs' => 'Moravská galerie, MG', + ]; + + protected array $mediumTranslationKeys; + protected array $techniqueTranslationKeys; + protected array $workTypeTranslationKeys; + protected array $topicTranslationKeys; + + protected function init(): void + { + $this->filters[] = function (array $record) { + return $record['Plus2T'] != 'ODPIS'; + }; + + $this->sanitizers[] = function ($value) { + return empty_to_null($value); + }; + + $this->mediumTranslationKeys = array_flip(trans('item.media', locale: 'cs')); + $this->techniqueTranslationKeys = array_flip(trans('item.techniques', locale: 'cs')); + $this->workTypeTranslationKeys = array_flip(trans('item.work_types', locale: 'cs')); + $this->topicTranslationKeys = array_flip(trans('item.topics', locale: 'cs')); + } + + protected function getItemId(array $record): string + { + $id = sprintf('CZE:MG.%s_%s', $record['Rada_S'], (int) $record['PorC_S']); + if ($record['Lomeni_S'] != '_') { + $id = sprintf('%s-%s', $id, $record['Lomeni_S']); + } + + return $id; + } + + protected function getItemImageFilenameFormat(array $record): string + { + $filename = sprintf( + '%s%s', + $record['Rada_S'], + str_pad($record['PorC_S'], 6, '0', STR_PAD_LEFT) + ); + if ($record['Lomeni_S'] != '_') { + $filename = sprintf('%s-%s', $filename, $record['Lomeni_S']); + } + + return sprintf('%s(_.*)?', preg_quote($filename)); + } + + protected function hydrateIdentifier(array $record): string + { + $identifier = sprintf('%s %s', $record['Rada_S'], (int) $record['PorC_S']); + if ($record['Lomeni_S'] != '_') { + $identifier = sprintf('%s/%s', $identifier, $record['Lomeni_S']); + } + + return $identifier; + } +} diff --git a/app/Importers/MgFotoImporter.php b/app/Importers/MgFotoImporter.php new file mode 100644 index 000000000..5111749e6 --- /dev/null +++ b/app/Importers/MgFotoImporter.php @@ -0,0 +1,138 @@ + 'RokVzOd', + 'date_latest' => 'RokVzDo', + 'acquisition_date' => 'RokAkv', + 'author' => 'Autor', + 'dating:sk' => 'DatVz', + 'dating:cs' => 'DatVz', + // 'location:sk' => 'AktLokace', todo + // 'location:cs' => 'AktLokace', todo + 'description:sk' => 'Popis', + 'description:cs' => 'Popis', + ]; + + protected array $surfaces = [ + 'J' => 'jiný', + 'L' => 'lesklý', + 'M' => 'matný', + 'P' => 'polomatný', + 'R' => 'rastr', + 'V' => 'velvet', + ]; + + protected array $zooms = [ + 'K' => 'kontakt fotografie', + 'M' => 'zmenšenina fotografie', + 'V' => 'zväčšenina fotografie', + ]; + + protected array $colors = [ + 'B' => 'farebná fotografia', + 'C' => 'čiernobiela fotografia', + 'CK' => 'kolorováno fotografie', + 'CP' => 'pastelový papier fotografia', + 'CT' => 'tónovaná fotografia', + 'CTK' => 'tónovaná, kolorovaná fotografia', + 'J' => 'iná fotografia', + ]; + + protected array $stateEditions = [ + 'K' => 'kópia', + 'N' => 'neznámy', + 'O' => 'originál', + 'P' => 'reprodukcia', + ]; + + protected function hydrateTitle(array $record, string $locale): ?string + { + if ($record['Název'] !== null) { + return in_array($locale, ['sk', 'cs']) ? $record['Název'] : null; + } elseif ($record['Předmět'] !== null) { + return in_array($locale, ['sk', 'cs']) ? $record['Předmět'] : null; + } else { + return $this->translator->get('item.untitled', locale: $locale); + } + } + + protected function hydrateStateEdition(array $record, string $locale): ?string + { + if ($record['Původnost'] === null) { + return null; + } + + $key = $this->stateEditions[$record['Původnost']]; + return trans("item.state_editions.$key", locale: $locale); + } + + protected function hydrateMedium(array $record, string $locale): ?string + { + $medium = $record['Materiál']; + if ($record['Povrch'] !== null) { + $medium .= Item::TREE_DELIMITER . $this->surfaces[$record['Povrch']]; + } + + if ($locale === 'cs') { + return $medium; + } + + $key = $this->mediumTranslationKeys[$medium] ?? null; + return $key ? trans("item.media.$key", locale: $locale) : null; + } + + protected function hydrateTechnique(array $record, string $locale): ?string + { + $techniques = collect(); + if ($record['Zoom'] !== null) { + $key = $this->zooms[$record['Zoom']]; + $techniques[] = trans("item.techniques.$key", locale: $locale); + } + + if ($record['Barva'] !== null) { + $key = $this->colors[$record['Barva']]; + $techniques[] = trans("item.techniques.$key", locale: $locale); + } + + return $techniques->join('; ') ?: null; + } + + protected function hydrateWorkType(array $record, string $locale): ?string + { + $workType = 'fotografie'; + if ($record['Předmět'] !== null) { + $workType .= Item::TREE_DELIMITER . $record['Předmět']; + } + + if ($locale === 'cs') { + return $workType; + } + + $key = $this->workTypeTranslationKeys[$workType] ?? null; + return $key ? trans("item.work_types.$key", locale: $locale) : null; + } + + protected function hydrateRelationshipType(array $record, string $locale): ?string + { + if ($record['Okolnosti'] === 'Archiv negativů Dagmar Hochové') { + return trans('importer.mg.relationship_type.from_set', locale: $locale); + } + + return null; + } + + protected function hydrateRelatedWork(array $record, string $locale): ?string + { + if ($record['Okolnosti'] === 'Archiv negativů Dagmar Hochové') { + return trans('importer.mg.related_work.dagmar_hochova', locale: $locale); + } + + return null; + } +} diff --git a/app/Importers/MgImporter.php b/app/Importers/MgImporter.php index 7f9b9ecd4..835cb740b 100644 --- a/app/Importers/MgImporter.php +++ b/app/Importers/MgImporter.php @@ -4,16 +4,8 @@ use App\Item; -class MgImporter extends AbstractImporter +class MgImporter extends AbstractMgImporter { - protected static $options = [ - 'delimiter' => ';', - 'enclosure' => '"', - 'escape' => '\\', - 'newline' => "\r\n", - 'input_encoding' => 'CP1250', - ]; - protected $mapping = [ 'date_earliest' => 'RokOd', 'date_latest' => 'Do', @@ -29,12 +21,6 @@ class MgImporter extends AbstractImporter 'state_edition:cs' => 'Původnost', ]; - protected $defaults = [ - 'author' => 'neurčený autor', // todo translatable author - 'gallery:sk' => 'Moravská galerie, MG', - 'gallery:cs' => 'Moravská galerie, MG', - ]; - protected array $workTypes = [ 'Ar' => 'architektura', 'Bi' => 'bibliofilie a staré tisky', @@ -53,61 +39,6 @@ class MgImporter extends AbstractImporter 'Te' => 'textil', ]; - protected array $mediumTranslationKeys; - protected array $techniqueTranslationKeys; - protected array $workTypeTranslationKeys; - protected array $topicTranslationKeys; - - protected function init(): void - { - $this->filters[] = function (array $record) { - return $record['Plus2T'] != 'ODPIS'; - }; - - $this->sanitizers[] = function ($value) { - return empty_to_null($value); - }; - - $this->mediumTranslationKeys = array_flip(trans('item.media', locale: 'cs')); - $this->techniqueTranslationKeys = array_flip(trans('item.techniques', locale: 'cs')); - $this->workTypeTranslationKeys = array_flip(trans('item.work_types', locale: 'cs')); - $this->topicTranslationKeys = array_flip(trans('item.topics', locale: 'cs')); - } - - protected function getItemId(array $record): string - { - $id = sprintf('CZE:MG.%s_%s', $record['Rada_S'], (int) $record['PorC_S']); - if ($record['Lomeni_S'] != '_') { - $id = sprintf('%s-%s', $id, $record['Lomeni_S']); - } - - return $id; - } - - protected function getItemImageFilenameFormat(array $record): string - { - $filename = sprintf( - '%s%s', - $record['Rada_S'], - str_pad($record['PorC_S'], 6, '0', STR_PAD_LEFT) - ); - if ($record['Lomeni_S'] != '_') { - $filename = sprintf('%s-%s', $filename, $record['Lomeni_S']); - } - - return sprintf('%s(_.*)?', preg_quote($filename)); - } - - protected function hydrateIdentifier(array $record): string - { - $identifier = sprintf('%s %s', $record['Rada_S'], (int) $record['PorC_S']); - if ($record['Lomeni_S'] != '_') { - $identifier = sprintf('%s/%s', $identifier, $record['Lomeni_S']); - } - - return $identifier; - } - protected function hydrateTitle(array $record, string $locale): ?string { if ($record['Titul'] !== null) { diff --git a/lang/cs/importer.php b/lang/cs/importer.php index e87b02835..de491970f 100644 --- a/lang/cs/importer.php +++ b/lang/cs/importer.php @@ -43,6 +43,7 @@ 'related_work' => [ 'biennal_brno' => 'Bienále Brno', 'jv' => 'Archiv a sbírka Jiřího Valocha', + 'dagmar_hochova' => 'Archiv negativů Dagmar Hochové', ], ], ]; diff --git a/lang/cs/item.php b/lang/cs/item.php index c9f936464..24d062944 100644 --- a/lang/cs/item.php +++ b/lang/cs/item.php @@ -151,8 +151,24 @@ 'techniques' => [ 'akvarel' => 'akvarel', 'akvarel/čierny' => 'akvarel/černý', + 'farebná fotografia' => 'barvená fotografie', + 'iná fotografia' => 'jiná fotografie', + 'kolorovaná fotografia' => 'kolorovaná fotografie', + 'kontakt fotografie' => 'kontakt fotografie', + 'pastelový papier fotografia' => 'pastelový papír fotografie', + 'tónovaná fotografia' => 'tónovaná fotografie', + 'tónovaná, kolorovaná fotografia' => 'tónovaná, kolorovaná fotografie', + 'zmenšenina fotografie' => 'zmenšenina fotografie', + 'zväčšenina fotografie' => 'zvětšenina fotografie', + 'čiernobiela fotografia' => 'černobílá fotografie', ], 'topics' => [ 'figurálna kompozícia' => 'figurální kompozice', ], + 'state_editions' => [ + 'kópia' => 'kopie', + 'neznámy' => 'neznámý', + 'originál' => 'originál', + 'reprodukcia' => 'reprodukce', + ], ]; diff --git a/lang/en/importer.php b/lang/en/importer.php index 38944e7ea..4766273dc 100644 --- a/lang/en/importer.php +++ b/lang/en/importer.php @@ -163,6 +163,7 @@ 'related_work' => [ 'biennal_brno' => 'Biennal Brno', 'jv' => 'Archive and collection of Jiří Valoch', + 'dagmar_hochova' => 'Archive of negatives of Dagmar Hochová', ], ], ]; diff --git a/lang/en/item.php b/lang/en/item.php index 41de57789..9a00595c5 100644 --- a/lang/en/item.php +++ b/lang/en/item.php @@ -152,4 +152,10 @@ 'topics' => [ 'figurálna kompozícia' => 'figurative composition', ], + 'state_editions' => [ + 'kópia' => 'copy', + 'neznámy' => 'unknown', + 'originál' => 'original', + 'reprodukcia' => 'reproduction', + ], ]; diff --git a/lang/sk/importer.php b/lang/sk/importer.php index e7bfe2e7b..faed7d56e 100644 --- a/lang/sk/importer.php +++ b/lang/sk/importer.php @@ -204,6 +204,7 @@ 'related_work' => [ 'biennal_brno' => 'Bienále Brno', 'jv' => 'Archív a zbierka Jiřího Valocha', + 'dagmar_hochova' => 'Archív negatívov Dagmar Hochovej', ], ], ]; diff --git a/lang/sk/item.php b/lang/sk/item.php index 2bce1cc9d..d1ad66657 100644 --- a/lang/sk/item.php +++ b/lang/sk/item.php @@ -148,8 +148,24 @@ 'techniques' => [ 'akvarel' => 'akvarel', 'akvarel/čierny' => 'akvarel/čierny', + 'farebná fotografia' => 'farebná fotografia', + 'iná fotografia' => 'iná fotografia', + 'kolorovaná fotografia' => 'kolorovaná fotografia', + 'kontakt fotografie' => 'kontakt fotografie', + 'pastelový papier fotografia' => 'pastelový papier fotografia', + 'tónovaná fotografia' => 'tónovaná fotografia', + 'tónovaná, kolorovaná fotografia' => 'tónovaná, kolorovaná fotografia', + 'zmenšenina fotografie' => 'zmenšenina fotografie', + 'zväčšenina fotografie' => 'zväčšenina fotografie', + 'čiernobiela fotografia' => 'čiernobiela fotografia', ], 'topics' => [ 'figurálna kompozícia' => 'figurálna kompozícia', ], + 'state_editions' => [ + 'kópia' => 'kópia', + 'neznámy' => 'neznámy', + 'originál' => 'originál', + 'reprodukcia' => 'reprodukcia', + ], ]; diff --git a/tests/Importers/MgFotoImporterTest.php b/tests/Importers/MgFotoImporterTest.php new file mode 100644 index 000000000..41e3f4dcc --- /dev/null +++ b/tests/Importers/MgFotoImporterTest.php @@ -0,0 +1,331 @@ +repositoryMock = $this->createMock(CsvRepository::class); + $this->importer = new MgFotoImporter( + app(AuthorityMatcher::class), + $this->repositoryMock, + app(Translator::class) + ); + } + + /** @dataProvider mediumProvider */ + public function testMedium($material, $povrch, $translations) + { + $this->importData([ + 'Material' => $material, + 'Povrch' => $povrch, + ]); + + $item = Item::find('CZE:MG.rada_s_123-lomeni_s'); + $this->assertEquals($translations['cs'], $item->translate('cs')->medium); + $this->assertEquals($translations['sk'], $item->translate('sk')->medium); + $this->assertEquals($translations['en'], $item->translate('en')->medium); + } + + public static function mediumProvider() + { + return [ + 'material' => [ + 'papír', + null, + [ + 'cs' => 'papír', + 'sk' => 'papier', + 'en' => 'paper', + ], + ], + 'materialWithSurface' => [ + 'papír', + 'M', + [ + 'cs' => 'papír/matný', + 'sk' => 'papier/matný', + 'en' => 'paper/matte', + ], + ], + ]; + } + + /** @dataProvider titleProvider */ + public function testTitle($nazev, $predmet, $translations) + { + $this->importData([ + 'Název' => $nazev, + 'Předmět' => $predmet, + ]); + + $item = Item::find('CZE:MG.rada_s_123-lomeni_s'); + $this->assertEquals($translations['cs'], $item->translate('cs')->title); + $this->assertEquals($translations['sk'], $item->translate('sk')->title); + $this->assertEquals($translations['en'], $item->translate('en')->title); + } + + public static function titleProvider() + { + return [ + 'nazev' => [ + 'nazev', + null, + [ + 'cs' => 'nazev', + 'sk' => 'nazev', + 'en' => null, + ], + ], + 'predmet' => [ + null, + 'predmet', + [ + 'cs' => 'predmet', + 'sk' => 'predmet', + 'en' => null, + ], + ], + 'untitled' => [ + null, + null, + [ + 'cs' => 'bez názvu', + 'sk' => 'bez názvu', + 'en' => 'untitled', + ], + ], + ]; + } + + public function testStateEdition() + { + $this->importData([ + 'Původnost' => 'O', + ]); + + $item = Item::find('CZE:MG.rada_s_123-lomeni_s'); + $this->assertEquals('originál', $item->translate('cs')->state_edition); + $this->assertEquals('originál', $item->translate('sk')->state_edition); + $this->assertEquals('original', $item->translate('en')->state_edition); + } + + /** @dataProvider workTypeProvider */ + public function testWorkType($predmet, $translations) + { + $this->importData([ + 'Předmět' => $predmet, + ]); + + $item = Item::find('CZE:MG.rada_s_123-lomeni_s'); + $this->assertEquals($translations['cs'], $item->translate('cs')->work_type); + $this->assertEquals($translations['sk'], $item->translate('sk')->work_type); + $this->assertEquals($translations['en'], $item->translate('en')->work_type); + } + + public static function workTypeProvider() + { + return [ + 'noSubject' => [ + null, + [ + 'cs' => 'fotografie', + 'sk' => 'fotografia', + 'en' => 'photograph', + ], + ], + 'subject' => [ + 'negativ', + [ + 'cs' => 'fotografie/negativ', + 'sk' => 'fotografia/negatív', + 'en' => 'photograph/negative', + ], + ], + ]; + } + + /** @dataProvider techniqueProvider */ + public function testTechnique($zoom, $barva, $translations) + { + $this->importData([ + 'Zoom' => $zoom, + 'Barva' => $barva, + ]); + + $item = Item::find('CZE:MG.rada_s_123-lomeni_s'); + $this->assertEquals($translations['cs'], $item->translate('cs')->technique); + $this->assertEquals($translations['sk'], $item->translate('sk')->technique); + $this->assertEquals($translations['en'], $item->translate('en')->technique); + } + + public static function techniqueProvider() + { + return [ + 'zoom' => [ + 'V', + null, + [ + 'cs' => 'zvětšenina fotografie', + 'sk' => 'zväčšenina fotografie', + 'en' => 'photograhp enlargement', + ], + ], + 'barva' => [ + null, + 'C', + [ + 'cs' => 'černobílá fotografie', + 'sk' => 'čiernobiela fotografia', + 'en' => 'black and white photograph', + ], + ], + 'zoom/barva' => [ + 'V', + 'C', + [ + 'cs' => 'zvětšenina fotografie; černobílá fotografie', + 'sk' => 'zväčšenina fotografie; čiernobiela fotografia', + 'en' => 'photograhp enlargement; black and white photograph', + ], + ], + ]; + } + + public function testDagmarHochovaArchive() + { + $this->importData([ + 'Okolnosti' => 'Archiv negativů Dagmar Hochové', + ]); + + $item = Item::find('CZE:MG.rada_s_123-lomeni_s'); + $this->assertEquals('ze souboru', $item->translate('cs')->relationship_type); + $this->assertEquals('zo súboru', $item->translate('sk')->relationship_type); + $this->assertEquals('from set', $item->translate('en')->relationship_type); + $this->assertEquals('Archiv negativů Dagmar Hochové', $item->translate('cs')->related_work); + $this->assertEquals( + 'Archív negatívov Dagmar Hochovej', + $item->translate('sk')->related_work + ); + $this->assertEquals( + 'Archive of negatives of Dagmar Hochová', + $item->translate('en')->related_work + ); + } + + protected function importData($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; + } + + protected function fakeData(array $overrides = []): array + { + return $overrides + [ + 'Rada_S' => 'rada_s', + 'PorC_S' => 123, + 'Lomeni_S' => 'lomeni_s', + 'až' => null, + '/' => null, + 'Stát' => 'CZE', + 'Spr' => '6BG', + 'Odd' => 'f', + 'Karta' => 'PRAVDA', + 'Opsána' => 'NEPRAVDA', + 'Ověřena' => 'NEPRAVDA', + 'Kopie_S' => 'NEPRAVDA', + 'Ozn' => 'NEPRAVDA', + 'PrirC_S' => 'NEPRAVDA', + 'JináČ' => 'neg.', + 'Zapsal' => 'TAČR - MM', + 'DatZap' => '16.11.2007', + 'Počet' => '1', + 'StLokace' => 'Z 25', + 'AktLokace' => 'Z 25', + 'Určil' => 'Dufek', + 'DatUrč' => '08.12.1969', + 'Podsb' => '15', + 'Autor' => 'Reichmann, Vilém', + 'Profi_S' => 'NEPRAVDA', + 'Ateliér' => null, + 'MístoPůs' => 'Brno (Brünn)', + 'SigZnA' => null, + 'SigZnR' => 'název, signatura, datace', + 'Původnost' => 'O', + 'Materiál' => 'papír', + 'Předmět' => 'pozitiv', + 'Zoom' => 'V', + 'Barva' => 'C', + 'Povrch' => null, + 'Adj' => 'P', + 'Orientace' => 'V', + 'Formát' => '30x40', + 'Stav' => '1', + 'DatSt' => '25.10.2006', + 'Čitelnost' => 'a', + 'Osetrit_S' => 'NEPRAVDA', + 'Ktg' => null, + 'Téma' => null, + 'Název' => 'Bez názvu', + 'Popis' => 'Světlomet na louce.', + 'Lokalita' => null, + 'SpecLok' => null, + 'Čtverec' => null, + 'DatVz' => '1949', + 'RokVzOd' => '1949', + 'RokVzDo' => '1949', + 'KlíčObs' => null, + 'RokObsOd' => null, + 'RokObsDo' => null, + 'DatObs' => null, + 'PopisSt' => null, + 'Markant' => null, + 'PopisAdj' => null, + 'Vazba' => null, + 'Ošetření' => null, + 'RokOš' => null, + 'DatRev' => '31.12.2011', + 'InvRev' => null, + 'Pozn' => 'dobová zvětšenina', + 'Plus1T' => null, + 'Plus2T' => 'fotografie', + 'Plus3Č' => null, + 'Služ' => 's=302mm; v=349mm', + 'SlužF' => 's=302mm; v=349mm', + 'Služ2' => null, + 'ČDoklAkv' => null, + 'ZpAkv' => null, + 'DatAkv' => null, + 'PředMajSlovy' => null, + 'Okolnosti' => null, + ]; + } +}