Add support for years

Add new action and model.

Also allow to get days of year and month.
Not always a week is helpful, sometimes all days of year or month are
more helpful.
This commit is contained in:
Daniel Siepmann 2021-02-23 13:04:29 +01:00
parent 6fff1efe49
commit 883dec188b
Signed by: Daniel Siepmann
GPG key ID: 33D6629915560EF4
7 changed files with 418 additions and 1 deletions

View file

@ -27,9 +27,35 @@ use TYPO3\CMS\Extbase\Property\TypeConverter\DateTimeConverter;
use WerkraumMedia\Calendar\Domain\Model\Day; use WerkraumMedia\Calendar\Domain\Model\Day;
use WerkraumMedia\Calendar\Domain\Model\Month; use WerkraumMedia\Calendar\Domain\Model\Month;
use WerkraumMedia\Calendar\Domain\Model\Week; use WerkraumMedia\Calendar\Domain\Model\Week;
use WerkraumMedia\Calendar\Domain\Model\Year;
class CalendarController extends ActionController class CalendarController extends ActionController
{ {
public function initializeYearAction()
{
if ($this->request->hasArgument('year') === false) {
$this->request->setArguments([
'year' => [
'year' => date('Y'),
],
]);
}
$this->arguments->getArgument('year')
->getPropertyMappingConfiguration()
->allowAllProperties();
}
/**
* @Extbase\IgnoreValidation("year")
*/
public function yearAction(Year $year)
{
$this->view->assignMultiple([
'year' => $year,
]);
}
public function initializeMonthAction() public function initializeMonthAction()
{ {
if ($this->request->hasArgument('month') === false) { if ($this->request->hasArgument('month') === false) {

View file

@ -24,7 +24,8 @@ namespace WerkraumMedia\Calendar\Domain\Model;
interface ForeignDataFactory interface ForeignDataFactory
{ {
/** /**
* * Receives a specific day and may return arbirtrary data.
* This data is attached to the day and available through getter.
*/ */
public function getData(Day $day); public function getData(Day $day);
} }

View file

@ -41,6 +41,11 @@ class Month
*/ */
private $weeks = []; private $weeks = [];
/**
* @var Day[]
*/
private $days = [];
public function __construct( public function __construct(
int $month, int $month,
int $year int $year
@ -82,6 +87,23 @@ class Month
return $this->weeks; return $this->weeks;
} }
public function getDays(): array
{
if ($this->days !== []) {
return $this->days;
}
$currentDay = $this->getDateTimeInstance()->modify('first day of this month');
$endOfWeek = $this->getDateTimeInstance()->modify('last day of this month');
while ($currentDay <= $endOfWeek) {
$this->days[] = new Day(\DateTime::createFromImmutable($currentDay));
$currentDay = $currentDay->modify('+1 day');
}
return $this->days;
}
public function getPreviousMonth(): Month public function getPreviousMonth(): Month
{ {
$previousMonth = $this->month - 1; $previousMonth = $this->month - 1;

View file

@ -0,0 +1,109 @@
<?php
namespace WerkraumMedia\Calendar\Domain\Model;
/*
* Copyright (C) 2020 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 TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Persistence\ObjectStorage;
class Year
{
/**
* @var int
*/
private $year;
/**
* @var Month[]
*/
private $months = [];
public function __construct(
int $year
) {
$this->year = $year;
}
public function isActive(): bool
{
foreach ($this->getMonths() as $month) {
if ($month->isActive()) {
return true;
}
}
return false;
}
public function getMonths(): array
{
if ($this->months !== []) {
return $this->months;
}
$lastMonth = new \DateTimeImmutable($this->year . '-12-31');
$currentMonth = new \DateTimeImmutable($this->year . '-01-01');
while ($currentMonth <= $lastMonth) {
$this->months[] = new Month(
(int) $currentMonth->format('n'),
$this->year
);
$currentMonth = $currentMonth->modify('+1 month');
}
return $this->months;
}
public function getDays(): array
{
$days = [];
foreach ($this->getMonths() as $month) {
$days = array_merge($days, $month->getDays());
}
return $days;
}
public function getPreviousYear(): Year
{
return new self($this->year - 1);
}
public function getNextYear(): Year
{
return new self($this->year + 1);
}
public function getAsUrlArgument(): array
{
return [
'year' => $this->year,
];
}
public function getDateTimeInstance(): \DateTimeImmutable
{
return new \DateTimeImmutable($this->year . '-01-01');
}
}

View file

@ -34,6 +34,7 @@ use WerkraumMedia\Calendar\Controller\Frontend\CalendarController;
use WerkraumMedia\Calendar\Domain\Model\Day; use WerkraumMedia\Calendar\Domain\Model\Day;
use WerkraumMedia\Calendar\Domain\Model\Month; use WerkraumMedia\Calendar\Domain\Model\Month;
use WerkraumMedia\Calendar\Domain\Model\Week; use WerkraumMedia\Calendar\Domain\Model\Week;
use WerkraumMedia\Calendar\Domain\Model\Year;
use WerkraumMedia\Calendar\Tests\ForcePropertyTrait; use WerkraumMedia\Calendar\Tests\ForcePropertyTrait;
/** /**
@ -45,6 +46,68 @@ class CalendarControllerTest extends TestCase
use ProphecyTrait; use ProphecyTrait;
use ForcePropertyTrait; use ForcePropertyTrait;
/**
* @test
*/
public function setsCurrentYearAsDefaultArgument(): void
{
$subject = new CalendarController();
$arguments = $this->allowsMappingOfAllPropertiesForArgument('year')['arguments'];
$request = $this->prophesize(Request::class);
$request->hasArgument('year')->willReturn(false);
$request->setArguments([
'year' => [
'year' => date('Y'),
],
])->shouldBeCalled();
$this->forceProperty($subject, 'request', $request->reveal());
$this->forceProperty($subject, 'arguments', $arguments->reveal());
$subject->initializeYearAction();
$request->checkProphecyMethodsPredictions();
}
/**
* @test
*/
public function allowsYearToBeMapped(): void
{
$subject = new CalendarController();
$arguments = $this->allowsMappingOfAllPropertiesForArgument('year')['arguments'];
$request = $this->prophesize(Request::class);
$request->hasArgument('year')->willReturn(true);
$this->forceProperty($subject, 'request', $request->reveal());
$this->forceProperty($subject, 'arguments', $arguments->reveal());
$subject->initializeYearAction();
$arguments->checkProphecyMethodsPredictions();
}
/**
* @test
*/
public function addsYearToView(): void
{
$subject = new CalendarController();
$year = $this->prophesize(Year::class);
$view = $this->prophesize(ViewInterface::class);
$view->assignMultiple([
'year' => $year->reveal(),
])->shouldBeCalled();
$this->forceProperty($subject, 'view', $view->reveal());
$subject->yearAction($year->reveal());
$view->checkProphecyMethodsPredictions();
}
/** /**
* @test * @test
*/ */

View file

@ -126,6 +126,44 @@ class MonthTest extends TestCase
self::assertSame($subject->getWeeks(), $subject->getWeeks()); self::assertSame($subject->getWeeks(), $subject->getWeeks());
} }
/**
* @test
*/
public function returnsAllDaysOfTheFebruaryMonth2021(): void
{
$subject = new Month(02, 2021);
$result = $subject->getDays();
self::assertCount(28, $result);
self::assertSame('2021-02-01', $result[0]->getDateTimeInstance()->format('Y-m-d'));
self::assertSame('2021-02-28', $result[27]->getDateTimeInstance()->format('Y-m-d'));
}
/**
* @test
*/
public function returnsAllDaysOfTheJuneMonth2021(): void
{
$subject = new Month(06, 2021);
$result = $subject->getDays();
self::assertCount(30, $result);
self::assertSame('2021-06-01', $result[0]->getDateTimeInstance()->format('Y-m-d'));
self::assertSame('2021-06-30', $result[29]->getDateTimeInstance()->format('Y-m-d'));
}
/**
* @test
*/
public function returnsSameDaysOnSecondCall(): void
{
$subject = new Month(06, 2021);
self::assertSame($subject->getDays(), $subject->getDays());
}
/** /**
* @test * @test
*/ */

View file

@ -0,0 +1,158 @@
<?php
namespace WerkraumMedia\Calendar\Tests\Unit\Domain\Model;
/*
* 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 Prophecy\PhpUnit\ProphecyTrait;
use WerkraumMedia\Calendar\Domain\Model\Month;
use WerkraumMedia\Calendar\Domain\Model\Year;
use WerkraumMedia\Calendar\Tests\ForcePropertyTrait;
/**
* @covers WerkraumMedia\Calendar\Domain\Model\Year
* @testdox A year
*/
class YearTest extends TestCase
{
use ProphecyTrait;
use ForcePropertyTrait;
/**
* @test
*/
public function canBeCreated(): void
{
$subject = new Year(2020);
self::assertInstanceOf(Year::class, $subject);
}
/**
* @test
*/
public function returnsPreviousYear(): void
{
$subject = new Year(2020);
$result = $subject->getPreviousYear();
self::assertInstanceOf(Year::class, $result);
self::assertSame('2019', $result->getDateTimeInstance()->format('Y'));
}
/**
* @test
*/
public function returnsNextYear(): void
{
$subject = new Year(2020);
$result = $subject->getNextYear();
self::assertInstanceOf(Year::class, $result);
self::assertSame('2021', $result->getDateTimeInstance()->format('Y'));
}
/**
* @test
*/
public function returnsAsUrlArguments(): void
{
$subject = new Year(2020);
self::assertSame([
'year' => 2020,
], $subject->getAsUrlArgument());
}
/**
* @test
*/
public function returnsMonthsForYear2020(): void
{
$subject = new Year(2020);
$result = $subject->getMonths();
self::assertCount(12, $result);
foreach ($result as $index => $month) {
self::assertInstanceOf(Month::class, $month);
$monthNumber = $index + 1;
self::assertSame((string) $monthNumber, $month->getDateTimeInstance()->format('n'));
}
}
/**
* @test
*/
public function returnsSameMonthsOnSecondCall(): void
{
$subject = new Year(2020);
self::assertSame($subject->getMonths(), $subject->getMonths());
}
/**
* @test
*/
public function returnsAllDaysFor2020(): void
{
$subject = new Year(2020);
$result = $subject->getDays();
self::assertCount(366, $result);
self::assertSame('2020-01-01', $result[0]->getDateTimeInstance()->format('Y-m-d'));
self::assertSame('2020-12-31', $result[365]->getDateTimeInstance()->format('Y-m-d'));
}
/**
* @test
*/
public function returnsNotActiveIfAllMonthsAreInactive(): void
{
$subject = new Year(2020);
$month = $this->prophesize(Month::class);
$month->isActive()->willReturn(false);
$months = [$month->reveal()];
$this->forceProperty($subject, 'months', $months);
self::assertFalse($subject->isActive());
}
/**
* @test
*/
public function returnsActiveIfASingleMonthIsActive(): void
{
$subject = new Year(2020);
$month = $this->prophesize(Month::class);
$month->isActive()->willReturn(true);
$months = [$month->reveal()];
$this->forceProperty($subject, 'months', $months);
self::assertTrue($subject->isActive());
}
}