diff --git a/src/TemporalExpression/Builder.php b/src/TemporalExpression/Builder.php new file mode 100644 index 0000000..651ef7a --- /dev/null +++ b/src/TemporalExpression/Builder.php @@ -0,0 +1,171 @@ +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); + } + } +} diff --git a/src/TemporalExpression/Exception/BadMethodCallException.php b/src/TemporalExpression/Exception/BadMethodCallException.php new file mode 100644 index 0000000..bc457c2 --- /dev/null +++ b/src/TemporalExpression/Exception/BadMethodCallException.php @@ -0,0 +1,9 @@ + 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); + } +} diff --git a/tests/TemporalExpression/BuilderTest.php b/tests/TemporalExpression/BuilderTest.php new file mode 100644 index 0000000..a1a95cf --- /dev/null +++ b/tests/TemporalExpression/BuilderTest.php @@ -0,0 +1,45 @@ +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'))); + } +}