1
0
mirror of https://github.com/rlanvin/php-rrule.git synced 2024-11-28 05:24:10 +01:00

Draft of a Proxy class to work with Event

Ref #63
Ref #4
This commit is contained in:
rlanvin 2019-01-13 16:42:40 +00:00
parent 5e84e08893
commit b2f0dd16b1
5 changed files with 350 additions and 0 deletions

View File

@ -15,6 +15,7 @@
- `getNthOccurrencesBefore`
- `getNthOccurrencesAfter`
- `getNthOccurrencesFrom`
- New classes: `Proxy` and `Event` to work with events (a date + a duration) instead of simple occurrence (a date)
## [1.6.3] - 2019-01-13

102
src/Event.php Executable file
View File

@ -0,0 +1,102 @@
<?php
/**
* Licensed under the MIT license.
*
* For the full copyright and license information, please view the LICENSE file.
*
* @author Rémi Lanvin <remi@cloudconnected.fr>
* @link https://github.com/rlanvin/php-rrule
*/
namespace RRule;
/**
* Helper class to work with event (a start time and a duration)
*/
class Event
{
/**
* @var \DateTimeInterface
*/
protected $start_date;
/**
* @var \DateTimeInterface
*/
protected $end_date;
/**
* @var \DateInterval
*/
protected $duration;
public function __construct(\DateTimeInterface $start_date, $duration)
{
$this->start_date = $start_date;
$this->duration = self::parseDuration($duration);
}
/**
* @return bool
*/
public function occursAt($date)
{
$date = RRule::parseDate($date);
return $this->start_date >= $date && $this->getEnd() <= $date;
}
/**
* @return \DateTimeInterface
*/
public function getStart()
{
return clone $this->start_date;
}
/**
* @return \DateInterval
*/
public function getDuration()
{
return $this->duration;
}
/**
* @return \DateTimeInterface
*/
public function getEnd()
{
if ( $this->end_date === null ) {
$this->end_date = $this->start_date->add($this->duration);
}
return clone $this->end_date;
}
static public function parseDuration($duration)
{
if ( is_numeric($duration) ) {
if ( $duration < 0 ) {
throw new \InvalidArgumentException("Duration must be a positive integer");
}
// duration is a integer in seconds
return \DateInterval::createFromDateString("$duration seconds");
}
if ( is_string($duration) ) {
if ( $duration[0] == 'P' ) {
// 'P3M'
return new \DateInterval($duration);
}
else {
// '3 months'
return \DateInterval::createFromDateString($duration);
}
}
throw new \InvalidArgumentException('Could not parse the duration');
}
}

145
src/Proxy.php Executable file
View File

@ -0,0 +1,145 @@
<?php
/**
* Licensed under the MIT license.
*
* For the full copyright and license information, please view the LICENSE file.
*
* @author Rémi Lanvin <remi@cloudconnected.fr>
* @link https://github.com/rlanvin/php-rrule
*/
namespace RRule;
/**
* Simple proxy class to convert the results into something else.
*
* Designed as an example how to work with events (date+duration) instead of occurrences (date only).
*
* Example:
* $rrule = new Proxy(
* new RRule("DTSTART:20170101\nRRULE:FREQ=DAILY;COUNT=2;INTERVAL=10"),
* function (\DateTimeInterface $occurrence) {
* return new Event($occurrence, 3600);
* }
* );
*/
class Proxy implements \ArrayAccess, \Countable, \IteratorAggregate
{
/**
* @var RRuleInterface
*/
protected $rrule;
/**
* @var \Callable
*/
protected $factory;
public function __construct(RRuleInterface $rrule, callable $factory)
{
$this->rrule = $rrule;
$this->factory = $factory;
}
/**
* @return \Iterator
*/
public function getOccurrences($limit = null)
{
$occurrences = $this->rrule->getOccurrences($limit);
return new ProxyIterator(new \ArrayIterator($occurrences), $this->factory);
}
/**
* @return \Iterator
*/
public function getOccurrencesBetween($begin, $end, $limit = null)
{
$occurrences = $this->rrule->getOccurrencesBetween($begin, $end, $limit);
return new ProxyIterator(new \ArrayIterator($occurrences), $this->factory);
}
/**
* @return \Iterator
*/
public function getOccurrencesAfter($date, $inclusive = false, $limit = null)
{
$occurrences = $this->rrule->getNthOccurrenceAfter($date, $inclusive, $limit);
return new ProxyIterator(new \ArrayIterator($occurrences), $this->factory);
}
public function getNthOccurrenceAfter($date, $index)
{
$occurrence = $this->rrule->getNthOccurrenceAfter($date, $index);
return call_user_func_array($this->factory, [$occurrence]);
}
/**
* @return \Iterator
*/
public function getOccurrencesBefore($date, $inclusive = false, $limit = null)
{
$occurrences = $this->rrule->getOccurrencesBefore($date, $inclusive, $limit);
return new ProxyIterator(new \ArrayIterator($occurrences), $this->factory);
}
public function getNthOccurrenceBefore($date, $index)
{
$occurrence = $this->rrule->getNthOccurrenceBefore($date, $index);
return call_user_func_array($this->factory, [$occurrence]);
}
public function getNthOccurrenceFrom($date, $index)
{
$occurrence = $this->rrule->getNthOccurrenceFrom($date, $index);
return call_user_func_array($this->factory, [$occurrence]);
}
public function isFinite()
{
return $this->rrule->isFinite();
}
public function isInfinite()
{
return $this->rrule->isInfinite();
}
public function occursAt($date)
{
return $this->rrule->occursAt();
}
public function offsetExists($offset)
{
return $this->rrule->offsetExists($offset);
}
public function offsetGet($offset)
{
$occurrence = $this->rrule->offsetGet($offset);
return call_user_func_array($this->factory, [$occurrence]);
}
public function offsetSet($offset, $value)
{
return $this->rrule->offsetSet($offset, $value);
}
public function offsetUnset($offset)
{
return $this->rrule->offsetUnset($offset);
}
public function count()
{
return $this->rrule->count();
}
public function getIterator()
{
return new ProxyIterator($this->rrule, $this->factory);
}
}

