mirror of
https://github.com/rlanvin/php-rrule.git
synced 2025-02-26 15:54:14 +01:00
parent
5e84e08893
commit
b2f0dd16b1
@ -15,6 +15,7 @@
|
|||||||
- `getNthOccurrencesBefore`
|
- `getNthOccurrencesBefore`
|
||||||
- `getNthOccurrencesAfter`
|
- `getNthOccurrencesAfter`
|
||||||
- `getNthOccurrencesFrom`
|
- `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
|
## [1.6.3] - 2019-01-13
|
||||||
|
|
||||||
|
102
src/Event.php
Executable file
102
src/Event.php
Executable 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
145
src/Proxy.php
Executable 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
20
src/ProxyIterator.php
Executable 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
82
tests/ProxyTest.php
Executable 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')));
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user