mirror of
https://github.com/werkraum-media/calendar.git
synced 2024-12-21 12:46:08 +01:00
calendar logic
Provide data structure for month, weeks and days. Provide controller to open month, week and day. Relates: #7887
This commit is contained in:
parent
10d6e94c4d
commit
98762332f5
23 changed files with 1782 additions and 1 deletions
163
.github/workflows/ci.yaml
vendored
Normal file
163
.github/workflows/ci.yaml
vendored
Normal file
|
@ -0,0 +1,163 @@
|
|||
name: CI
|
||||
on: [push]
|
||||
jobs:
|
||||
check-composer:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Validate composer.json
|
||||
run: composer validate
|
||||
|
||||
php-linting:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
php-version:
|
||||
- 7.3
|
||||
- 7.4
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Install PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: "${{ matrix.php-version }}"
|
||||
|
||||
- name: PHP lint
|
||||
run: "find *.php Classes Tests -name '*.php' -print0 | xargs -0 -n 1 -P 4 php -l"
|
||||
|
||||
check-dependencies:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [check-composer]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Keep composer at 1.x
|
||||
run: sudo composer selfupdate --1
|
||||
|
||||
- name: Get Composer Cache Directory
|
||||
id: composer-cache
|
||||
run: |
|
||||
echo "::set-output name=dir::$(composer config cache-files-dir)"
|
||||
|
||||
- uses: actions/cache@v1
|
||||
with:
|
||||
path: ${{ steps.composer-cache.outputs.dir }}
|
||||
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-composer-
|
||||
|
||||
- name: Install dependencies
|
||||
run: composer install --prefer-dist --no-progress --no-suggest --no-plugins
|
||||
|
||||
- name: Missing composer requirements
|
||||
run: ./vendor/bin/composer-require-checker check
|
||||
|
||||
xml-linting:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [check-composer]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install xmllint
|
||||
run: sudo apt-get install libxml2-utils
|
||||
|
||||
- name: Keep composer at 1.x
|
||||
run: sudo composer selfupdate --1
|
||||
|
||||
- name: Get Composer Cache Directory
|
||||
id: composer-cache
|
||||
run: |
|
||||
echo "::set-output name=dir::$(composer config cache-files-dir)"
|
||||
|
||||
- uses: actions/cache@v1
|
||||
with:
|
||||
path: ${{ steps.composer-cache.outputs.dir }}
|
||||
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-composer-
|
||||
|
||||
- name: Install dependencies
|
||||
run: composer install --prefer-dist --no-progress --no-suggest
|
||||
|
||||
- name: PHPUnit configuration file
|
||||
run: xmllint --schema vendor/phpunit/phpunit/phpunit.xsd --noout phpunit.xml.dist
|
||||
|
||||
- name: PHPCodeSniffer configuration file
|
||||
run: xmllint --schema vendor/squizlabs/php_codesniffer/phpcs.xsd --noout phpcs.xml.dist
|
||||
|
||||
- name: Fetch schema for xliff
|
||||
run: wget https://docs.oasis-open.org/xliff/v1.2/os/xliff-core-1.2-strict.xsd --output-document=.Build/xliff-core-1.2-strict.xsd
|
||||
|
||||
- name: TYPO3 language files
|
||||
run: xmllint --schema .Build/xliff-core-1.2-strict.xsd --noout $(find Resources -name '*.xlf')
|
||||
|
||||
coding-guideline:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- check-dependencies
|
||||
- xml-linting
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Keep composer at 1.x
|
||||
run: sudo composer selfupdate --1
|
||||
|
||||
- name: Get Composer Cache Directory
|
||||
id: composer-cache
|
||||
run: |
|
||||
echo "::set-output name=dir::$(composer config cache-files-dir)"
|
||||
|
||||
- uses: actions/cache@v1
|
||||
with:
|
||||
path: ${{ steps.composer-cache.outputs.dir }}
|
||||
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-composer-
|
||||
|
||||
- name: Install dependencies
|
||||
run: composer install --prefer-dist --no-progress --no-suggest
|
||||
|
||||
- name: Coding Guideline
|
||||
run: ./vendor/bin/phpcs
|
||||
|
||||
tests:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- check-dependencies
|
||||
- xml-linting
|
||||
strategy:
|
||||
matrix:
|
||||
php-version:
|
||||
- 7.3
|
||||
- 7.4
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: "${{ matrix.php-version }}"
|
||||
|
||||
- name: Keep composer at 1.x
|
||||
run: sudo composer selfupdate --1
|
||||
|
||||
- name: Get Composer Cache Directory
|
||||
id: composer-cache
|
||||
run: |
|
||||
echo "::set-output name=dir::$(composer config cache-files-dir)"
|
||||
|
||||
- uses: actions/cache@v1
|
||||
with:
|
||||
path: ${{ steps.composer-cache.outputs.dir }}
|
||||
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-composer-
|
||||
|
||||
- name: Install dependencies
|
||||
run: composer install --prefer-dist --no-progress --no-suggest
|
||||
|
||||
- name: PHPUnit Tests
|
||||
run: ./vendor/bin/phpunit --testdox
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,2 +1,3 @@
|
|||
/.Build/
|
||||
/vendor/
|
||||
/composer.lock
|
||||
|
|
115
Classes/Controller/Frontend/CalendarController.php
Normal file
115
Classes/Controller/Frontend/CalendarController.php
Normal file
|
@ -0,0 +1,115 @@
|
|||
<?php
|
||||
|
||||
namespace WerkraumMedia\Calendar\Controller\Frontend;
|
||||
|
||||
/*
|
||||
* 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\Extbase\Annotation as Extbase;
|
||||
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
|
||||
use TYPO3\CMS\Extbase\Property\TypeConverter\DateTimeConverter;
|
||||
use WerkraumMedia\Calendar\Domain\Model\Day;
|
||||
use WerkraumMedia\Calendar\Domain\Model\Month;
|
||||
use WerkraumMedia\Calendar\Domain\Model\Week;
|
||||
|
||||
class CalendarController extends ActionController
|
||||
{
|
||||
public function initializeMonthAction()
|
||||
{
|
||||
if ($this->request->hasArgument('month') === false) {
|
||||
$this->request->setArguments([
|
||||
'month' => [
|
||||
'month' => date('m'),
|
||||
'year' => date('Y'),
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
$this->arguments->getArgument('month')
|
||||
->getPropertyMappingConfiguration()
|
||||
->allowAllProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
* @Extbase\IgnoreValidation("month")
|
||||
*/
|
||||
public function monthAction(Month $month)
|
||||
{
|
||||
$this->view->assignMultiple([
|
||||
'month' => $month,
|
||||
]);
|
||||
}
|
||||
|
||||
public function initializeWeekAction()
|
||||
{
|
||||
if ($this->request->hasArgument('week') === false) {
|
||||
$this->request->setArguments([
|
||||
'week' => [
|
||||
'week' => date('W'),
|
||||
'year' => date('Y'),
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
$this->arguments->getArgument('week')
|
||||
->getPropertyMappingConfiguration()
|
||||
->allowAllProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
* @Extbase\IgnoreValidation("week")
|
||||
*/
|
||||
public function weekAction(Week $week)
|
||||
{
|
||||
$this->view->assignMultiple([
|
||||
'week' => $week,
|
||||
]);
|
||||
}
|
||||
|
||||
public function initializeDayAction()
|
||||
{
|
||||
if ($this->request->hasArgument('day') === false) {
|
||||
$this->request->setArguments([
|
||||
'day' => new \DateTimeImmutable(),
|
||||
]);
|
||||
}
|
||||
|
||||
$propertyMappingConfiguration = $this->arguments->getArgument('day')
|
||||
->getPropertyMappingConfiguration();
|
||||
|
||||
$propertyMappingConfiguration->allowAllProperties();
|
||||
$propertyMappingConfiguration
|
||||
->forProperty('day')
|
||||
->setTypeConverterOption(
|
||||
DateTimeConverter::class,
|
||||
DateTimeConverter::CONFIGURATION_DATE_FORMAT,
|
||||
'Y-m-d'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Extbase\IgnoreValidation("day")
|
||||
*/
|
||||
public function dayAction(Day $day)
|
||||
{
|
||||
$this->view->assignMultiple([
|
||||
'day' => $day,
|
||||
]);
|
||||
}
|
||||
}
|
89
Classes/Domain/Model/Day.php
Normal file
89
Classes/Domain/Model/Day.php
Normal file
|
@ -0,0 +1,89 @@
|
|||
<?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 Day
|
||||
{
|
||||
/**
|
||||
* @var \DateTimeImmutable
|
||||
*/
|
||||
private $day;
|
||||
|
||||
/**
|
||||
* @var mixed
|
||||
*/
|
||||
private $foreignData;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $initialized = false;
|
||||
|
||||
public function __construct(
|
||||
\DateTime $day
|
||||
) {
|
||||
$this->periods = new ObjectStorage();
|
||||
$this->day = \DateTimeImmutable::createFromMutable($day)->modify('midnight');
|
||||
}
|
||||
|
||||
public function isActive(): bool
|
||||
{
|
||||
$foreignData = $this->getForeignData();
|
||||
if ($foreignData instanceof IsDayActive) {
|
||||
return $foreignData->isActive($this->getDateTimeInstance());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getForeignData()
|
||||
{
|
||||
$this->initializeForeignData();
|
||||
|
||||
return $this->foreignData;
|
||||
}
|
||||
|
||||
public function getDateTimeInstance(): \DateTimeImmutable
|
||||
{
|
||||
return $this->day;
|
||||
}
|
||||
|
||||
public function getAsUrlArgument(): array
|
||||
{
|
||||
return [
|
||||
'day' => $this->day->format('Y-m-d'),
|
||||
];
|
||||
}
|
||||
|
||||
private function initializeForeignData(): void
|
||||
{
|
||||
if ($this->initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->foreignData = GeneralUtility::makeInstance(ForeignDataFactory::class)
|
||||
->getData($this);
|
||||
}
|
||||
}
|
30
Classes/Domain/Model/ForeignDataFactory.php
Normal file
30
Classes/Domain/Model/ForeignDataFactory.php
Normal file
|
@ -0,0 +1,30 @@
|
|||
<?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.
|
||||
*/
|
||||
|
||||
interface ForeignDataFactory
|
||||
{
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function getData(Day $day);
|
||||
}
|
27
Classes/Domain/Model/IsDayActive.php
Normal file
27
Classes/Domain/Model/IsDayActive.php
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?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.
|
||||
*/
|
||||
|
||||
interface IsDayActive
|
||||
{
|
||||
public function isActive(\DateTimeImmutable $dateTime): bool;
|
||||
}
|
129
Classes/Domain/Model/Month.php
Normal file
129
Classes/Domain/Model/Month.php
Normal file
|
@ -0,0 +1,129 @@
|
|||
<?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 Month
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $month;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $year;
|
||||
|
||||
/**
|
||||
* @var Week[]
|
||||
*/
|
||||
private $weeks = [];
|
||||
|
||||
public function __construct(
|
||||
int $month,
|
||||
int $year
|
||||
) {
|
||||
$this->month = $month;
|
||||
$this->year = $year;
|
||||
}
|
||||
|
||||
public function isActive(): bool
|
||||
{
|
||||
foreach ($this->getWeeks() as $week) {
|
||||
if ($week->isActive()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getWeeks(): array
|
||||
{
|
||||
if ($this->weeks !== []) {
|
||||
return $this->weeks;
|
||||
}
|
||||
|
||||
$month = $this->getDateTimeInstance();
|
||||
$lastDay = $month->modify('last day of this month')->modify('sunday this week');
|
||||
$currentDay = $month->modify('monday this week');
|
||||
|
||||
while ($currentDay <= $lastDay) {
|
||||
$this->weeks[] = new Week(
|
||||
(int) $currentDay->format('W'),
|
||||
(int) $currentDay->format('Y')
|
||||
);
|
||||
|
||||
$currentDay = $currentDay->modify('+7 days');
|
||||
}
|
||||
|
||||
return $this->weeks;
|
||||
}
|
||||
|
||||
public function getPreviousMonth(): Month
|
||||
{
|
||||
$previousMonth = $this->month - 1;
|
||||
$previousYear = $this->year;
|
||||
|
||||
if ($previousMonth <= 0) {
|
||||
$previousMonth = 12;
|
||||
--$previousYear;
|
||||
}
|
||||
|
||||
return new self(
|
||||
$previousMonth,
|
||||
$previousYear
|
||||
);
|
||||
}
|
||||
|
||||
public function getNextMonth(): Month
|
||||
{
|
||||
$nextMonth = $this->month + 1;
|
||||
$nextYear = $this->year;
|
||||
|
||||
if ($nextMonth > 12) {
|
||||
$nextMonth = 1;
|
||||
++$nextYear;
|
||||
}
|
||||
|
||||
return new self(
|
||||
$nextMonth,
|
||||
$nextYear
|
||||
);
|
||||
}
|
||||
|
||||
public function getAsUrlArgument(): array
|
||||
{
|
||||
return [
|
||||
'month' => $this->month,
|
||||
'year' => $this->year,
|
||||
];
|
||||
}
|
||||
|
||||
public function getDateTimeInstance(): \DateTimeImmutable
|
||||
{
|
||||
return new \DateTimeImmutable($this->year . '-' . $this->month . '-01');
|
||||
}
|
||||
}
|
30
Classes/Domain/Model/NullDataFactory.php
Normal file
30
Classes/Domain/Model/NullDataFactory.php
Normal file
|
@ -0,0 +1,30 @@
|
|||
<?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.
|
||||
*/
|
||||
|
||||
class NullDataFactory implements ForeignDataFactory
|
||||
{
|
||||
public function getData(Day $day)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
118
Classes/Domain/Model/Week.php
Normal file
118
Classes/Domain/Model/Week.php
Normal file
|
@ -0,0 +1,118 @@
|
|||
<?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.
|
||||
*/
|
||||
|
||||
class Week
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $week;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $year;
|
||||
|
||||
/**
|
||||
* @var Day[]
|
||||
*/
|
||||
private $days = [];
|
||||
|
||||
public function __construct(
|
||||
int $week,
|
||||
int $year
|
||||
) {
|
||||
$this->week = $week;
|
||||
$this->year = $year;
|
||||
}
|
||||
|
||||
public function isActive(): bool
|
||||
{
|
||||
foreach ($this->getDays() as $day) {
|
||||
if ($day->isActive()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getDays(): array
|
||||
{
|
||||
if ($this->days !== []) {
|
||||
return $this->days;
|
||||
}
|
||||
|
||||
$currentDay = $this->getWeek()->modify('monday this week');
|
||||
$endOfWeek = $currentDay->modify('sunday this week');
|
||||
|
||||
while ($currentDay <= $endOfWeek) {
|
||||
$this->days[] = new Day(\DateTime::createFromImmutable($currentDay));
|
||||
$currentDay = $currentDay->modify('+1 day');
|
||||
}
|
||||
|
||||
return $this->days;
|
||||
}
|
||||
|
||||
public function getPreviousWeek(): Week
|
||||
{
|
||||
$newDay = $this->getWeek()->modify('-1 week');
|
||||
|
||||
return new self(
|
||||
(int) $newDay->format('W'),
|
||||
(int) $newDay->format('Y')
|
||||
);
|
||||
}
|
||||
|
||||
public function getNextWeek(): Week
|
||||
{
|
||||
$newDay = $this->getWeek()->modify('+1 week');
|
||||
|
||||
return new self(
|
||||
(int) $newDay->format('W'),
|
||||
(int) $newDay->format('Y')
|
||||
);
|
||||
}
|
||||
|
||||
public function getDateTimeInstance(): \DateTimeImmutable
|
||||
{
|
||||
return $this->getWeek();
|
||||
}
|
||||
|
||||
public function getAsUrlArgument(): array
|
||||
{
|
||||
return [
|
||||
'week' => $this->week,
|
||||
'year' => $this->year,
|
||||
];
|
||||
}
|
||||
|
||||
private function getWeek(): \DateTimeImmutable
|
||||
{
|
||||
$week = new \DateTimeImmutable();
|
||||
$week = $week->setISODate($this->year, $this->week);
|
||||
$week = $week->modify('thursday');
|
||||
|
||||
return $week;
|
||||
}
|
||||
}
|
8
Configuration/Services.yaml
Normal file
8
Configuration/Services.yaml
Normal file
|
@ -0,0 +1,8 @@
|
|||
services:
|
||||
_defaults:
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
public: false
|
||||
|
||||
WerkraumMedia\Calendar\:
|
||||
resource: '../Classes/*'
|
8
Resources/Private/Templates/Frontend/Calendar/Day.html
Normal file
8
Resources/Private/Templates/Frontend/Calendar/Day.html
Normal file
|
@ -0,0 +1,8 @@
|
|||
<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
|
||||
data-namespace-typo3-fluid="true">
|
||||
|
||||
<h2>{day.dateTimeInstance -> f:format.date(format: 'd.m.Y')}</h2>
|
||||
|
||||
TODO: Show periods
|
||||
Maybe remove and instead link to filtered list
|
||||
</html>
|
42
Resources/Private/Templates/Frontend/Calendar/Month.html
Normal file
42
Resources/Private/Templates/Frontend/Calendar/Month.html
Normal file
|
@ -0,0 +1,42 @@
|
|||
<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
|
||||
data-namespace-typo3-fluid="true">
|
||||
|
||||
<h2>{month.dateTimeInstance -> f:format.date(format: '%B %Y')}</h2>
|
||||
|
||||
<f:link.action action="month" controller="Frontend\Calendar" arguments="{month: month.previousMonth}">
|
||||
Prev Month
|
||||
</f:link.action>
|
||||
<f:link.action action="month" controller="Frontend\Calendar" arguments="{month: month.nextMonth}">
|
||||
Next Month
|
||||
</f:link.action>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>KW</th>
|
||||
<th>Mo</th>
|
||||
<th>Di</th>
|
||||
<th>Mi</th>
|
||||
<th>Do</th>
|
||||
<th>Fr</th>
|
||||
<th>Sa</th>
|
||||
<th>So</th>
|
||||
</tr>
|
||||
<f:for each="{month.weeks}" as="week">
|
||||
<tr class="{f:if(condition: week.active, then: 'active', else: 'inactive')}">
|
||||
<td>
|
||||
<f:link.action action="week" controller="Frontend\Calendar" arguments="{week: week.asUrlArgument}">
|
||||
{week.dateTimeInstance -> f:format.date(format: '%V')}
|
||||
</f:link.action>
|
||||
</td>
|
||||
<f:for each="{week.days}" as="day">
|
||||
<td class="{f:if(condition: day.active, then: 'active', else: 'inactive')}">
|
||||
<f:link.action action="day" controller="Frontend\Calendar" arguments="{day: day.asUrlArgument}">
|
||||
{day.dateTimeInstance -> f:format.date(format: 'd')}
|
||||
</f:link.action>
|
||||
</td>
|
||||
</f:for>
|
||||
</tr>
|
||||
</f:for>
|
||||
</table>
|
||||
|
||||
</html>
|
33
Resources/Private/Templates/Frontend/Calendar/Week.html
Normal file
33
Resources/Private/Templates/Frontend/Calendar/Week.html
Normal file
|
@ -0,0 +1,33 @@
|
|||
<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
|
||||
data-namespace-typo3-fluid="true">
|
||||
|
||||
<h2>{week.dateTimeInstance -> f:format.date(format: '%V %Y')}</h2>
|
||||
|
||||
<f:link.action action="week" controller="Frontend\Calendar" arguments="{week: week.previousWeek}">
|
||||
Prev Week
|
||||
</f:link.action>
|
||||
<f:link.action action="week" controller="Frontend\Calendar" arguments="{week: week.nextWeek}">
|
||||
Next Week
|
||||
</f:link.action>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>Mo</th>
|
||||
<th>Di</th>
|
||||
<th>Mi</th>
|
||||
<th>Do</th>
|
||||
<th>Fr</th>
|
||||
<th>Sa</th>
|
||||
<th>So</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<f:for each="{week.days}" as="day">
|
||||
<td class="{f:if(condition: day.active, then: 'active', else: 'inactive')}">
|
||||
<f:link.action action="day" controller="Frontend\Calendar" arguments="{day: day.asUrlArgument}">
|
||||
{day.dateTimeInstance -> f:format.date(format: 'd')}
|
||||
</f:link.action>
|
||||
</td>
|
||||
</f:for>
|
||||
</tr>
|
||||
</table>
|
||||
</html>
|
33
Tests/ForcePropertyTrait.php
Normal file
33
Tests/ForcePropertyTrait.php
Normal file
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
namespace WerkraumMedia\Calendar\Tests;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
trait ForcePropertyTrait
|
||||
{
|
||||
protected function forceProperty($subject, string $name, $value)
|
||||
{
|
||||
$objectReflection = new \ReflectionObject($subject);
|
||||
$property = $objectReflection->getProperty($name);
|
||||
$property->setAccessible(true);
|
||||
$property->setValue($subject, $value);
|
||||
}
|
||||
}
|
275
Tests/Unit/Controller/Frontend/CalendarControllerTest.php
Normal file
275
Tests/Unit/Controller/Frontend/CalendarControllerTest.php
Normal file
|
@ -0,0 +1,275 @@
|
|||
<?php
|
||||
|
||||
namespace WerkraumMedia\Calendar\Tests\Unit\Controller\Frontend;
|
||||
|
||||
/*
|
||||
* 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 PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Argument as ProphetArgument;
|
||||
use Prophecy\PhpUnit\ProphecyTrait;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use TYPO3\CMS\Extbase\Mvc\Controller\Argument;
|
||||
use TYPO3\CMS\Extbase\Mvc\Controller\Arguments;
|
||||
use TYPO3\CMS\Extbase\Mvc\View\ViewInterface;
|
||||
use TYPO3\CMS\Extbase\Mvc\Web\Request;
|
||||
use TYPO3\CMS\Extbase\Property\PropertyMappingConfiguration;
|
||||
use WerkraumMedia\Calendar\Controller\Frontend\CalendarController;
|
||||
use WerkraumMedia\Calendar\Domain\Model\Day;
|
||||
use WerkraumMedia\Calendar\Domain\Model\Month;
|
||||
use WerkraumMedia\Calendar\Domain\Model\Week;
|
||||
use WerkraumMedia\Calendar\Tests\ForcePropertyTrait;
|
||||
|
||||
/**
|
||||
* @covers WerkraumMedia\Calendar\Controller\Frontend\CalendarController
|
||||
* @testdox The calendar controller
|
||||
*/
|
||||
class CalendarControllerTest extends TestCase
|
||||
{
|
||||
use ProphecyTrait;
|
||||
use ForcePropertyTrait;
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function setsCurrentMonthAsDefaultArgument(): void
|
||||
{
|
||||
$subject = new CalendarController();
|
||||
|
||||
$arguments = $this->allowsMappingOfAllPropertiesForArgument('month')['arguments'];
|
||||
|
||||
$request = $this->prophesize(Request::class);
|
||||
$request->hasArgument('month')->willReturn(false);
|
||||
$request->setArguments([
|
||||
'month' => [
|
||||
'month' => date('m'),
|
||||
'year' => date('Y'),
|
||||
],
|
||||
])->shouldBeCalled();
|
||||
|
||||
$this->forceProperty($subject, 'request', $request->reveal());
|
||||
$this->forceProperty($subject, 'arguments', $arguments->reveal());
|
||||
|
||||
$subject->initializeMonthAction();
|
||||
$request->checkProphecyMethodsPredictions();
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function allowsMonthToBeMapped(): void
|
||||
{
|
||||
$subject = new CalendarController();
|
||||
|
||||
$arguments = $this->allowsMappingOfAllPropertiesForArgument('month')['arguments'];
|
||||
|
||||
$request = $this->prophesize(Request::class);
|
||||
$request->hasArgument('month')->willReturn(true);
|
||||
|
||||
$this->forceProperty($subject, 'request', $request->reveal());
|
||||
$this->forceProperty($subject, 'arguments', $arguments->reveal());
|
||||
|
||||
$subject->initializeMonthAction();
|
||||
$arguments->checkProphecyMethodsPredictions();
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function addsMonthToView(): void
|
||||
{
|
||||
$subject = new CalendarController();
|
||||
|
||||
$month = $this->prophesize(Month::class);
|
||||
$view = $this->prophesize(ViewInterface::class);
|
||||
$view->assignMultiple([
|
||||
'month' => $month->reveal(),
|
||||
])->shouldBeCalled();
|
||||
|
||||
$this->forceProperty($subject, 'view', $view->reveal());
|
||||
|
||||
$subject->monthAction($month->reveal());
|
||||
$view->checkProphecyMethodsPredictions();
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function setsCurrentWeekAsDefaultArgument(): void
|
||||
{
|
||||
$subject = new CalendarController();
|
||||
|
||||
$arguments = $this->allowsMappingOfAllPropertiesForArgument('week')['arguments'];
|
||||
|
||||
$request = $this->prophesize(Request::class);
|
||||
$request->hasArgument('week')->willReturn(false);
|
||||
$request->setArguments([
|
||||
'week' => [
|
||||
'week' => date('W'),
|
||||
'year' => date('Y'),
|
||||
],
|
||||
])->shouldBeCalled();
|
||||
|
||||
$this->forceProperty($subject, 'request', $request->reveal());
|
||||
$this->forceProperty($subject, 'arguments', $arguments->reveal());
|
||||
|
||||
$subject->initializeWeekAction();
|
||||
$request->checkProphecyMethodsPredictions();
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function allowsWeekToBeMapped(): void
|
||||
{
|
||||
$subject = new CalendarController();
|
||||
|
||||
$arguments = $this->allowsMappingOfAllPropertiesForArgument('week')['arguments'];
|
||||
|
||||
$request = $this->prophesize(Request::class);
|
||||
$request->hasArgument('week')->willReturn(true);
|
||||
|
||||
$this->forceProperty($subject, 'request', $request->reveal());
|
||||
$this->forceProperty($subject, 'arguments', $arguments->reveal());
|
||||
|
||||
$subject->initializeWeekAction();
|
||||
$arguments->checkProphecyMethodsPredictions();
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function addsWeekToView(): void
|
||||
{
|
||||
$subject = new CalendarController();
|
||||
|
||||
$week = $this->prophesize(Week::class);
|
||||
$view = $this->prophesize(ViewInterface::class);
|
||||
$view->assignMultiple([
|
||||
'week' => $week->reveal(),
|
||||
])->shouldBeCalled();
|
||||
|
||||
$this->forceProperty($subject, 'view', $view->reveal());
|
||||
|
||||
$subject->weekAction($week->reveal());
|
||||
$view->checkProphecyMethodsPredictions();
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function setsCurrentDayAsDefaultArgument(): void
|
||||
{
|
||||
$subject = new CalendarController();
|
||||
|
||||
$prophecies = $this->allowsMappingOfAllPropertiesForArgument('day');
|
||||
$propertyConfiguration = $prophecies['propertyMappingConfiguration'];
|
||||
$arguments = $prophecies['arguments'];
|
||||
|
||||
$request = $this->prophesize(Request::class);
|
||||
$request->hasArgument('day')->willReturn(false);
|
||||
$request->setArguments(ProphetArgument::that(function (array $arguments) {
|
||||
return count($arguments) === 1
|
||||
&& isset($arguments['day'])
|
||||
&& $arguments['day'] instanceof \DateTimeImmutable
|
||||
&& $arguments['day']->format('Y-m-d') === date('Y-m-d')
|
||||
;
|
||||
}))->shouldBeCalled();
|
||||
|
||||
$configuration = $this->prophesize(PropertyMappingConfiguration::class);
|
||||
$configuration->setTypeConverterOption(
|
||||
'',
|
||||
'',
|
||||
'Y-m-d'
|
||||
);
|
||||
$propertyConfiguration->forProperty('day')->willReturn($configuration);
|
||||
|
||||
$this->forceProperty($subject, 'request', $request->reveal());
|
||||
$this->forceProperty($subject, 'arguments', $arguments->reveal());
|
||||
|
||||
$subject->initializeDayAction();
|
||||
$request->checkProphecyMethodsPredictions();
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function configuredMappingForDay(): void
|
||||
{
|
||||
$subject = new CalendarController();
|
||||
|
||||
$prophecies = $this->allowsMappingOfAllPropertiesForArgument('day');
|
||||
$propertyConfiguration = $prophecies['propertyMappingConfiguration'];
|
||||
$arguments = $prophecies['arguments'];
|
||||
|
||||
$request = $this->prophesize(Request::class);
|
||||
$request->hasArgument('day')->willReturn(true);
|
||||
|
||||
$configuration = $this->prophesize(PropertyMappingConfiguration::class);
|
||||
$configuration->setTypeConverterOption(
|
||||
'',
|
||||
'',
|
||||
'Y-m-d'
|
||||
);
|
||||
$propertyConfiguration->forProperty('day')->willReturn($configuration);
|
||||
|
||||
$this->forceProperty($subject, 'request', $request->reveal());
|
||||
$this->forceProperty($subject, 'arguments', $arguments->reveal());
|
||||
|
||||
$subject->initializeDayAction();
|
||||
$arguments->checkProphecyMethodsPredictions();
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function addsDayToView(): void
|
||||
{
|
||||
$subject = new CalendarController();
|
||||
|
||||
$day = $this->prophesize(Day::class);
|
||||
$view = $this->prophesize(ViewInterface::class);
|
||||
$view->assignMultiple([
|
||||
'day' => $day->reveal(),
|
||||
])->shouldBeCalled();
|
||||
|
||||
$this->forceProperty($subject, 'view', $view->reveal());
|
||||
|
||||
$subject->dayAction($day->reveal());
|
||||
$view->checkProphecyMethodsPredictions();
|
||||
}
|
||||
|
||||
private function allowsMappingOfAllPropertiesForArgument(string $argumentName): array
|
||||
{
|
||||
$propertyMappingConfiguration = $this->prophesize(PropertyMappingConfiguration::class);
|
||||
$propertyMappingConfiguration->allowAllProperties()->shouldBeCalled();
|
||||
|
||||
$argument = $this->prophesize(Argument::class);
|
||||
$argument->getPropertyMappingConfiguration()->willReturn($propertyMappingConfiguration);
|
||||
|
||||
$arguments = $this->prophesize(Arguments::class);
|
||||
$arguments->getArgument($argumentName)->willReturn($argument->reveal());
|
||||
|
||||
return [
|
||||
'propertyMappingConfiguration' => $propertyMappingConfiguration,
|
||||
'argument' => $argument,
|
||||
'arguments' => $arguments,
|
||||
];
|
||||
}
|
||||
}
|
144
Tests/Unit/Domain/Model/DayTest.php
Normal file
144
Tests/Unit/Domain/Model/DayTest.php
Normal file
|
@ -0,0 +1,144 @@
|
|||
<?php
|
||||
|
||||
namespace WerkraumMedia\Calendar\Tests\Unit\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 PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Argument;
|
||||
use Prophecy\PhpUnit\ProphecyTrait;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Extbase\Persistence\ObjectStorage;
|
||||
use WerkraumMedia\Calendar\Domain\Model\Day;
|
||||
use WerkraumMedia\Calendar\Domain\Model\ForeignDataFactory;
|
||||
use WerkraumMedia\Calendar\Domain\Model\IsDayActive;
|
||||
use WerkraumMedia\Calendar\Domain\Model\NullDataFactory;
|
||||
use WerkraumMedia\Calendar\Tests\ForcePropertyTrait;
|
||||
|
||||
/**
|
||||
* @covers WerkraumMedia\Calendar\Domain\Model\Day
|
||||
* @testdox A day
|
||||
*/
|
||||
class DayTest extends TestCase
|
||||
{
|
||||
use ProphecyTrait;
|
||||
use ForcePropertyTrait;
|
||||
|
||||
public function tearDown(): void
|
||||
{
|
||||
GeneralUtility::purgeInstances();
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function canBeCreated(): void
|
||||
{
|
||||
$subject = new Day(
|
||||
new \DateTime()
|
||||
);
|
||||
|
||||
self::assertInstanceOf(Day::class, $subject);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function providesDateTimeInstance(): void
|
||||
{
|
||||
$dateTimeInstance = new \DateTime();
|
||||
$subject = new Day(
|
||||
$dateTimeInstance
|
||||
);
|
||||
|
||||
self::assertInstanceOf(\DateTimeImmutable::class, $subject->getDateTimeInstance());
|
||||
self::assertSame($dateTimeInstance->format('U'), $subject->getDateTimeInstance()->format('U'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function providedDateTimeInstanceHasMidnight(): void
|
||||
{
|
||||
$dateTimeInstance = new \DateTime();
|
||||
$subject = new Day(
|
||||
$dateTimeInstance
|
||||
);
|
||||
|
||||
self::assertSame('00:00:00', $subject->getDateTimeInstance()->format('H:i:s'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function providesItselfAsUrlArgument(): void
|
||||
{
|
||||
$subject = new Day(new \DateTime('2020-10-19'));
|
||||
|
||||
self::assertSame(['day' => '2020-10-19'], $subject->getAsUrlArgument());
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function isNotActiveIfNoForeignDataWithInterfaceExists(): void
|
||||
{
|
||||
$subject = new Day(new \DateTime('2020-10-19'));
|
||||
|
||||
$this->forceProperty($subject, 'initialized', true);
|
||||
|
||||
self::assertFalse($subject->isActive());
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function isNotActiveIfForeignDataIsNotActive(): void
|
||||
{
|
||||
$subject = new Day(new \DateTime('2020-10-19'));
|
||||
|
||||
$foreignData = $this->prophesize(IsDayActive::class);
|
||||
$foreignData->isActive(Argument::any())->willReturn(false);
|
||||
|
||||
$this->forceProperty($subject, 'initialized', true);
|
||||
$this->forceProperty($subject, 'foreignData', $foreignData->reveal());
|
||||
|
||||
self::assertFalse($subject->isActive());
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function initializesForeignDataViaFactory(): void
|
||||
{
|
||||
$subject = new Day(new \DateTime('2020-10-19'));
|
||||
|
||||
$foreignData = $this->prophesize(IsDayActive::class);
|
||||
$foreignData->isActive(Argument::any())->willReturn(true);
|
||||
|
||||
$factory = $this->prophesize(ForeignDataFactory::class);
|
||||
$factory->getData($subject)->willReturn($foreignData->reveal());
|
||||
|
||||
GeneralUtility::addInstance(ForeignDataFactory::class, $factory->reveal());
|
||||
|
||||
self::assertTrue($subject->isActive());
|
||||
}
|
||||
}
|
183
Tests/Unit/Domain/Model/MonthTest.php
Normal file
183
Tests/Unit/Domain/Model/MonthTest.php
Normal file
|
@ -0,0 +1,183 @@
|
|||
<?php
|
||||
|
||||
namespace WerkraumMedia\Calendar\Tests\Unit\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 PHPUnit\Framework\TestCase;
|
||||
use Prophecy\PhpUnit\ProphecyTrait;
|
||||
use WerkraumMedia\Calendar\Domain\Model\Month;
|
||||
use WerkraumMedia\Calendar\Domain\Model\Week;
|
||||
use WerkraumMedia\Calendar\Tests\ForcePropertyTrait;
|
||||
|
||||
/**
|
||||
* @covers WerkraumMedia\Calendar\Domain\Model\Month
|
||||
* @testdox A month
|
||||
*/
|
||||
class MonthTest extends TestCase
|
||||
{
|
||||
use ProphecyTrait;
|
||||
use ForcePropertyTrait;
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function canBeCreated(): void
|
||||
{
|
||||
$subject = new Month(1, 2020);
|
||||
|
||||
self::assertInstanceOf(Month::class, $subject);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function returnsPreviousMonthForSameYear(): void
|
||||
{
|
||||
$subject = new Month(2, 2020);
|
||||
|
||||
self::assertSame('01', $subject->getPreviousMonth()->getDateTimeInstance()->format('m'));
|
||||
self::assertSame('2020', $subject->getPreviousMonth()->getDateTimeInstance()->format('Y'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function returnsPreviousMonthForPreviousYear(): void
|
||||
{
|
||||
$subject = new Month(1, 2020);
|
||||
|
||||
self::assertSame('12', $subject->getPreviousMonth()->getDateTimeInstance()->format('m'));
|
||||
self::assertSame('2019', $subject->getPreviousMonth()->getDateTimeInstance()->format('Y'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function returnsNextMonthForSameYear(): void
|
||||
{
|
||||
$subject = new Month(1, 2020);
|
||||
|
||||
self::assertSame('02', $subject->getNextMonth()->getDateTimeInstance()->format('m'));
|
||||
self::assertSame('2020', $subject->getNextMonth()->getDateTimeInstance()->format('Y'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function returnsNextMonthForNextYear(): void
|
||||
{
|
||||
$subject = new Month(12, 2020);
|
||||
|
||||
self::assertSame('01', $subject->getNextMonth()->getDateTimeInstance()->format('m'));
|
||||
self::assertSame('2021', $subject->getNextMonth()->getDateTimeInstance()->format('Y'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function returnsFiveWeeksForDecember2020(): void
|
||||
{
|
||||
$subject = new Month(12, 2020);
|
||||
$weeks = $subject->getWeeks();
|
||||
|
||||
self::assertCount(5, $weeks);
|
||||
self::assertSame('2020-11-30', $weeks[0]->getDays()[0]->getDateTimeInstance()->format('Y-m-d'));
|
||||
self::assertSame('2021-01-03', $weeks[4]->getDays()[6]->getDateTimeInstance()->format('Y-m-d'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function returnsSixWeeksForNovember2020(): void
|
||||
{
|
||||
$subject = new Month(11, 2020);
|
||||
$weeks = $subject->getWeeks();
|
||||
|
||||
self::assertCount(6, $weeks);
|
||||
self::assertSame('2020-10-26', $weeks[0]->getDays()[0]->getDateTimeInstance()->format('Y-m-d'));
|
||||
self::assertSame('2020-12-06', $weeks[5]->getDays()[6]->getDateTimeInstance()->format('Y-m-d'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function returnsSameWeeksOnSecondCall(): void
|
||||
{
|
||||
$subject = new Month(11, 2020);
|
||||
|
||||
self::assertSame($subject->getWeeks(), $subject->getWeeks());
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function providesDateTimeInstance(): void
|
||||
{
|
||||
$subject = new Month(02, 2018);
|
||||
|
||||
self::assertSame('2018-02-01', $subject->getDateTimeInstance()->format('Y-m-d'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function returnsAsUrlArguments(): void
|
||||
{
|
||||
$subject = new Month(02, 2018);
|
||||
|
||||
self::assertSame([
|
||||
'month' => 2,
|
||||
'year' => 2018,
|
||||
], $subject->getAsUrlArgument());
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function returnsNotActiveIfAllWeeksAreInactive(): void
|
||||
{
|
||||
$subject = new Month(02, 2018);
|
||||
|
||||
$week = $this->prophesize(Week::class);
|
||||
$week->isActive()->willReturn(false);
|
||||
$weeks = [$week->reveal()];
|
||||
$this->forceProperty($subject, 'weeks', $weeks);
|
||||
|
||||
self::assertFalse($subject->isActive());
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function returnsActiveIfASingleWeekIsActive(): void
|
||||
{
|
||||
$subject = new Month(02, 2018);
|
||||
|
||||
$week = $this->prophesize(Week::class);
|
||||
$week->isActive()->willReturn(true);
|
||||
$week2 = $this->prophesize(Week::class);
|
||||
$week2->isActive()->willReturn(false);
|
||||
$weeks = [$week->reveal(), $week2->reveal()];
|
||||
$this->forceProperty($subject, 'weeks', $weeks);
|
||||
|
||||
self::assertTrue($subject->isActive());
|
||||
}
|
||||
}
|
45
Tests/Unit/Domain/Model/NullDataFactoryTest.php
Normal file
45
Tests/Unit/Domain/Model/NullDataFactoryTest.php
Normal file
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
|
||||
namespace WerkraumMedia\Calendar\Tests\Unit\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 Prophecy\PhpUnit\ProphecyTrait;
|
||||
use WerkraumMedia\Calendar\Domain\Model\Day;
|
||||
use WerkraumMedia\Calendar\Domain\Model\NullDataFactory;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers WerkraumMedia\Calendar\Domain\Model\NullDataFactory
|
||||
*/
|
||||
class NullDataFactoryTest extends TestCase
|
||||
{
|
||||
use ProphecyTrait;
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function returnsNull(): void
|
||||
{
|
||||
$subject = new NullDataFactory();
|
||||
$day = $this->prophesize(Day::class);
|
||||
self::assertNull($subject->getData($day->reveal()));
|
||||
}
|
||||
}
|
235
Tests/Unit/Domain/Model/WeekTest.php
Normal file
235
Tests/Unit/Domain/Model/WeekTest.php
Normal file
|
@ -0,0 +1,235 @@
|
|||
<?php
|
||||
|
||||
namespace WerkraumMedia\Calendar\Tests\Unit\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 PHPUnit\Framework\TestCase;
|
||||
use Prophecy\PhpUnit\ProphecyTrait;
|
||||
use WerkraumMedia\Calendar\Domain\Model\Day;
|
||||
use WerkraumMedia\Calendar\Domain\Model\Week;
|
||||
use WerkraumMedia\Calendar\Tests\ForcePropertyTrait;
|
||||
|
||||
/**
|
||||
* @covers WerkraumMedia\Calendar\Domain\Model\Week
|
||||
* @testdox A week
|
||||
*/
|
||||
class WeekTest extends TestCase
|
||||
{
|
||||
use ProphecyTrait;
|
||||
use ForcePropertyTrait;
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function canBeCreated(): void
|
||||
{
|
||||
$subject = new Week(1, 2020);
|
||||
|
||||
self::assertInstanceOf(Week::class, $subject);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function returnsSevenDays(): void
|
||||
{
|
||||
$subject = new Week(1, 2020);
|
||||
|
||||
self::assertCount(7, $subject->getDays());
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function returnsSameDaysOnSecondCall(): void
|
||||
{
|
||||
$subject = new Week(1, 2020);
|
||||
|
||||
self::assertSame($subject->getDays(), $subject->getDays());
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function returnsDaysForWeek1(): void
|
||||
{
|
||||
$subject = new Week(1, 2020);
|
||||
$days = $subject->getDays();
|
||||
|
||||
self::assertSame('2019-12-30', $days[0]->getDateTimeInstance()->format('Y-m-d'));
|
||||
self::assertSame('2019-12-31', $days[1]->getDateTimeInstance()->format('Y-m-d'));
|
||||
self::assertSame('2020-01-01', $days[2]->getDateTimeInstance()->format('Y-m-d'));
|
||||
self::assertSame('2020-01-02', $days[3]->getDateTimeInstance()->format('Y-m-d'));
|
||||
self::assertSame('2020-01-03', $days[4]->getDateTimeInstance()->format('Y-m-d'));
|
||||
self::assertSame('2020-01-04', $days[5]->getDateTimeInstance()->format('Y-m-d'));
|
||||
self::assertSame('2020-01-05', $days[6]->getDateTimeInstance()->format('Y-m-d'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function returnsDaysForWeek53(): void
|
||||
{
|
||||
$subject = new Week(53, 2020);
|
||||
$days = $subject->getDays();
|
||||
|
||||
self::assertSame('2020-12-28', $days[0]->getDateTimeInstance()->format('Y-m-d'));
|
||||
self::assertSame('2020-12-29', $days[1]->getDateTimeInstance()->format('Y-m-d'));
|
||||
self::assertSame('2020-12-30', $days[2]->getDateTimeInstance()->format('Y-m-d'));
|
||||
self::assertSame('2020-12-31', $days[3]->getDateTimeInstance()->format('Y-m-d'));
|
||||
self::assertSame('2021-01-01', $days[4]->getDateTimeInstance()->format('Y-m-d'));
|
||||
self::assertSame('2021-01-02', $days[5]->getDateTimeInstance()->format('Y-m-d'));
|
||||
self::assertSame('2021-01-03', $days[6]->getDateTimeInstance()->format('Y-m-d'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function returnsPreviousWeekForSameYear(): void
|
||||
{
|
||||
$subject = new Week(2, 2020);
|
||||
|
||||
self::assertSame('01', $subject->getPreviousWeek()->getDateTimeInstance()->format('W'));
|
||||
self::assertSame('2020', $subject->getPreviousWeek()->getDateTimeInstance()->format('Y'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function returnsPreviousWeekForYearSwitchFrom2019To2018(): void
|
||||
{
|
||||
$subject = new Week(1, 2019);
|
||||
|
||||
self::assertSame('52', $subject->getPreviousWeek()->getDateTimeInstance()->format('W'));
|
||||
self::assertSame('2018', $subject->getPreviousWeek()->getDateTimeInstance()->format('Y'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function returnsPreviousWeekForYearSwitchFrom2018To2017(): void
|
||||
{
|
||||
$subject = new Week(1, 2018);
|
||||
|
||||
self::assertSame('52', $subject->getPreviousWeek()->getDateTimeInstance()->format('W'));
|
||||
self::assertSame('2017', $subject->getPreviousWeek()->getDateTimeInstance()->format('Y'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function returnsPreviousWeekForPreviousYear(): void
|
||||
{
|
||||
$subject = new Week(1, 2021);
|
||||
|
||||
self::assertSame('53', $subject->getPreviousWeek()->getDateTimeInstance()->format('W'));
|
||||
self::assertSame('2020', $subject->getPreviousWeek()->getDateTimeInstance()->format('Y'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function returnsNextWeekForSameYear(): void
|
||||
{
|
||||
$subject = new Week(1, 2020);
|
||||
|
||||
self::assertSame('02', $subject->getNextWeek()->getDateTimeInstance()->format('W'));
|
||||
self::assertSame('2020', $subject->getNextWeek()->getDateTimeInstance()->format('Y'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function returnsNextWeekForNextYear(): void
|
||||
{
|
||||
$subject = new Week(53, 2020);
|
||||
|
||||
self::assertSame('01', $subject->getNextWeek()->getDateTimeInstance()->format('W'));
|
||||
self::assertSame('2021', $subject->getNextWeek()->getDateTimeInstance()->format('Y'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function returnsNextWeekForNextYearFrom2018To2019(): void
|
||||
{
|
||||
$subject = new Week(52, 2018);
|
||||
|
||||
self::assertSame('01', $subject->getNextWeek()->getDateTimeInstance()->format('W'));
|
||||
self::assertSame('2019', $subject->getNextWeek()->getDateTimeInstance()->format('Y'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function providesDateTimeInstance(): void
|
||||
{
|
||||
$subject = new Week(52, 2018);
|
||||
|
||||
self::assertSame('52', $subject->getDateTimeInstance()->format('W'));
|
||||
self::assertSame('2018-12-27 Thursday', $subject->getDateTimeInstance()->format('Y-m-d l'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function providesItselfAsUrlArgument(): void
|
||||
{
|
||||
$subject = new Week(52, 2018);
|
||||
|
||||
self::assertSame([
|
||||
'week' => 52,
|
||||
'year' => 2018,
|
||||
], $subject->getAsUrlArgument());
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function returnsNotActiveIfAllDaysAreInactive(): void
|
||||
{
|
||||
$subject = new Week(02, 2018);
|
||||
|
||||
$day = $this->prophesize(Day::class);
|
||||
$day->isActive()->willReturn(false);
|
||||
$days = [$day->reveal()];
|
||||
$this->forceProperty($subject, 'days', $days);
|
||||
|
||||
self::assertFalse($subject->isActive());
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function returnsActiveIfASingleDayActive(): void
|
||||
{
|
||||
$subject = new Week(02, 2018);
|
||||
|
||||
$day = $this->prophesize(Day::class);
|
||||
$day->isActive()->willReturn(true);
|
||||
$day2 = $this->prophesize(Day::class);
|
||||
$day2->isActive()->willReturn(false);
|
||||
$days = [$day->reveal(), $day2->reveal()];
|
||||
$this->forceProperty($subject, 'days', $days);
|
||||
|
||||
self::assertTrue($subject->isActive());
|
||||
}
|
||||
}
|
|
@ -13,6 +13,7 @@
|
|||
"sort-packages": true
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.3.0 || ^7.4.0",
|
||||
"typo3/cms-core": "^10.4",
|
||||
"typo3/cms-extbase": "^10.4"
|
||||
},
|
||||
|
@ -28,8 +29,10 @@
|
|||
},
|
||||
"require-dev": {
|
||||
"jangregor/phpstan-prophecy": "^0.6.2",
|
||||
"maglnet/composer-require-checker": "^2.1",
|
||||
"phpspec/prophecy-phpunit": "^2.0",
|
||||
"phpunit/phpunit": "^9.4"
|
||||
"phpunit/phpunit": "^9.4",
|
||||
"squizlabs/php_codesniffer": "^3.5"
|
||||
},
|
||||
"extra": {
|
||||
"typo3/cms": {
|
||||
|
|
21
ext_emconf.php
Normal file
21
ext_emconf.php
Normal file
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
$EM_CONF['calendar'] = [
|
||||
'title' => 'Calendar',
|
||||
'description' => 'API for extensions to create calendar',
|
||||
'category' => 'misc',
|
||||
'author' => 'Daniel Siepmann',
|
||||
'author_email' => 'coding@daniel-siepmann.de',
|
||||
'author_company' => 'Codappix GmbH',
|
||||
'state' => 'alpha',
|
||||
'uploadfolder' => 0,
|
||||
'clearCacheOnLoad' => 0,
|
||||
'version' => '1.0.0',
|
||||
'constraints' => [
|
||||
'depends' => [
|
||||
'typo3' => '*',
|
||||
],
|
||||
'conflicts' => [],
|
||||
'suggests' => [],
|
||||
],
|
||||
];
|
19
phpcs.xml.dist
Normal file
19
phpcs.xml.dist
Normal file
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0"?>
|
||||
<ruleset name="project">
|
||||
<description>This project coding standard</description>
|
||||
|
||||
<file>Classes/</file>
|
||||
<file>Tests/</file>
|
||||
|
||||
<!-- Set default settings -->
|
||||
<arg value="sp"/>
|
||||
<arg name="colors"/>
|
||||
<arg name="encoding" value="utf-8" />
|
||||
<arg name="extensions" value="php" />
|
||||
|
||||
<!-- Base rules -->
|
||||
<rule ref="PSR12" />
|
||||
<rule ref="Generic.Files.LineLength.TooLong">
|
||||
<exclude-pattern>/Tests/*</exclude-pattern>
|
||||
</rule>
|
||||
</ruleset>
|
30
phpunit.xml.dist
Normal file
30
phpunit.xml.dist
Normal file
|
@ -0,0 +1,30 @@
|
|||
<?xml version="1.0"?>
|
||||
<phpunit
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd"
|
||||
backupGlobals="false"
|
||||
backupStaticAttributes="false"
|
||||
colors="true"
|
||||
convertErrorsToExceptions="true"
|
||||
convertWarningsToExceptions="true"
|
||||
forceCoversAnnotation="false"
|
||||
processIsolation="false"
|
||||
stopOnError="false"
|
||||
stopOnFailure="false"
|
||||
stopOnIncomplete="false"
|
||||
stopOnSkipped="false"
|
||||
verbose="false"
|
||||
>
|
||||
|
||||
<testsuites>
|
||||
<testsuite name="unit">
|
||||
<directory>Tests/Unit/</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
||||
<coverage>
|
||||
<include>
|
||||
<directory suffix=".php">Classes</directory>
|
||||
</include>
|
||||
</coverage>
|
||||
</phpunit>
|
Loading…
Reference in a new issue