mirror of
https://github.com/werkraum-media/thuecat.git
synced 2024-12-05 03:26:13 +01:00
Filter and sort opening hours (#83)
Opening hours are filtered. Opening hours from the past are no longer available. Opening hours are sorted. Newer opening hours are shown last. Relates: #10185
This commit is contained in:
parent
4cb1cf1438
commit
672f78a5dc
15 changed files with 501 additions and 279 deletions
|
@ -23,6 +23,7 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace WerkraumMedia\ThueCat\Domain\Import\Entity;
|
namespace WerkraumMedia\ThueCat\Domain\Import\Entity;
|
||||||
|
|
||||||
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||||
use WerkraumMedia\ThueCat\Domain\Import\EntityMapper\PropertyValues;
|
use WerkraumMedia\ThueCat\Domain\Import\EntityMapper\PropertyValues;
|
||||||
use WerkraumMedia\ThueCat\Domain\Import\Entity\Properties\Address;
|
use WerkraumMedia\ThueCat\Domain\Import\Entity\Properties\Address;
|
||||||
use WerkraumMedia\ThueCat\Domain\Import\Entity\Properties\ForeignReference;
|
use WerkraumMedia\ThueCat\Domain\Import\Entity\Properties\ForeignReference;
|
||||||
|
@ -30,6 +31,7 @@ use WerkraumMedia\ThueCat\Domain\Import\Entity\Properties\Geo;
|
||||||
use WerkraumMedia\ThueCat\Domain\Import\Entity\Properties\OpeningHour;
|
use WerkraumMedia\ThueCat\Domain\Import\Entity\Properties\OpeningHour;
|
||||||
use WerkraumMedia\ThueCat\Domain\Import\Entity\Shared\ContainedInPlace;
|
use WerkraumMedia\ThueCat\Domain\Import\Entity\Shared\ContainedInPlace;
|
||||||
use WerkraumMedia\ThueCat\Domain\Import\Entity\Shared\Organization;
|
use WerkraumMedia\ThueCat\Domain\Import\Entity\Shared\Organization;
|
||||||
|
use WerkraumMedia\ThueCat\Service\DateBasedFilter;
|
||||||
|
|
||||||
class Place extends Base
|
class Place extends Base
|
||||||
{
|
{
|
||||||
|
@ -146,6 +148,28 @@ class Place extends Base
|
||||||
return $this->accessibilitySpecification;
|
return $this->accessibilitySpecification;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return OpeningHour[]
|
||||||
|
*/
|
||||||
|
public function getOpeningHoursSpecification(): array
|
||||||
|
{
|
||||||
|
return GeneralUtility::makeInstance(DateBasedFilter::class)
|
||||||
|
->filterOutPreviousDates(
|
||||||
|
$this->openingHours,
|
||||||
|
function (OpeningHour $hour): ?\DateTimeImmutable {
|
||||||
|
return $hour->getValidThrough();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return ForeignReference[]
|
||||||
|
*/
|
||||||
|
public function getParkingFacilityNearBy(): array
|
||||||
|
{
|
||||||
|
return $this->parkingFacilitiesNearBy;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal for mapping via Symfony component.
|
* @internal for mapping via Symfony component.
|
||||||
*/
|
*/
|
||||||
|
@ -162,15 +186,6 @@ class Place extends Base
|
||||||
$this->geo = $geo;
|
$this->geo = $geo;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return OpeningHour[]
|
|
||||||
* @internal for mapping via Symfony component.
|
|
||||||
*/
|
|
||||||
public function getOpeningHoursSpecification(): array
|
|
||||||
{
|
|
||||||
return $this->openingHours;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal for mapping via Symfony component.
|
* @internal for mapping via Symfony component.
|
||||||
*/
|
*/
|
||||||
|
@ -186,15 +201,6 @@ class Place extends Base
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @internal for mapping via Symfony component.
|
|
||||||
* @return ForeignReference[]
|
|
||||||
*/
|
|
||||||
public function getParkingFacilityNearBy(): array
|
|
||||||
{
|
|
||||||
return $this->parkingFacilitiesNearBy;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal for mapping via Symfony component.
|
* @internal for mapping via Symfony component.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -24,6 +24,8 @@ declare(strict_types=1);
|
||||||
namespace WerkraumMedia\ThueCat\Domain\Model\Frontend;
|
namespace WerkraumMedia\ThueCat\Domain\Model\Frontend;
|
||||||
|
|
||||||
use TYPO3\CMS\Core\Type\TypeInterface;
|
use TYPO3\CMS\Core\Type\TypeInterface;
|
||||||
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||||
|
use WerkraumMedia\ThueCat\Service\DateBasedFilter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @implements \Iterator<int, OpeningHour>
|
* @implements \Iterator<int, OpeningHour>
|
||||||
|
@ -48,10 +50,29 @@ class OpeningHours implements TypeInterface, \Iterator, \Countable
|
||||||
public function __construct(string $serialized)
|
public function __construct(string $serialized)
|
||||||
{
|
{
|
||||||
$this->serialized = $serialized;
|
$this->serialized = $serialized;
|
||||||
$this->array = array_map(
|
$this->array = $this->createArray($serialized);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createArray(string $serialized): array
|
||||||
|
{
|
||||||
|
$array = array_map(
|
||||||
[OpeningHour::class, 'createFromArray'],
|
[OpeningHour::class, 'createFromArray'],
|
||||||
json_decode($serialized, true) ?? []
|
json_decode($serialized, true) ?? []
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$array = GeneralUtility::makeInstance(DateBasedFilter::class)
|
||||||
|
->filterOutPreviousDates(
|
||||||
|
$array,
|
||||||
|
function (OpeningHour $hour): ?\DateTimeImmutable {
|
||||||
|
return $hour->getThrough();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
usort($array, function (OpeningHour $hourA, OpeningHour $hourB) {
|
||||||
|
return $hourA->getFrom() <=> $hourB->getFrom();
|
||||||
|
});
|
||||||
|
|
||||||
|
return array_values($array);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __toString(): string
|
public function __toString(): string
|
||||||
|
|
57
Classes/Service/DateBasedFilter.php
Normal file
57
Classes/Service/DateBasedFilter.php
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
<?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\Service;
|
||||||
|
|
||||||
|
use TYPO3\CMS\Core\Context\Context;
|
||||||
|
|
||||||
|
class DateBasedFilter
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var Context
|
||||||
|
*/
|
||||||
|
private $context;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
Context $context
|
||||||
|
) {
|
||||||
|
$this->context = $context;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters out all objects where the date is prior the reference date.
|
||||||
|
*
|
||||||
|
* The reference date is now.
|
||||||
|
*/
|
||||||
|
public function filterOutPreviousDates(
|
||||||
|
array $listToFilter,
|
||||||
|
callable $provideDate
|
||||||
|
): array {
|
||||||
|
$referenceDate = $this->context->getPropertyFromAspect('date', 'full');
|
||||||
|
|
||||||
|
return array_filter($listToFilter, function($elementToFilter) use ($referenceDate, $provideDate) {
|
||||||
|
$objectDate = $provideDate($elementToFilter);
|
||||||
|
return $objectDate === null || $objectDate >= $referenceDate;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,6 +16,9 @@ services:
|
||||||
resource: '../Classes/Frontend/DataProcessing/*'
|
resource: '../Classes/Frontend/DataProcessing/*'
|
||||||
public: true
|
public: true
|
||||||
|
|
||||||
|
WerkraumMedia\ThueCat\Service\DateBasedFilter:
|
||||||
|
public: true
|
||||||
|
|
||||||
'cache.thuecat_fetchdata':
|
'cache.thuecat_fetchdata':
|
||||||
class: 'TYPO3\CMS\Core\Cache\Frontend\FrontendInterface'
|
class: 'TYPO3\CMS\Core\Cache\Frontend\FrontendInterface'
|
||||||
factory:
|
factory:
|
||||||
|
|
|
@ -15,6 +15,13 @@ Features
|
||||||
|
|
||||||
* Import author of media. This allows to either render the license author or the author.
|
* Import author of media. This allows to either render the license author or the author.
|
||||||
|
|
||||||
|
* Filter and sort opening hours.
|
||||||
|
Filter out opening hours from the past, they are not available to the template anymore.
|
||||||
|
Sort opening hours from early to later based on their end timing.
|
||||||
|
|
||||||
|
This should improve the UX of website visitors.
|
||||||
|
It is not possible yet to sort opening hours by hand within the thuecat backend.
|
||||||
|
|
||||||
Fixes
|
Fixes
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<dataset>
|
||||||
|
<tx_thuecat_tourist_attraction>
|
||||||
|
<uid>1</uid>
|
||||||
|
<pid>3</pid>
|
||||||
|
<title>Erste Attraktion</title>
|
||||||
|
<description>Die Beschreibung der Attraktion</description>
|
||||||
|
</tx_thuecat_tourist_attraction>
|
||||||
|
</dataset>
|
||||||
|
|
|
@ -0,0 +1,122 @@
|
||||||
|
{
|
||||||
|
"@context": {
|
||||||
|
"cdb": "https://thuecat.org/ontology/cdb/1.0/",
|
||||||
|
"dachkg": "https://thuecat.org/ontology/dachkg/1.0/",
|
||||||
|
"dbo": "http://dbpedia.org/ontology/",
|
||||||
|
"dsv": "http://ontologies.sti-innsbruck.at/dsv/",
|
||||||
|
"foaf": "http://xmlns.com/foaf/0.1/",
|
||||||
|
"owl": "http://www.w3.org/2002/07/owl#",
|
||||||
|
"rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
|
||||||
|
"rdfs": "http://www.w3.org/2000/01/rdf-schema#",
|
||||||
|
"schema": "http://schema.org/",
|
||||||
|
"sh": "http://www.w3.org/ns/shacl#",
|
||||||
|
"thuecat": "https://thuecat.org/ontology/thuecat/1.0/",
|
||||||
|
"ttgds": "https://thuecat.org/ontology/ttgds/1.0/",
|
||||||
|
"xsd": "http://www.w3.org/2001/XMLSchema#"
|
||||||
|
},
|
||||||
|
"@graph": [
|
||||||
|
{
|
||||||
|
"@id": "https://thuecat.org/resources/835224016581-dara",
|
||||||
|
"@type": [
|
||||||
|
"schema:Place",
|
||||||
|
"schema:Thing",
|
||||||
|
"schema:TouristAttraction",
|
||||||
|
"ttgds:PointOfInterest",
|
||||||
|
"thuecat:Building",
|
||||||
|
"thuecat:ReligiousBuilding",
|
||||||
|
"thuecat:Cathedral",
|
||||||
|
"thuecat:CatholicChurch",
|
||||||
|
"thuecat:Dome"
|
||||||
|
],
|
||||||
|
"thuecat:contentResponsible": {
|
||||||
|
"@id": "https://thuecat.org/resources/018132452787-ngbe"
|
||||||
|
},
|
||||||
|
"schema:availableLanguage": [
|
||||||
|
{
|
||||||
|
"@type": "thuecat:Language",
|
||||||
|
"@value": "thuecat:German"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"@type": "thuecat:Language",
|
||||||
|
"@value": "thuecat:English"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"schema:name": [
|
||||||
|
{
|
||||||
|
"@language": "de",
|
||||||
|
"@value": "Dom St. Marien"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"@language": "en",
|
||||||
|
"@value": "Cathedral of St. Mary"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"schema:openingHoursSpecification": [
|
||||||
|
{
|
||||||
|
"@id": "genid-7bb7d92bd6624bdf84634c86e8acdbb4-b4",
|
||||||
|
"@type": [
|
||||||
|
"schema:Intangible",
|
||||||
|
"schema:StructuredValue",
|
||||||
|
"schema:Thing",
|
||||||
|
"schema:OpeningHoursSpecification"
|
||||||
|
],
|
||||||
|
"schema:closes": {
|
||||||
|
"@type": "schema:Time",
|
||||||
|
"@value": "18:00:00"
|
||||||
|
},
|
||||||
|
"schema:dayOfWeek": [
|
||||||
|
{
|
||||||
|
"@type": "schema:DayOfWeek",
|
||||||
|
"@value": "schema:Wednesday"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"schema:opens": {
|
||||||
|
"@type": "schema:Time",
|
||||||
|
"@value": "09:30:00"
|
||||||
|
},
|
||||||
|
"schema:validFrom": {
|
||||||
|
"@type": "schema:Date",
|
||||||
|
"@value": "2021-05-01"
|
||||||
|
},
|
||||||
|
"schema:validThrough": {
|
||||||
|
"@type": "schema:Date",
|
||||||
|
"@value": "2021-10-31"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"@id": "genid-7bb7d92bd6624bdf84634c86e8acdbb4-b7",
|
||||||
|
"@type": [
|
||||||
|
"schema:Intangible",
|
||||||
|
"schema:StructuredValue",
|
||||||
|
"schema:Thing",
|
||||||
|
"schema:OpeningHoursSpecification"
|
||||||
|
],
|
||||||
|
"schema:closes": {
|
||||||
|
"@type": "schema:Time",
|
||||||
|
"@value": "17:00:00"
|
||||||
|
},
|
||||||
|
"schema:dayOfWeek": {
|
||||||
|
"@type": "schema:DayOfWeek",
|
||||||
|
"@value": "schema:Sunday"
|
||||||
|
},
|
||||||
|
"schema:opens": {
|
||||||
|
"@type": "schema:Time",
|
||||||
|
"@value": "13:00:00"
|
||||||
|
},
|
||||||
|
"schema:validFrom": {
|
||||||
|
"@type": "schema:Date",
|
||||||
|
"@value": "2050-11-01"
|
||||||
|
},
|
||||||
|
"schema:validThrough": {
|
||||||
|
"@type": "schema:Date",
|
||||||
|
"@value": "2050-04-30"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"schema:url": {
|
||||||
|
"@type": "schema:URL",
|
||||||
|
"@value": "http://www.dom-erfurt.de"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,76 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<dataset>
|
||||||
|
<pages>
|
||||||
|
<uid>1</uid>
|
||||||
|
<pid>0</pid>
|
||||||
|
<tstamp>1613400587</tstamp>
|
||||||
|
<crdate>1613400558</crdate>
|
||||||
|
<cruser_id>1</cruser_id>
|
||||||
|
<doktype>4</doktype>
|
||||||
|
<title>Rootpage</title>
|
||||||
|
<is_siteroot>1</is_siteroot>
|
||||||
|
</pages>
|
||||||
|
<pages>
|
||||||
|
<uid>10</uid>
|
||||||
|
<pid>1</pid>
|
||||||
|
<tstamp>1613400587</tstamp>
|
||||||
|
<crdate>1613400558</crdate>
|
||||||
|
<cruser_id>1</cruser_id>
|
||||||
|
<doktype>254</doktype>
|
||||||
|
<title>Storage folder</title>
|
||||||
|
</pages>
|
||||||
|
|
||||||
|
<sys_language>
|
||||||
|
<uid>1</uid>
|
||||||
|
<pid>0</pid>
|
||||||
|
<title>English</title>
|
||||||
|
<flag>en-us-gb</flag>
|
||||||
|
<language_isocode>en</language_isocode>
|
||||||
|
</sys_language>
|
||||||
|
|
||||||
|
<sys_language>
|
||||||
|
<uid>2</uid>
|
||||||
|
<pid>0</pid>
|
||||||
|
<title>French</title>
|
||||||
|
<flag>fr</flag>
|
||||||
|
<language_isocode>fr</language_isocode>
|
||||||
|
</sys_language>
|
||||||
|
|
||||||
|
<tx_thuecat_import_configuration>
|
||||||
|
<uid>1</uid>
|
||||||
|
<pid>0</pid>
|
||||||
|
<tstamp>1613400587</tstamp>
|
||||||
|
<crdate>1613400558</crdate>
|
||||||
|
<cruser_id>1</cruser_id>
|
||||||
|
<disable>0</disable>
|
||||||
|
<title>The tourist attraction</title>
|
||||||
|
<type>static</type>
|
||||||
|
<configuration><![CDATA[<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
||||||
|
<T3FlexForms>
|
||||||
|
<data>
|
||||||
|
<sheet index="sDEF">
|
||||||
|
<language index="lDEF">
|
||||||
|
<field index="storagePid">
|
||||||
|
<value index="vDEF">10</value>
|
||||||
|
</field>
|
||||||
|
<field index="urls">
|
||||||
|
<el index="el">
|
||||||
|
<field index="602a89f54d694654233086">
|
||||||
|
<value index="url">
|
||||||
|
<el>
|
||||||
|
<field index="url">
|
||||||
|
<value index="vDEF">https://thuecat.org/resources/opening-hours-to-filter</value>
|
||||||
|
</field>
|
||||||
|
</el>
|
||||||
|
</value>
|
||||||
|
<value index="_TOGGLE">0</value>
|
||||||
|
</field>
|
||||||
|
</el>
|
||||||
|
</field>
|
||||||
|
</language>
|
||||||
|
</sheet>
|
||||||
|
</data>
|
||||||
|
</T3FlexForms>
|
||||||
|
]]></configuration>
|
||||||
|
</tx_thuecat_import_configuration>
|
||||||
|
</dataset>
|
|
@ -0,0 +1,4 @@
|
||||||
|
"tx_thuecat_tourist_attraction",,,,,,,,
|
||||||
|
,"uid","pid","sys_language_uid","l18n_parent","l10n_source","remote_id","title","opening_hours"
|
||||||
|
,1,10,0,0,0,"https://thuecat.org/resources/835224016581-dara","Dom St. Marien","[{""opens"":""13:00:00"",""closes"":""17:00:00"",""from"":{""date"":""2050-11-01 00:00:00.000000"",""timezone_type"":3,""timezone"":""UTC""},""through"":{""date"":""2050-04-30 00:00:00.000000"",""timezone_type"":3,""timezone"":""UTC""},""daysOfWeek"":[""Sunday""]}]"
|
||||||
|
,2,10,1,1,1,"https://thuecat.org/resources/835224016581-dara","Cathedral of St. Mary","[{""opens"":""13:00:00"",""closes"":""17:00:00"",""from"":{""date"":""2050-11-01 00:00:00.000000"",""timezone_type"":3,""timezone"":""UTC""},""through"":{""date"":""2050-04-30 00:00:00.000000"",""timezone_type"":3,""timezone"":""UTC""},""daysOfWeek"":[""Sunday""]}]"
|
|
File diff suppressed because one or more lines are too long
|
@ -26,9 +26,6 @@ namespace WerkraumMedia\ThueCat\Tests\Functional;
|
||||||
use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\InternalRequest;
|
use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\InternalRequest;
|
||||||
use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
|
use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
|
||||||
|
|
||||||
/**
|
|
||||||
* @covers \
|
|
||||||
*/
|
|
||||||
class FrontendTest extends FunctionalTestCase
|
class FrontendTest extends FunctionalTestCase
|
||||||
{
|
{
|
||||||
protected $coreExtensionsToLoad = [
|
protected $coreExtensionsToLoad = [
|
||||||
|
@ -83,23 +80,6 @@ class FrontendTest extends FunctionalTestCase
|
||||||
self::assertStringContainsString('example@example.com', (string)$result->getBody());
|
self::assertStringContainsString('example@example.com', (string)$result->getBody());
|
||||||
self::assertStringContainsString('(0)30 23125 000', (string)$result->getBody());
|
self::assertStringContainsString('(0)30 23125 000', (string)$result->getBody());
|
||||||
|
|
||||||
self::assertStringContainsString('Montag:', (string)$result->getBody());
|
|
||||||
self::assertStringContainsString('09:30:00 - 17:00:00', (string)$result->getBody());
|
|
||||||
self::assertStringContainsString('Dienstag:', (string)$result->getBody());
|
|
||||||
self::assertStringContainsString('09:30:00 - 17:00:00', (string)$result->getBody());
|
|
||||||
self::assertStringContainsString('Mittwoch:', (string)$result->getBody());
|
|
||||||
self::assertStringContainsString('09:30:00 - 17:00:00', (string)$result->getBody());
|
|
||||||
self::assertStringContainsString('Donnerstag:', (string)$result->getBody());
|
|
||||||
self::assertStringContainsString('09:30:00 - 17:00:00', (string)$result->getBody());
|
|
||||||
self::assertStringContainsString('Freitag:', (string)$result->getBody());
|
|
||||||
self::assertStringContainsString('09:30:00 - 17:00:00', (string)$result->getBody());
|
|
||||||
self::assertStringContainsString('Samstag:', (string)$result->getBody());
|
|
||||||
self::assertStringContainsString('09:30:00 - 17:00:00', (string)$result->getBody());
|
|
||||||
self::assertStringContainsString('Sonntag:', (string)$result->getBody());
|
|
||||||
self::assertStringContainsString('13:00:00 - 17:00:00', (string)$result->getBody());
|
|
||||||
self::assertStringContainsString('Feiertags:', (string)$result->getBody());
|
|
||||||
self::assertStringContainsString('13:00:00 - 17:00:00', (string)$result->getBody());
|
|
||||||
|
|
||||||
self::assertStringContainsString('Führungen', (string)$result->getBody());
|
self::assertStringContainsString('Führungen', (string)$result->getBody());
|
||||||
self::assertStringContainsString('(Führung)', (string)$result->getBody());
|
self::assertStringContainsString('(Führung)', (string)$result->getBody());
|
||||||
self::assertStringContainsString('Immer samstags, um 11:15 Uhr findet eine öffentliche Führung durch das Museum statt. Dauer etwa 90 Minuten', (string)$result->getBody());
|
self::assertStringContainsString('Immer samstags, um 11:15 Uhr findet eine öffentliche Führung durch das Museum statt. Dauer etwa 90 Minuten', (string)$result->getBody());
|
||||||
|
@ -443,4 +423,142 @@ class FrontendTest extends FunctionalTestCase
|
||||||
'"Parkgebühr" is not rendered before "Verkostung"'
|
'"Parkgebühr" is not rendered before "Verkostung"'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function openingHoursAreFilteredByThough(): void
|
||||||
|
{
|
||||||
|
$this->importDataSet('EXT:thuecat/Tests/Functional/Fixtures/Frontend/TouristAttractionsOpeningHours.xml');
|
||||||
|
|
||||||
|
$hidden = new \DateTimeImmutable('yesterday');
|
||||||
|
$available = new \DateTimeImmutable('tomorrow');
|
||||||
|
|
||||||
|
$this->getConnectionPool()
|
||||||
|
->getConnectionForTable('tx_thuecat_tourist_attraction')
|
||||||
|
->update(
|
||||||
|
'tx_thuecat_tourist_attraction',
|
||||||
|
['opening_hours' => json_encode([
|
||||||
|
[
|
||||||
|
'closes' => '17:00:00',
|
||||||
|
'opens' => '13:00:00',
|
||||||
|
'daysOfWeek' => ['Sunday'],
|
||||||
|
'from' => [
|
||||||
|
'date' => $hidden->modify('-1 day')->format('Y-m-d') . ' 00:00:00.000000',
|
||||||
|
'timezone' => 'UTC',
|
||||||
|
'timezone_type' => 3,
|
||||||
|
],
|
||||||
|
'through' => [
|
||||||
|
'date' => $hidden->format('Y-m-d') . ' 00:00:00.000000',
|
||||||
|
'timezone' => 'UTC',
|
||||||
|
'timezone_type' => 3,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'closes' => '17:00:00',
|
||||||
|
'opens' => '13:00:00',
|
||||||
|
'daysOfWeek' => ['Sunday'],
|
||||||
|
'from' => [
|
||||||
|
'date' => $available->modify('-1 day')->format('Y-m-d') . ' 00:00:00.000000',
|
||||||
|
'timezone' => 'UTC',
|
||||||
|
'timezone_type' => 3,
|
||||||
|
],
|
||||||
|
'through' => [
|
||||||
|
'date' => $available->format('Y-m-d') . ' 00:00:00.000000',
|
||||||
|
'timezone' => 'UTC',
|
||||||
|
'timezone_type' => 3,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
])],
|
||||||
|
['uid' => 1]
|
||||||
|
);
|
||||||
|
|
||||||
|
$request = new InternalRequest();
|
||||||
|
$request = $request->withPageId(2);
|
||||||
|
|
||||||
|
$result = (string)$this->executeFrontendRequest($request)->getBody();
|
||||||
|
|
||||||
|
self::assertStringNotContainsString($hidden->modify('-1 day')->format('d.m.Y'), $result);
|
||||||
|
self::assertStringNotContainsString($hidden->format('d.m.Y'), $result);
|
||||||
|
self::assertStringContainsString($available->modify('-1 day')->format('d.m.Y'), $result);
|
||||||
|
self::assertStringContainsString($available->format('d.m.Y'), $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function openingHoursAreSortedByFrom(): void
|
||||||
|
{
|
||||||
|
$this->importDataSet('EXT:thuecat/Tests/Functional/Fixtures/Frontend/TouristAttractionsOpeningHours.xml');
|
||||||
|
|
||||||
|
$fromFirstOpening = new \DateTimeImmutable('today');
|
||||||
|
$fromSecondOpening = new \DateTimeImmutable('+2 days');
|
||||||
|
$fromThirdOpening = new \DateTimeImmutable('+7 days');
|
||||||
|
|
||||||
|
$this->getConnectionPool()
|
||||||
|
->getConnectionForTable('tx_thuecat_tourist_attraction')
|
||||||
|
->update(
|
||||||
|
'tx_thuecat_tourist_attraction',
|
||||||
|
['opening_hours' => json_encode([
|
||||||
|
[
|
||||||
|
'closes' => '17:00:00',
|
||||||
|
'opens' => '13:00:00',
|
||||||
|
'daysOfWeek' => ['Sunday'],
|
||||||
|
'from' => [
|
||||||
|
'date' => $fromThirdOpening->format('Y-m-d') . ' 00:00:00.000000',
|
||||||
|
'timezone' => 'UTC',
|
||||||
|
'timezone_type' => 3,
|
||||||
|
],
|
||||||
|
'through' => [
|
||||||
|
'date' => $fromThirdOpening->modify('+1 day')->format('Y-m-d') . ' 00:00:00.000000',
|
||||||
|
'timezone' => 'UTC',
|
||||||
|
'timezone_type' => 3,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'closes' => '17:00:00',
|
||||||
|
'opens' => '13:00:00',
|
||||||
|
'daysOfWeek' => ['Sunday'],
|
||||||
|
'from' => [
|
||||||
|
'date' => $fromFirstOpening->format('Y-m-d') . ' 00:00:00.000000',
|
||||||
|
'timezone' => 'UTC',
|
||||||
|
'timezone_type' => 3,
|
||||||
|
],
|
||||||
|
'through' => [
|
||||||
|
'date' => $fromFirstOpening->modify('+1 day')->format('Y-m-d') . ' 00:00:00.000000',
|
||||||
|
'timezone' => 'UTC',
|
||||||
|
'timezone_type' => 3,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'closes' => '17:00:00',
|
||||||
|
'opens' => '13:00:00',
|
||||||
|
'daysOfWeek' => ['Sunday'],
|
||||||
|
'from' => [
|
||||||
|
'date' => $fromSecondOpening->format('Y-m-d') . ' 00:00:00.000000',
|
||||||
|
'timezone' => 'UTC',
|
||||||
|
'timezone_type' => 3,
|
||||||
|
],
|
||||||
|
'through' => [
|
||||||
|
'date' => $fromSecondOpening->modify('+1 day')->format('Y-m-d') . ' 00:00:00.000000',
|
||||||
|
'timezone' => 'UTC',
|
||||||
|
'timezone_type' => 3,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
])],
|
||||||
|
['uid' => 1]
|
||||||
|
);
|
||||||
|
|
||||||
|
$request = new InternalRequest();
|
||||||
|
$request = $request->withPageId(2);
|
||||||
|
|
||||||
|
$result = (string)$this->executeFrontendRequest($request)->getBody();
|
||||||
|
|
||||||
|
$positionFirstHour = mb_strpos($result, $fromFirstOpening->format('d.m.Y'));
|
||||||
|
$positionSecondHour = mb_strpos($result, $fromSecondOpening->format('d.m.Y'));
|
||||||
|
$positionThirdHour = mb_strpos($result, $fromThirdOpening->format('d.m.Y'));
|
||||||
|
|
||||||
|
self::assertLessThan($positionThirdHour, $positionSecondHour, 'Third hour does not come after second hour.');
|
||||||
|
self::assertLessThan($positionSecondHour, $positionFirstHour, 'Second hour does not come after first hour.');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,107 +68,6 @@ class PlaceInfosTest extends TestCase
|
||||||
self::assertSame([], $result->getOpeningHoursSpecification());
|
self::assertSame([], $result->getOpeningHoursSpecification());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @test
|
|
||||||
*/
|
|
||||||
public function mapsIncomingOpeningHoursSpecificaton(): void
|
|
||||||
{
|
|
||||||
$subject = new EntityMapper();
|
|
||||||
|
|
||||||
$result = $subject->mapDataToEntity([
|
|
||||||
'schema:openingHoursSpecification' => [
|
|
||||||
0 => [
|
|
||||||
'schema:closes' => [
|
|
||||||
'@type' => 'schema:Time',
|
|
||||||
'@value' => '18:00:00',
|
|
||||||
],
|
|
||||||
'schema:dayOfWeek' => [
|
|
||||||
0 => [
|
|
||||||
'@type' => 'schema:DayOfWeek',
|
|
||||||
'@value' => 'schema:Saturday',
|
|
||||||
],
|
|
||||||
1 => [
|
|
||||||
'@type' => 'schema:DayOfWeek',
|
|
||||||
'@value' => 'schema:Friday',
|
|
||||||
],
|
|
||||||
2 => [
|
|
||||||
'@type' => 'schema:DayOfWeek',
|
|
||||||
'@value' => 'schema:Thursday',
|
|
||||||
],
|
|
||||||
3 => [
|
|
||||||
'@type' => 'schema:DayOfWeek',
|
|
||||||
'@value' => 'schema:Tuesday',
|
|
||||||
],
|
|
||||||
4 => [
|
|
||||||
'@type' => 'schema:DayOfWeek',
|
|
||||||
'@value' => 'schema:Monday',
|
|
||||||
],
|
|
||||||
5 => [
|
|
||||||
'@type' => 'schema:DayOfWeek',
|
|
||||||
'@value' => 'schema:Wednesday',
|
|
||||||
],
|
|
||||||
],
|
|
||||||
'schema:opens' => [
|
|
||||||
'@type' => 'schema:Time',
|
|
||||||
'@value' => '09:30:00',
|
|
||||||
],
|
|
||||||
'schema:validFrom' => [
|
|
||||||
'@type' => 'schema:Date',
|
|
||||||
'@value' => '2021-05-01',
|
|
||||||
],
|
|
||||||
'schema:validThrough' => [
|
|
||||||
'@type' => 'schema:Date',
|
|
||||||
'@value' => '2021-10-31',
|
|
||||||
],
|
|
||||||
],
|
|
||||||
1 => [
|
|
||||||
'schema:closes' => [
|
|
||||||
'@type' => 'schema:Time',
|
|
||||||
'@value' => '18:00:00',
|
|
||||||
],
|
|
||||||
'schema:dayOfWeek' => [
|
|
||||||
'@type' => 'schema:DayOfWeek',
|
|
||||||
'@value' => 'schema:Sunday',
|
|
||||||
],
|
|
||||||
'schema:opens' => [
|
|
||||||
'@type' => 'schema:Time',
|
|
||||||
'@value' => '13:00:00',
|
|
||||||
],
|
|
||||||
'schema:validFrom' => [
|
|
||||||
'@type' => 'schema:Date',
|
|
||||||
'@value' => '2021-05-01',
|
|
||||||
],
|
|
||||||
'schema:validThrough' => [
|
|
||||||
'@type' => 'schema:Date',
|
|
||||||
'@value' => '2021-10-31',
|
|
||||||
],
|
|
||||||
],
|
|
||||||
],
|
|
||||||
], Place::class, [
|
|
||||||
JsonDecode::ACTIVE_LANGUAGE => 'de',
|
|
||||||
]);
|
|
||||||
|
|
||||||
self::assertInstanceOf(Place::class, $result);
|
|
||||||
self::assertCount(2, $result->getOpeningHoursSpecification());
|
|
||||||
self::assertSame('18:00:00', $result->getOpeningHoursSpecification()[0]->getCloses()->format('H:i:s'));
|
|
||||||
self::assertSame('09:30:00', $result->getOpeningHoursSpecification()[0]->getOpens()->format('H:i:s'));
|
|
||||||
self::assertSame('2021-05-01', $result->getOpeningHoursSpecification()[0]->getValidFrom()->format('Y-m-d'));
|
|
||||||
self::assertSame('2021-10-31', $result->getOpeningHoursSpecification()[0]->getValidThrough()->format('Y-m-d'));
|
|
||||||
self::assertSame([
|
|
||||||
'Saturday',
|
|
||||||
'Friday',
|
|
||||||
'Thursday',
|
|
||||||
'Tuesday',
|
|
||||||
'Monday',
|
|
||||||
'Wednesday',
|
|
||||||
], $result->getOpeningHoursSpecification()[0]->getDaysOfWeek());
|
|
||||||
self::assertSame('18:00:00', $result->getOpeningHoursSpecification()[1]->getCloses()->format('H:i:s'));
|
|
||||||
self::assertSame('13:00:00', $result->getOpeningHoursSpecification()[1]->getOpens()->format('H:i:s'));
|
|
||||||
self::assertSame('2021-05-01', $result->getOpeningHoursSpecification()[1]->getValidFrom()->format('Y-m-d'));
|
|
||||||
self::assertSame('2021-10-31', $result->getOpeningHoursSpecification()[1]->getValidThrough()->format('Y-m-d'));
|
|
||||||
self::assertSame(['Sunday'], $result->getOpeningHoursSpecification()[1]->getDaysOfWeek());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -215,6 +215,21 @@ class ImportTest extends TestCase
|
||||||
$this->assertCSVDataSet('EXT:thuecat/Tests/Functional/Fixtures/Import/ImportsTouristAttractionsWithRelations.csv');
|
$this->assertCSVDataSet('EXT:thuecat/Tests/Functional/Fixtures/Import/ImportsTouristAttractionsWithRelations.csv');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function importsTouristAttractionsWithFilteredOpeningHours(): void
|
||||||
|
{
|
||||||
|
$this->importDataSet(__DIR__ . '/Fixtures/Import/ImportsTouristAttractionWithFilteredOpeningHours.xml');
|
||||||
|
GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/thuecat.org/resources/opening-hours-to-filter.json');
|
||||||
|
GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/thuecat.org/resources/018132452787-ngbe.json');
|
||||||
|
|
||||||
|
$configuration = $this->get(ImportConfigurationRepository::class)->findByUid(1);
|
||||||
|
$this->get(Importer::class)->importConfiguration($configuration);
|
||||||
|
|
||||||
|
$this->assertCSVDataSet('EXT:thuecat/Tests/Functional/Fixtures/Import/ImportsTouristAttractionsWithFilteredOpeningHours.csv');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,111 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace WerkraumMedia\ThueCat\Tests\Unit\Domain\Model\Frontend;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (C) 2021 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
use WerkraumMedia\ThueCat\Domain\Model\Frontend\OpeningHours;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @covers \WerkraumMedia\ThueCat\Domain\Model\Frontend\OpeningHours
|
|
||||||
*
|
|
||||||
* @uses \WerkraumMedia\ThueCat\Domain\Model\Frontend\OpeningHour
|
|
||||||
*
|
|
||||||
* @testdox Frontend model for offers
|
|
||||||
*/
|
|
||||||
class OpeningHoursTest extends TestCase
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @test
|
|
||||||
*/
|
|
||||||
public function canBeCreated(): void
|
|
||||||
{
|
|
||||||
$subject = new OpeningHours('{}');
|
|
||||||
|
|
||||||
self::assertInstanceOf(OpeningHours::class, $subject);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @test
|
|
||||||
*/
|
|
||||||
public function isCountable(): void
|
|
||||||
{
|
|
||||||
$subject = new OpeningHours('{}');
|
|
||||||
|
|
||||||
self::assertInstanceOf(\Countable::class, $subject);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @test
|
|
||||||
*/
|
|
||||||
public function isIterator(): void
|
|
||||||
{
|
|
||||||
$subject = new OpeningHours('{}');
|
|
||||||
|
|
||||||
self::assertInstanceOf(\Iterator::class, $subject);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @test
|
|
||||||
* @dataProvider forCount
|
|
||||||
* @testdox returns $expected for count
|
|
||||||
*/
|
|
||||||
public function returnsExpectedCount(string $serialized, int $expected): void
|
|
||||||
{
|
|
||||||
$subject = new OpeningHours($serialized);
|
|
||||||
|
|
||||||
self::assertCount($expected, $subject);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function forCount(): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'zero' => [
|
|
||||||
'serialized' => '{}',
|
|
||||||
'expected' => 0,
|
|
||||||
],
|
|
||||||
'one' => [
|
|
||||||
'serialized' => json_encode([
|
|
||||||
[
|
|
||||||
],
|
|
||||||
]),
|
|
||||||
'expected' => 1,
|
|
||||||
],
|
|
||||||
'five' => [
|
|
||||||
'serialized' => json_encode([
|
|
||||||
[
|
|
||||||
],
|
|
||||||
[
|
|
||||||
],
|
|
||||||
[
|
|
||||||
],
|
|
||||||
[
|
|
||||||
],
|
|
||||||
[
|
|
||||||
],
|
|
||||||
]),
|
|
||||||
'expected' => 5,
|
|
||||||
],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -349,18 +349,13 @@ parameters:
|
||||||
count: 1
|
count: 1
|
||||||
path: Configuration/TCA/tx_thuecat_town.php
|
path: Configuration/TCA/tx_thuecat_town.php
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Cannot call method format\\(\\) on DateTimeImmutable\\|null\\.$#"
|
|
||||||
count: 4
|
|
||||||
path: Tests/Functional/Import/EntityMapping/PlaceInfosTest.php
|
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Cannot call method findByUid\\(\\) on mixed\\.$#"
|
message: "#^Cannot call method findByUid\\(\\) on mixed\\.$#"
|
||||||
count: 8
|
count: 9
|
||||||
path: Tests/Functional/ImportTest.php
|
path: Tests/Functional/ImportTest.php
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Cannot call method importConfiguration\\(\\) on mixed\\.$#"
|
message: "#^Cannot call method importConfiguration\\(\\) on mixed\\.$#"
|
||||||
count: 8
|
count: 9
|
||||||
path: Tests/Functional/ImportTest.php
|
path: Tests/Functional/ImportTest.php
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue