Import image author beside image license author (#82)

This allows to use a fallback.
Some maintain the actual copyright as author instead of license author.

Relates: #10183
This commit is contained in:
Daniel Siepmann 2022-11-24 11:05:13 +01:00 committed by GitHub
parent c814dff4a0
commit 4cb1cf1438
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 127 additions and 21 deletions

View file

@ -23,6 +23,8 @@ declare(strict_types=1);
namespace WerkraumMedia\ThueCat\Domain\Import\Entity; namespace WerkraumMedia\ThueCat\Domain\Import\Entity;
use WerkraumMedia\ThueCat\Domain\Import\Entity\Properties\ForeignReference;
class MediaObject extends Minimum implements MapsToType class MediaObject extends Minimum implements MapsToType
{ {
/** /**
@ -40,6 +42,11 @@ class MediaObject extends Minimum implements MapsToType
*/ */
protected $licenseAuthor = ''; protected $licenseAuthor = '';
/**
* @var string|ForeignReference
*/
protected $author;
/** /**
* @var string * @var string
*/ */
@ -60,6 +67,14 @@ class MediaObject extends Minimum implements MapsToType
return $this->licenseAuthor; return $this->licenseAuthor;
} }
/**
* @return string|ForeignReference
*/
public function getAuthor()
{
return $this->author;
}
public function getType(): string public function getType(): string
{ {
return $this->type; return $this->type;
@ -89,6 +104,15 @@ class MediaObject extends Minimum implements MapsToType
$this->licenseAuthor = $licenseAuthor; $this->licenseAuthor = $licenseAuthor;
} }
/**
* @internal for mapping via Symfony component.
* @param string|ForeignReference $author
*/
public function setAuthor($author): void
{
$this->author = $author;
}
/** /**
* @internal for mapping via Symfony component. * @internal for mapping via Symfony component.
*/ */

View file

@ -83,6 +83,11 @@ class GeneralConverter implements Converter, LoggerAwareInterface
*/ */
private $parkingFacilityRepository; private $parkingFacilityRepository;
/**
* @var NameExtractor
*/
private $nameExtractor;
/** /**
* @var ImportConfiguration * @var ImportConfiguration
*/ */
@ -106,7 +111,8 @@ class GeneralConverter implements Converter, LoggerAwareInterface
LanguageHandling $languageHandling, LanguageHandling $languageHandling,
OrganisationRepository $organisationRepository, OrganisationRepository $organisationRepository,
TownRepository $townRepository, TownRepository $townRepository,
ParkingFacilityRepository $parkingFacilityRepository ParkingFacilityRepository $parkingFacilityRepository,
NameExtractor $nameExtractor
) { ) {
$this->resolveForeignReference = $resolveForeignReference; $this->resolveForeignReference = $resolveForeignReference;
$this->importer = $importer; $this->importer = $importer;
@ -114,6 +120,7 @@ class GeneralConverter implements Converter, LoggerAwareInterface
$this->organisationRepository = $organisationRepository; $this->organisationRepository = $organisationRepository;
$this->townRepository = $townRepository; $this->townRepository = $townRepository;
$this->parkingFacilityRepository = $parkingFacilityRepository; $this->parkingFacilityRepository = $parkingFacilityRepository;
$this->nameExtractor = $nameExtractor;
} }
public function convert( public function convert(
@ -360,7 +367,7 @@ class GeneralConverter implements Converter, LoggerAwareInterface
$language $language
); );
if ($photo instanceof MediaObject) { if ($photo instanceof MediaObject) {
$data[] = $this->getSingleMedia($photo, true); $data[] = $this->getSingleMedia($photo, true, $language);
} }
} }
@ -370,7 +377,7 @@ class GeneralConverter implements Converter, LoggerAwareInterface
$language $language
); );
if ($image instanceof MediaObject) { if ($image instanceof MediaObject) {
$data[] = $this->getSingleMedia($image, false); $data[] = $this->getSingleMedia($image, false, $language);
} }
} }
@ -379,7 +386,8 @@ class GeneralConverter implements Converter, LoggerAwareInterface
private function getSingleMedia( private function getSingleMedia(
MediaObject $mediaObject, MediaObject $mediaObject,
bool $mainImage bool $mainImage,
string $language
): array { ): array {
return [ return [
'mainImage' => $mainImage, 'mainImage' => $mainImage,
@ -387,6 +395,7 @@ class GeneralConverter implements Converter, LoggerAwareInterface
'title' => $mediaObject->getName(), 'title' => $mediaObject->getName(),
'description' => $mediaObject->getDescription(), 'description' => $mediaObject->getDescription(),
'url' => $mediaObject->getUrls()[0] ?? '', 'url' => $mediaObject->getUrls()[0] ?? '',
'author' => $this->nameExtractor->extract($mediaObject->getAuthor(), $language),
'copyrightYear' => $mediaObject->getCopyrightYear(), 'copyrightYear' => $mediaObject->getCopyrightYear(),
'license' => [ 'license' => [
'type' => $mediaObject->getLicense(), 'type' => $mediaObject->getLicense(),

View file

@ -0,0 +1,62 @@
<?php
declare(strict_types=1);
/*
* Copyright (C) 2022 Daniel Siepmann <coding@daniel-siepmann.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
namespace WerkraumMedia\ThueCat\Domain\Import\Typo3Converter;
use WerkraumMedia\ThueCat\Domain\Import\Entity\Properties\ForeignReference;
use WerkraumMedia\ThueCat\Domain\Import\ResolveForeignReference;
class NameExtractor
{
/**
* @var ResolveForeignReference
*/
private $resolveForeignReference;
public function __construct(
ResolveForeignReference $resolveForeignReference
) {
$this->resolveForeignReference = $resolveForeignReference;
}
/**
* @param string|ForeignReference $foreignReference
*/
public function extract(
$foreignReference,
string $language
): string {
if (is_string($foreignReference)) {
return $foreignReference;
}
if ($foreignReference instanceof ForeignReference) {
$remote = $this->resolveForeignReference->resolve($foreignReference, $language);
if (is_object($remote) && method_exists($remote, 'getName')) {
return $remote->getName();
}
}
return '';
}
}

View file

@ -13,6 +13,8 @@ Features
* Last import date is now shown within backend module beside each import configuration. * Last import date is now shown within backend module beside each import configuration.
* Import author of media. This allows to either render the license author or the author.
Fixes Fixes
----- -----

View file

@ -10,6 +10,9 @@
<div class="col-12 col-md-6 order-first order-md-last"> <div class="col-12 col-md-6 order-first order-md-last">
<f:if condition="{entity.media.mainImage}"> <f:if condition="{entity.media.mainImage}">
<img class="img-fluid" src="{entity.media.mainImage.url}" /> <img class="img-fluid" src="{entity.media.mainImage.url}" />
<f:if condition="{entity.media.mainImage.author}">
<p>ⓒ {entity.media.mainImage.author}</p>
</f:if>
</f:if> </f:if>
</div> </div>
</div> </div>

View file

@ -6,7 +6,7 @@
<title>Erste Attraktion</title> <title>Erste Attraktion</title>
<description>Die Beschreibung der Attraktion</description> <description>Die Beschreibung der Attraktion</description>
<town>1</town> <town>1</town>
<media>[{"mainImage":true,"type":"image","title":"Erfurt-Dom und Severikirche-beleuchtet.jpg","description":"","url":"https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/5159216\/Preview-1280x0\/image","copyrightYear":2016,"license":{"type":"https:\/\/creativecommons.org\/licenses\/by\/4.0\/","author":""}},{"mainImage":false,"type":"image","title":"Erfurt-Dom-und-Severikirche.jpg","description":"Sicht auf Dom St. Marien, St. Severikirche sowie die davor liegenden Klostergeb\u00e4ude und einem Ausschnitt des Biergartens umgeben von einem d\u00e4mmerungsverf\u00e4rten Himmel","url":"https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/5159186\/Preview-1280x0\/image","copyrightYear":2020,"license":{"type":"https:\/\/creativecommons.org\/licenses\/by\/4.0\/","author":""}},{"mainImage":false,"type":"image","title":"Erfurt-Dom und Severikirche-beleuchtet.jpg","description":"","url":"https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/5159216\/Preview-1280x0\/image","copyrightYear":2016,"license":{"type":"https:\/\/creativecommons.org\/licenses\/by\/4.0\/","author":""}}]</media> <media>[{"mainImage":true,"type":"image","title":"Erfurt-Dom und Severikirche-beleuchtet.jpg","description":"","url":"https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/5159216\/Preview-1280x0\/image","copyrightYear":2016,"author":"Image Author","license":{"type":"https:\/\/creativecommons.org\/licenses\/by\/4.0\/","author":""}},{"mainImage":false,"type":"image","title":"Erfurt-Dom-und-Severikirche.jpg","description":"Sicht auf Dom St. Marien, St. Severikirche sowie die davor liegenden Klostergeb\u00e4ude und einem Ausschnitt des Biergartens umgeben von einem d\u00e4mmerungsverf\u00e4rten Himmel","url":"https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/5159186\/Preview-1280x0\/image","copyrightYear":2020,"license":{"type":"https:\/\/creativecommons.org\/licenses\/by\/4.0\/","author":""}},{"mainImage":false,"type":"image","title":"Erfurt-Dom und Severikirche-beleuchtet.jpg","description":"","url":"https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/5159216\/Preview-1280x0\/image","copyrightYear":2016,"license":{"type":"https:\/\/creativecommons.org\/licenses\/by\/4.0\/","author":""}}]</media>
<opening_hours>[{"opens":"09:30:00","closes":"18:00:00","from":{"date":"2021-05-01 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"through":{"date":"2021-10-31 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"daysOfWeek":["Saturday","Friday","Thursday","Tuesday","Monday","Wednesday"]},{"opens":"13:00:00","closes":"18:00:00","from":{"date":"2021-05-01 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"through":{"date":"2021-10-31 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"daysOfWeek":["Sunday"]},{"opens":"09:30:00","closes":"17:00:00","from":{"date":"2021-11-01 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"through":{"date":"2022-04-30 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"daysOfWeek":["Saturday","Friday","Thursday","Tuesday","Monday","Wednesday"]},{"opens":"13:00:00","closes":"17:00:00","from":{"date":"2021-11-01 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"through":{"date":"2022-04-30 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"daysOfWeek":["Sunday","PublicHolidays"]}]</opening_hours> <opening_hours>[{"opens":"09:30:00","closes":"18:00:00","from":{"date":"2021-05-01 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"through":{"date":"2021-10-31 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"daysOfWeek":["Saturday","Friday","Thursday","Tuesday","Monday","Wednesday"]},{"opens":"13:00:00","closes":"18:00:00","from":{"date":"2021-05-01 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"through":{"date":"2021-10-31 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"daysOfWeek":["Sunday"]},{"opens":"09:30:00","closes":"17:00:00","from":{"date":"2021-11-01 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"through":{"date":"2022-04-30 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"daysOfWeek":["Saturday","Friday","Thursday","Tuesday","Monday","Wednesday"]},{"opens":"13:00:00","closes":"17:00:00","from":{"date":"2021-11-01 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"through":{"date":"2022-04-30 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"daysOfWeek":["Sunday","PublicHolidays"]}]</opening_hours>
<address>{"street":"Beispielstraße 1a","zip":"99084","city":"Beispielstadt","email":"example@example.com","phone":"(0)30 23125 000","fax":"","geo":{"latitude":50.975955358589545,"longitude":11.023667024961856}}</address> <address>{"street":"Beispielstraße 1a","zip":"99084","city":"Beispielstadt","email":"example@example.com","phone":"(0)30 23125 000","fax":"","geo":{"latitude":50.975955358589545,"longitude":11.023667024961856}}</address>
<offers>[{"type":"GuidedTourOffer","title":"F\u00fchrungen","description":"Immer samstags, um 11:15 Uhr findet eine \u00f6ffentliche F\u00fchrung durch das Museum statt. Dauer etwa 90 Minuten","prices":[{"title":"Erwachsene","description":"","price":8,"currency":"EUR","rule":"PerPerson"},{"title":"Erm\u00e4\u00dfigt","description":"als erm\u00e4\u00dfigt gelten schulpflichtige Kinder, Auszubildende, Studierende, Rentner\/-innen, Menschen mit Behinderungen, Inhaber Sozialausweis der Landeshauptstadt Erfurt","price":5,"currency":"EUR","rule":"PerPerson"}]},{"type":"EntryOffer","title":"Eintritt","description":"Schulklassen und Kitagruppen im Rahmen des Unterrichts: Eintritt frei\nAn jedem ersten Dienstag im Monat: Eintritt frei","prices":[{"title":"Erm\u00e4\u00dfigt","description":"als erm\u00e4\u00dfigt gelten schulpflichtige Kinder, Auszubildende, Studierende, Rentner\/-innen, Menschen mit Behinderungen, Inhaber Sozialausweis der Landeshauptstadt Erfurt","price":5,"currency":"EUR","rule":"PerPerson"},{"title":"Familienkarte","description":"","price":17,"currency":"EUR","rule":"PerGroup"},{"title":"ErfurtCard","description":"","price":14.9,"currency":"EUR","rule":"PerPackage"},{"title":"Erwachsene","description":"","price":8,"currency":"EUR","rule":"PerPerson"}]}]</offers> <offers>[{"type":"GuidedTourOffer","title":"F\u00fchrungen","description":"Immer samstags, um 11:15 Uhr findet eine \u00f6ffentliche F\u00fchrung durch das Museum statt. Dauer etwa 90 Minuten","prices":[{"title":"Erwachsene","description":"","price":8,"currency":"EUR","rule":"PerPerson"},{"title":"Erm\u00e4\u00dfigt","description":"als erm\u00e4\u00dfigt gelten schulpflichtige Kinder, Auszubildende, Studierende, Rentner\/-innen, Menschen mit Behinderungen, Inhaber Sozialausweis der Landeshauptstadt Erfurt","price":5,"currency":"EUR","rule":"PerPerson"}]},{"type":"EntryOffer","title":"Eintritt","description":"Schulklassen und Kitagruppen im Rahmen des Unterrichts: Eintritt frei\nAn jedem ersten Dienstag im Monat: Eintritt frei","prices":[{"title":"Erm\u00e4\u00dfigt","description":"als erm\u00e4\u00dfigt gelten schulpflichtige Kinder, Auszubildende, Studierende, Rentner\/-innen, Menschen mit Behinderungen, Inhaber Sozialausweis der Landeshauptstadt Erfurt","price":5,"currency":"EUR","rule":"PerPerson"},{"title":"Familienkarte","description":"","price":17,"currency":"EUR","rule":"PerGroup"},{"title":"ErfurtCard","description":"","price":14.9,"currency":"EUR","rule":"PerPackage"},{"title":"Erwachsene","description":"","price":8,"currency":"EUR","rule":"PerPerson"}]}]</offers>

File diff suppressed because one or more lines are too long

View file

@ -75,6 +75,7 @@ class FrontendTest extends FunctionalTestCase
self::assertStringContainsString('Highlight', (string)$result->getBody()); self::assertStringContainsString('Highlight', (string)$result->getBody());
self::assertStringContainsString('<img class="img-fluid" src="https://cms.thuecat.org/o/adaptive-media/image/5159216/Preview-1280x0/image" />', (string)$result->getBody()); self::assertStringContainsString('<img class="img-fluid" src="https://cms.thuecat.org/o/adaptive-media/image/5159216/Preview-1280x0/image" />', (string)$result->getBody());
self::assertStringContainsString('ⓒ Image Author', (string)$result->getBody());
self::assertStringContainsString('Beispielstraße 1a', (string)$result->getBody()); self::assertStringContainsString('Beispielstraße 1a', (string)$result->getBody());
self::assertStringContainsString('99084', (string)$result->getBody()); self::assertStringContainsString('99084', (string)$result->getBody());

View file

@ -31,6 +31,7 @@ use WerkraumMedia\ThueCat\Domain\Import\Typo3Converter\GeneralConverter;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use WerkraumMedia\ThueCat\Domain\Import\ResolveForeignReference; use WerkraumMedia\ThueCat\Domain\Import\ResolveForeignReference;
use WerkraumMedia\ThueCat\Domain\Import\Typo3Converter\LanguageHandling; use WerkraumMedia\ThueCat\Domain\Import\Typo3Converter\LanguageHandling;
use WerkraumMedia\ThueCat\Domain\Import\Typo3Converter\NameExtractor;
use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration; use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration;
use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLog; use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLog;
use WerkraumMedia\ThueCat\Domain\Repository\Backend\OrganisationRepository; use WerkraumMedia\ThueCat\Domain\Repository\Backend\OrganisationRepository;
@ -53,6 +54,7 @@ class GeneralConverterTest extends TestCase
$organisationRepository = $this->createStub(OrganisationRepository::class); $organisationRepository = $this->createStub(OrganisationRepository::class);
$townRepository = $this->createStub(TownRepository::class); $townRepository = $this->createStub(TownRepository::class);
$parkingFacilityRepository = $this->createStub(ParkingFacilityRepository::class); $parkingFacilityRepository = $this->createStub(ParkingFacilityRepository::class);
$nameExtractor = $this->createStub(NameExtractor::class);
$subject = new GeneralConverter( $subject = new GeneralConverter(
$resolveForeignReference, $resolveForeignReference,
@ -60,7 +62,8 @@ class GeneralConverterTest extends TestCase
$languageHandling, $languageHandling,
$organisationRepository, $organisationRepository,
$townRepository, $townRepository,
$parkingFacilityRepository $parkingFacilityRepository,
$nameExtractor
); );
self::assertInstanceOf( self::assertInstanceOf(
@ -82,6 +85,7 @@ class GeneralConverterTest extends TestCase
$organisationRepository = $this->createStub(OrganisationRepository::class); $organisationRepository = $this->createStub(OrganisationRepository::class);
$townRepository = $this->createStub(TownRepository::class); $townRepository = $this->createStub(TownRepository::class);
$parkingFacilityRepository = $this->createStub(ParkingFacilityRepository::class); $parkingFacilityRepository = $this->createStub(ParkingFacilityRepository::class);
$nameExtractor = $this->createStub(NameExtractor::class);
$logger = $this->createStub(LoggerInterface::class); $logger = $this->createStub(LoggerInterface::class);
$subject = new GeneralConverter( $subject = new GeneralConverter(
@ -90,7 +94,8 @@ class GeneralConverterTest extends TestCase
$languageHandling, $languageHandling,
$organisationRepository, $organisationRepository,
$townRepository, $townRepository,
$parkingFacilityRepository $parkingFacilityRepository,
$nameExtractor
); );
$subject->setLogger($logger); $subject->setLogger($logger);