Improve opening hours (#86)

Strip off seconds from strings.
Prepare code to easily provide a structured data to allow integrators to
format timing differently.
Provide a method to easily check if an opening hour is only valid for a
single day.

Relates: #10185
This commit is contained in:
Daniel Siepmann 2022-11-29 10:02:44 +01:00 committed by GitHub
parent 0c9700cf42
commit 35398b49c7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 205 additions and 10 deletions

View file

@ -91,12 +91,12 @@ class OpeningHour
public function getOpens(): string public function getOpens(): string
{ {
return $this->opens; return $this->formatTiming($this->opens);
} }
public function getCloses(): string public function getCloses(): string
{ {
return $this->closes; return $this->formatTiming($this->closes);
} }
public function getDaysOfWeek(): array public function getDaysOfWeek(): array
@ -128,6 +128,17 @@ class OpeningHour
return $this->through; return $this->through;
} }
public function isSingleDay(): bool
{
$from = $this->getFrom();
$through = $this->getThrough();
return $from instanceof \DateTimeImmutable
&& $through instanceof \DateTimeImmutable
&& $from->format('Ymd') === $through->format('Ymd')
;
}
private function sortedDaysOfWeek(array $sorting): array private function sortedDaysOfWeek(array $sorting): array
{ {
if ($this->daysOfWeek === []) { if ($this->daysOfWeek === []) {
@ -147,4 +158,35 @@ class OpeningHour
return $days; return $days;
} }
/**
* Returns timing in default format.
*
* @return string
*/
private function formatTiming(string $timing): string
{
$parts = $this->getTimingParts($timing);
if ($parts['hour'] === '' || $parts['minutes'] === '') {
return '';
}
return $parts['hour'] . ':' . $parts['minutes'];
}
/**
* Converts the string representationg of a time HH:MM:SS into an array.
*
* @return string[]
*/
private function getTimingParts(string $string): array
{
$parts = explode(':', $string);
return [
'hour' => $parts[0] ?? '',
'minutes' => $parts[1] ?? '',
'seconds' => $parts[2] ?? '',
];
}
} }

View file

@ -26,6 +26,8 @@ Features
It is possible to define special opening hours, e.g. for holidays. It is possible to define special opening hours, e.g. for holidays.
Those are now also imported and provided to the templates. Those are now also imported and provided to the templates.
* Allow to check if an opening hour is valid for a single day.
Fixes Fixes
----- -----
@ -53,6 +55,8 @@ Tasks
The key was already moved to extension configuration as documented. The key was already moved to extension configuration as documented.
Still we extended the site configuration, which is now cleaned up, see: https://github.com/werkraum-media/thuecat/issues/55 Still we extended the site configuration, which is now cleaned up, see: https://github.com/werkraum-media/thuecat/issues/55
* Remove seconds from opens and closes of opening hours as we don't expect them to be used.
Deprecation Deprecation
----------- -----------

View file