20
src/ProxyIterator.php Executable file
View File

@ -0,0 +1,20 @@
<?php
namespace RRule;
class ProxyIterator extends \IteratorIterator
{
protected $factory;
public function __construct(\Traversable $iterator, callable $factory)
{
$this->factory = $factory;
parent::__construct($iterator);
}
public function current()
{
return call_user_func_array($this->factory, [parent::current()]);
}
}

82
tests/ProxyTest.php Executable file
View File

@ -0,0 +1,82 @@
<?php
namespace RRule\Tests;
use RRule\RRule;
use RRule\Proxy;
use PHPUnit\Framework\TestCase;
class ProxyTest extends TestCase
{
public function testIterator()
{
$proxy = new Proxy(
new RRule([
'FREQ' => 'MONTHLY',
'COUNT' => 3,
'BYMONTHDAY' => 31,
'DTSTART' => '1997-09-02'
]),
function (\DateTimeInterface $occurrence) {
return new \RRule\Event($occurrence, 3600);
}
);
$expected = [
new \RRule\Event(date_create('1997-10-31'), 3600),
new \RRule\Event(date_create('1997-12-31'), 3600),
new \RRule\Event(date_create('1998-01-31'), 3600),
];
$n = 0;
foreach ( $proxy as $event ) {
$this->assertEquals($expected[$n],$event);
$n++;
}
}
public function testGetOccurrences()
{
$proxy = new Proxy(
new RRule([
'FREQ' => 'MONTHLY',
'COUNT' => 3,
'BYMONTHDAY' => 31,
'DTSTART' => '1997-09-02'
]),
function (\DateTimeInterface $occurrence) {
return new \RRule\Event($occurrence, 3600);
}
);
$expected = [
new \RRule\Event(date_create('1997-10-31'), 3600),
new \RRule\Event(date_create('1997-12-31'), 3600),
new \RRule\Event(date_create('1998-01-31'), 3600),
];
$this->assertEquals($expected, iterator_to_array($proxy->getOccurrences()));
}
public function testGetOccurrencesBetween()
{
$proxy = new Proxy(
new RRule([
'FREQ' => 'MONTHLY',
'COUNT' => 3,
'BYMONTHDAY' => 31,
'DTSTART' => '1997-09-02'
]),
function (\DateTimeInterface $occurrence) {
return new \RRule\Event($occurrence, 3600);
}
);
$expected = [
new \RRule\Event(date_create('1997-10-31'), 3600),
new \RRule\Event(date_create('1997-12-31'), 3600)
];
$this->assertEquals($expected, iterator_to_array($proxy->getOccurrencesBetween('1997-10-31', '1997-12-31')));
}
}