File: /var/www/html/triad-infosec/wp-content/plugins/events-calendar-pro/src/Tribe/Recurrence.php
<?php
/**
* Given a start date, series end (end date or number of occurrences), and rules engine; find me all the dates in a recurrence
*/
class Tribe__Events__Pro__Recurrence {
const NO_END = -1;
private $start_date;
private $duration;
private $end;
/** @var Tribe__Events__Pro__Date_Series_Rules__Rules_Interface */
private $series_rules;
private $by_occurrence_count;
private $event;
/**
* @var string
*/
private $start_time;
private $minDate = 0;
private $maxDate = 2147483647; // Y2K38, an arbitrary limit. TODO: revisit this in twenty years
private $last_request_constrained = false;
public function __construct( $start_date, $end, $series_rules, $by_occurrence_count = false, $event = null, $start_time = null, $duration = null ) {
$this->start_date = $start_date;
$this->end = $end;
$this->series_rules = $series_rules;
$this->by_occurrence_count = $by_occurrence_count;
$this->event = $event;
$this->start_time = $start_time;
$this->duration = $duration;
}
/**
* Adjusts the start time of a date
*
* @param timestamp $date Date timestamp to adjust
*
* @return timestamp
*/
public function adjust_start_time( $date ) {
if ( ! $this->start_time ) {
return $date;
}
$date = date( 'Y-m-d', $date ) . ' ' . $this->start_time;
$date = strtotime( $date );
return $date;
}
public function setMinDate( $timestamp ) {
$this->minDate = (int) $timestamp;
}
public function setMaxDate( $timestamp ) {
$this->maxDate = (int) $timestamp;
}
/**
* Using the rules engine, find all dates in the series.
*
* Each individual date is represented by an array structured as:
*
* [ "timestamp" => int,
* "duration" => int ]
*
* If the duration is -1 then it can be taken as equal to the parent event's
* duration.
*
* @param int $rule_count current recurrence rule processing
*
* @return array An array of all dates in the series
*/
public function getDates( $rule_count = null ) {
$this->last_request_constrained = false;
if ( $this->series_rules && ! is_wp_error( $this->series_rules ) ) {
$dates = array();
$cur_date = $this->start_date;
$last_date = $cur_date;
$i = 0;
while ( $cur_date = $this->getNextDate( $cur_date, $i, $rule_count ) ) {
if ( $cur_date === $last_date ) {
// We're looping, break out of the loop.
break;
}
$last_date = $cur_date;
$i++;
if ( $cur_date > $this->maxDate ) {
$this->last_request_constrained = $cur_date;
break; // no more dates will be in range. stop here
}
if ( $cur_date < $this->minDate ) {
continue; // move forward until we find a date within range
}
if ( $this->afterSeries( $this->by_occurrence_count ? $i : $cur_date ) ) {
break; // end of the series
}
$dates[] = $date = array(
'timestamp' => $this->adjust_start_time( $cur_date ),
'duration' => $this->duration,
);
$cur_date = $date['timestamp'];
}
return $dates;
}
return array();
}
/**
* Flag indicating if the last getDates() request was constrained
* by the max date setting
*
* @return bool
*/
public function constrainedByMaxDate() {
return $this->last_request_constrained;
}
/**
* Get the next date in the series
*
* @param int $current_date
* @param int $count current event count for rule
* @param int $rule_count the current rule number
*
* @return bool|int The date, as a timestamp, or FALSE if it exceeds the system's max int
*/
private function getNextDate( $current_date, $count = null, $rule_count = null ) {
$next_date = $this->series_rules->getNextDate( $current_date );
if ( 0 !== $rule_count && 0 === $count && ( $next_date === $current_date ) ) {
/**
* return the $current_date on the first run of the 2nd rule and later to
* enable events to start on the parent's date without duplicating initial event
*/
return $current_date;
}
if ( intval( $next_date ) < $current_date ) { // bit overflow
return false;
}
// Makes sure to assign the proper hours to the date.
$next_date = mktime( date( 'H', $this->start_date ), date( 'i', $this->start_date ), date( 's', $this->start_date ), date( 'n', $next_date ), date( 'j', $next_date ), date( 'Y', $next_date ) );
return $next_date;
}
private function afterSeries( $instance ) {
if ( $this->end == self::NO_END ) {
return false;
}
return $instance > $this->end;
}
}