@ -440,7 +440,7 @@ class FrontendTest extends FunctionalTestCase
'tx_thuecat_tourist_attraction', 'tx_thuecat_tourist_attraction',
['opening_hours' => json_encode([ ['opening_hours' => json_encode([
[ [
'closes' => '17:00:00', 'closes' => '14:00:00',
'opens' => '13:00:00', 'opens' => '13:00:00',
'daysOfWeek' => ['Sunday'], 'daysOfWeek' => ['Sunday'],
'from' => [ 'from' => [
@ -455,8 +455,8 @@ class FrontendTest extends FunctionalTestCase
], ],
], ],
[ [
'closes' => '17:00:00', 'closes' => '16:00:00',
'opens' => '13:00:00', 'opens' => '15:00:00',
'daysOfWeek' => ['Sunday'], 'daysOfWeek' => ['Sunday'],
'from' => [ 'from' => [
'date' => $available->modify('-1 day')->format('Y-m-d') . ' 00:00:00.000000', 'date' => $available->modify('-1 day')->format('Y-m-d') . ' 00:00:00.000000',
@ -478,6 +478,13 @@ class FrontendTest extends FunctionalTestCase
$result = (string)$this->executeFrontendRequest($request)->getBody(); $result = (string)$this->executeFrontendRequest($request)->getBody();
self::assertStringNotContainsString('14:00', $result);
self::assertStringNotContainsString('13:00', $result);
self::assertStringNotContainsString('16:00:00', $result);
self::assertStringContainsString('16:00', $result);
self::assertStringNotContainsString('15:00:00', $result);
self::assertStringContainsString('15:00', $result);
self::assertStringNotContainsString($hidden->modify('-1 day')->format('d.m.Y'), $result); self::assertStringNotContainsString($hidden->modify('-1 day')->format('d.m.Y'), $result);
self::assertStringNotContainsString($hidden->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->modify('-1 day')->format('d.m.Y'), $result);
@ -579,8 +586,8 @@ class FrontendTest extends FunctionalTestCase
'tx_thuecat_tourist_attraction', 'tx_thuecat_tourist_attraction',
['special_opening_hours' => json_encode([ ['special_opening_hours' => json_encode([
[ [
'closes' => '17:00:00', 'closes' => '12:00:00',
'opens' => '13:00:00', 'opens' => '11:00:00',
'daysOfWeek' => ['Sunday'], 'daysOfWeek' => ['Sunday'],
'from' => [ 'from' => [
'date' => $hidden->modify('-1 day')->format('Y-m-d') . ' 00:00:00.000000', 'date' => $hidden->modify('-1 day')->format('Y-m-d') . ' 00:00:00.000000',
@ -594,7 +601,7 @@ class FrontendTest extends FunctionalTestCase
], ],
], ],
[ [
'closes' => '17:00:00', 'closes' => '14:00:00',
'opens' => '13:00:00', 'opens' => '13:00:00',
'daysOfWeek' => ['Sunday'], 'daysOfWeek' => ['Sunday'],
'from' => [ 'from' => [
@ -609,8 +616,8 @@ class FrontendTest extends FunctionalTestCase
], ],
], ],
[ [
'closes' => '17:00:00', 'closes' => '16:00:00',
'opens' => '13:00:00', 'opens' => '15:00:00',
'daysOfWeek' => ['Sunday'], 'daysOfWeek' => ['Sunday'],
'from' => [ 'from' => [
'date' => $available->modify('-1 day')->format('Y-m-d') . ' 00:00:00.000000', 'date' => $available->modify('-1 day')->format('Y-m-d') . ' 00:00:00.000000',
@ -632,6 +639,17 @@ class FrontendTest extends FunctionalTestCase
$result = (string)$this->executeFrontendRequest($request)->getBody(); $result = (string)$this->executeFrontendRequest($request)->getBody();
self::assertStringNotContainsString('11:00', $result);
self::assertStringNotContainsString('12:00', $result);
self::assertStringNotContainsString('14:00:00', $result);
self::assertStringContainsString('14:00', $result);
self::assertStringNotContainsString('13:00:00', $result);
self::assertStringContainsString('13:00', $result);
self::assertStringNotContainsString('16:00:00', $result);
self::assertStringContainsString('16:00', $result);
self::assertStringNotContainsString('15:00:00', $result);
self::assertStringContainsString('15:00', $result);
self::assertStringNotContainsString($hidden->modify('-1 day')->format('d.m.Y'), $result, 'Filtered date is shown'); self::assertStringNotContainsString($hidden->modify('-1 day')->format('d.m.Y'), $result, 'Filtered date is shown');
self::assertStringNotContainsString($hidden->format('d.m.Y'), $result, 'Filtered date is shown'); self::assertStringNotContainsString($hidden->format('d.m.Y'), $result, 'Filtered date is shown');
self::assertStringContainsString($available->modify('-1 day')->format('d.m.Y'), $result, 'First special opening hour is missing'); self::assertStringContainsString($available->modify('-1 day')->format('d.m.Y'), $result, 'First special opening hour is missing');

View file

@ -0,0 +1,131 @@
<?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\Tests\Unit\Domain\Model\Frontend;
use PHPUnit\Framework\TestCase;
use WerkraumMedia\ThueCat\Domain\Model\Frontend\OpeningHour;
/**
* @covers \WerkraumMedia\Domain\Model\Frontend\OpeningHour
*/
class OpeningHourTest extends TestCase
{
/**
* @test
*/
public function returnsReducedOpens(): void
{
$subject = OpeningHour::createFromArray([
'opens' => '14:13:12',
]);
self::assertSame(
'14:13',
$subject->getOpens()
);
}
/**
* @test
*/
public function returnsOpensForEmptyString(): void
{
$subject = OpeningHour::createFromArray([]);
self::assertSame(
'',
$subject->getOpens()
);
}
/**
* @test
*/
public function returnsReducedCloses(): void
{
$subject = OpeningHour::createFromArray([
'closes' => '14:13:12',
]);
self::assertSame(
'14:13',
$subject->getCloses()
);
}
/**
* @test
*/
public function returnsClosesForEmptyString(): void
{
$subject = OpeningHour::createFromArray([]);
self::assertSame(
'',
$subject->getCloses()
);
}
/**
* @test
*/
public function returnsThatThisIsOnlyASingleDay(): void
{
$subject = OpeningHour::createFromArray([
'from' => [
'date' => '2022-11-28 00:00:00.000000',
'timezone_type' => 3,
'timezone' => 'UTC',
],
'through' => [
'date' => '2022-11-28 00:00:00.000000',
'timezone_type' => 3,
'timezone' => 'UTC',
],
]);
self::assertTrue($subject->isSingleDay());
}
/**
* @test
*/
public function returnsThatThisIsATimeframe(): void
{
$subject = OpeningHour::createFromArray([
'from' => [
'date' => '2022-11-28 00:00:00.000000',
'timezone_type' => 3,
'timezone' => 'UTC',
],
'through' => [
'date' => '2022-11-29 00:00:00.000000',
'timezone_type' => 3,
'timezone' => 'UTC',
],
]);
self::assertFalse($subject->isSingleDay());
}
}