Last active
July 19, 2018 23:01
-
-
Save jmwebservices/fe317271e74c5f5f3a819b2c604053fd to your computer and use it in GitHub Desktop.
Apply filters over the iterable values of a DatePeriod object.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Apply filters over the iterable values of a DatePeriod object | |
* | |
* @method self monday Include Mondays while iterating the DatePeriod | |
* @method self tuesday Include Tuesdays while iterating the DatePeriod | |
* @method self wednesday Include Wednesdays while iterating the DatePeriod | |
* @method self thursday Include Thursdays while iterating the DatePeriod | |
* @method self friday Include Fridays while iterating the DatePeriod | |
* @method self saturday Include Saturdays while iterating the DatePeriod | |
* @method self sunday Include Sundays while iterating the DatePeriod | |
* | |
* @method self weekdays Include weekdays while iterating the DatePeriod | |
* @method self weekends Include weekends while iterating the DatePeriod | |
* | |
* @method self am Include AM DateTimes while iterating the DatePeriod | |
* @method self pm Include PM DateTimes while iterating the DatePeriod | |
* | |
* @method self january Include days in January while iterating the DatePeriod | |
* @method self february Include days in February while iterating the DatePeriod | |
* @method self march Include days in March while iterating the DatePeriod | |
* @method self april Include days in April while iterating the DatePeriod | |
* @method self may Include days in May while iterating the DatePeriod | |
* @method self june Include days in June while iterating the DatePeriod | |
* @method self july Include days in July while iterating the DatePeriod | |
* @method self august Include days in August while iterating the DatePeriod | |
* @method self september Include days in September while iterating the DatePeriod | |
* @method self october Include days in October while iterating the DatePeriod | |
* @method self november Include days in November while iterating the DatePeriod | |
* @method self december Include days in December while iterating the DatePeriod | |
*/ | |
class DatePeriod_Filter extends FilterIterator | |
{ | |
/** | |
* Array of days to filter | |
* | |
* @var array | |
* <ul> | |
* <li>@key string day => @type boolean true | |
* ... | |
* </ul> | |
*/ | |
private $_dayFilter = []; | |
/** | |
* Array of ante/post meridiems to filter | |
* | |
* @var array | |
* <ul> | |
* <li>@key string 'am' => @type boolean true | |
* <li>@key string 'pm' => @type boolean true | |
* </ul> | |
*/ | |
private $_meridiemFilter = []; | |
/** | |
* Array of months to filter | |
* | |
* @var array | |
* <ul> | |
* <li>@key string month => @type boolean true | |
* ... | |
* </ul> | |
*/ | |
private $_monthFilter = []; | |
/** | |
* Array of user filters | |
* | |
* @var array | |
* <ul> | |
* <li>@type callable Invoked with the current DateTime object and is expected to return a boolean | |
* ... | |
* </ul> | |
*/ | |
private $_userFilter = []; | |
/** | |
* @link http://php.net/manual/en/dateperiod.construct.php | |
* @see DatePeriod::__construct() | |
*/ | |
public function __construct( ...$params ) | |
{ | |
parent::__construct( new IteratorIterator( new DatePeriod( ...$params ) ) ); | |
} | |
/** | |
* Method overloading | |
* | |
* @throws BadMethodCallException | |
* | |
* @param string $name | |
* @param array $noop | |
* @return self | |
*/ | |
public function __call( string $name, array $noop ) : self | |
{ | |
switch( $name ) | |
{ | |
case 'monday' : | |
case 'tuesday' : | |
case 'wednesday': | |
case 'thursday' : | |
case 'friday' : | |
case 'saturday' : | |
case 'sunday' : | |
$this->_dayFilter[ ucfirst( $name ) ] = true; | |
break; | |
case 'weekdays': | |
$this->monday()->tuesday()->wednesday()->thursday()->friday(); | |
break; | |
case 'weekends': | |
$this->saturday()->sunday(); | |
break; | |
case 'am': | |
case 'pm': | |
$this->_meridiemFilter[ $name ] = true; | |
break; | |
case 'january' : | |
case 'february' : | |
case 'march' : | |
case 'april' : | |
case 'may' : | |
case 'june' : | |
case 'july' : | |
case 'august' : | |
case 'september' : | |
case 'october' : | |
case 'november' : | |
case 'december' : | |
$this->_monthFilter[ ucfirst( $name ) ] = true; | |
break; | |
default: | |
throw new BadMethodCallException( "Call to undefined method $name" ); | |
} | |
return $this; | |
} | |
/** | |
* Given the current DateTime object, check if it matches a user filter | |
* | |
* @param DateTime $current | |
* @return bool | |
*/ | |
private function _userFilterMatches( DateTime $current ) : bool | |
{ | |
foreach( $this->_userFilter as $filter ) | |
{ | |
if( $filter( $current ) ) | |
return true; | |
} | |
return false; | |
} | |
/** | |
* {@inheritDoc} | |
* @see FilterIterator::accept() | |
*/ | |
public function accept() : bool | |
{ | |
$current = $this->current(); | |
if( $this->_dayFilter && !isset( $this->_dayFilter[ $current->format( 'l' ) ] ) ) return false; | |
if( $this->_meridiemFilter && !isset( $this->_meridiemFilter[ $current->format( 'a' ) ] ) ) return false; | |
if( $this->_monthFilter && !isset( $this->_monthFilter[ $current->format( 'F' ) ] ) ) return false; | |
if( $this->_userFilter && !$this->_userFilterMatches( $current ) ) return false; | |
return true; | |
} | |
/** | |
* Add one or more custom filters to control which DateTime | |
* objects of DatePeriod will be interated | |
* | |
* @param callable $filter | |
* <div>Invoked with the current DateTime object and is expected to return a boolean value to indicate whether it should be iterated.</div> | |
* | |
* @param callable ...$filters | |
* @return self | |
*/ | |
public function filter( callable $filter, callable ...$filters ) : self | |
{ | |
array_push( $this->_userFilter, $filter, ...$filters ); | |
return $this; | |
} | |
/** | |
* Return the DatePeriod constructed during instantiation | |
* | |
* @return DatePeriod | |
*/ | |
public function getDatePeriod() : DatePeriod | |
{ | |
return $this->getInnerIterator() | |
->getInnerIterator() | |
; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment