Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
171 changes: 171 additions & 0 deletions src/TemporalExpression/Builder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
<?php
namespace Riskio\Schedule\TemporalExpression;

use Riskio\Schedule\TemporalExpression\Collection\Intersection;
use Riskio\Schedule\TemporalExpression\Collection\Union;
use Riskio\Schedule\TemporalExpression\DayInMonth;
use Riskio\Schedule\TemporalExpression\DayInWeek;
use Riskio\Schedule\TemporalExpression\MonthInYear;
use Riskio\Schedule\TemporalExpression\Semester;
use Riskio\Schedule\TemporalExpression\TemporalExpressionInterface;
use Riskio\Schedule\TemporalExpression\Trimester;
use Riskio\Schedule\TemporalExpression\Year;
use SplStack;

/**
* @method DayInWeek dayInWeek() dayInWeek(int $dayIndex)
* @method DayInMonth dayInMonth() dayInMonth(int $dayIndex)
* @method MonthInYear monthInYear() monthInYear(int $monthIndex)
* @method Semester semester() semester(int $semester)
* @method Trimester trimester() trimester(int $trimester)
* @method Year year() year(int $year)
*/
class Builder
{
const JANUARY = 1;
const FEBRUARY = 2;
const MARCH = 3;
const APRIL = 4;
const MAY = 5;
const JUNE = 6;
const JULY = 7;
const AUGUST = 8;
const SEPTEMBER = 9;
const OCTOBER = 10;
const NOVEMBER = 11;
const DECEMBER = 12;

const SUNDAY = 0;
const MONDAY = 1;
const TUESDAY = 2;
const WEDNESDAY = 3;
const THURSDAY = 4;
const FRIDAY = 5;
const SATURDAY = 6;

/**
* @var Factory
*/
protected $factory;

/**
* @var TemporalExpressionInterface
*/
protected $expression;

/**
* @var SplStack
*/
protected $expressionStack;

public function __construct()
{
$this->expressionStack = new SplStack();
}

/**
* @return Factory
*/
public function getFactory()
{
if (!$this->factory) {
$this->factory = new Factory();
}

return $this->factory;
}

/**
* @param Factory $factory
*/
public function setFactory(Factory $factory)
{
$this->factory = $factory;
}

/**
* @return self
*/
public function startUnion()
{
$this->expressionStack->push(new Union());

return $this;
}

/**
* @return self
* @throws Exception\BadMethodCallException
*/
public function endUnion()
{
$expression = $this->expressionStack->pop();
if (!$expression instanceof Union) {
throw new Exception\BadMethodCallException('Another composite must be ended before');
}

$this->aggregateExpression($expression);

return $this;
}

/**
* @return self
*/
public function startIntersect()
{
$this->expressionStack->push(new Intersection());

return $this;
}

/**
* @return self
* @throws Exception\BadMethodCallException
*/
public function endIntersect()
{
$expression = $this->expressionStack->pop();
if (!$expression instanceof Intersection) {
throw new Exception\BadMethodCallException('Another composite must be ended before');
}

$this->aggregateExpression($expression);

return $this;
}

public function __call($name, $arguments)
{
$expression = $this->getFactory()->createTemporalExpression($name, $arguments);

$this->aggregateExpression($expression);

return $this;
}

/**
* @return TemporalExpressionInterface
* @throws Exception\BadMethodCallException
*/
public function getExpression()
{
if ($this->expressionStack->count() > 0) {
throw new Exception\BadMethodCallException('The expression cannot be created');
}

return $this->expression;
}

private function aggregateExpression(TemporalExpressionInterface $expression)
{
if ($this->expressionStack->count() == 0) {
$this->expression = $expression;
} else {
$this->expressionStack->rewind();

$composite = $this->expressionStack->current();
$composite->addElement($expression);
}
}
}
9 changes: 9 additions & 0 deletions src/TemporalExpression/Exception/BadMethodCallException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php
namespace Riskio\Schedule\TemporalExpression\Exception;

use Riskio\Schedule\Exception\ExceptionInterface;

class BadMethodCallException
extends \BadMethodCallException
implements ExceptionInterface
{}
8 changes: 8 additions & 0 deletions src/TemporalExpression/Exception/UnexpectedValueException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php
namespace Riskio\Schedule\TemporalExpression\Exception;

use Riskio\Schedule\Exception\UnexpectedValueException as BaseUnexpectedValueException;

class UnexpectedValueException
extends BaseUnexpectedValueException
{}
65 changes: 65 additions & 0 deletions src/TemporalExpression/Factory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php
namespace Riskio\Schedule\TemporalExpression;

class Factory
{
/**
* @var array
*/
protected $expressions = [
'dayInMonth' => DayInMonth::class,
'dayInWeek' => DayInWeek::class,
'monthInYear' => MonthInYear::class,
'semester' => Semester::class,
'trimester' => Trimester::class,
'year' => Year::class,
];

/**
* @param string $name
* @param TemporalExpressionInterface $expression
* @return self
*/
public function addTemporalExpression($name, TemporalExpressionInterface $expression)
{
if ($this->hasTemporalExpression($name)) {
throw new Exception\UnexpectedValueException(sprintf(
'The temporal expression "%s" already exists',
$name
));
}

$this->expressions[$name] = $expression;

return $this;
}

/**
* @param string $name
* @return bool
*/
public function hasTemporalExpression($name)
{
return array_key_exists($name, $this->expressions);
}

/**
* @param string $name
* @param array $params
* @return TemporalExpressionInterface
* @throws Exception\UnexpectedValueException
*/
public function createTemporalExpression($name, array $params = [])
{
if (!$this->hasTemporalExpression($name)) {
throw new Exception\UnexpectedValueException(sprintf(
'Temporal expression "%s" does not exists',
$name
));
}

$class = new \ReflectionClass($this->expressions[$name]);

return $class->newInstanceArgs($params);
}
}
45 changes: 45 additions & 0 deletions tests/TemporalExpression/BuilderTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php
namespace Riskio\ScheduleTest\TemporalExpression;

use Riskio\Schedule\TemporalExpression\TemporalExpressionInterface;
use Riskio\Schedule\TemporalExpression\Builder;

class BuilderTest extends \PHPUnit_Framework_TestCase
{
public function testIncludesDateWhenProvidedDateAtSameMonthDayShouldReturnTrue()
{
$builder = new Builder();

$temporalExpression = $builder
->startUnion()
// tous les lundi du mois de mars
->startIntersect()
->dayInWeek(Builder::MONDAY)
->monthInYear(Builder::MARCH)
->endIntersect()

// tous les jours du mois de mai
->monthInYear(Builder::MAY)

// tous les jours de l'année 2016
->year(2016)

// tous les jours du 1er semestre 2017
->startIntersect()
->semester(1)
->year(2017)
->endIntersect()

->endUnion()
->getExpression();

$this->assertInstanceOf(TemporalExpressionInterface::class, $temporalExpression);

$this->assertTrue($temporalExpression->includes(new \DateTime('2015-03-02')));
$this->assertTrue($temporalExpression->includes(new \DateTime('2015-03-09')));
$this->assertFalse($temporalExpression->includes(new \DateTime('2015-03-03')));
$this->assertFalse($temporalExpression->includes(new \DateTime('2015-04-02')));
$this->assertTrue($temporalExpression->includes(new \DateTime('2015-05-15')));
$this->assertTrue($temporalExpression->includes(new \DateTime('2016-09-15')));
}
}