Files
roi-theme/wp-content/plugins/thrive-ultimatum/inc/classes/class-tu-schedule-rolling.php
root a22573bf0b Commit inicial - WordPress Análisis de Precios Unitarios
- WordPress core y plugins
- Tema Twenty Twenty-Four configurado
- Plugin allow-unfiltered-html.php simplificado
- .gitignore configurado para excluir wp-config.php y uploads

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 21:04:30 -06:00

744 lines
24 KiB
PHP
Executable File

<?php
/**
* Created by PhpStorm.
* User: radu
* Date: 08.02.2016
* Time: 10:23
*/
class TU_Schedule_Rolling extends TU_Schedule_Abstract {
/**
* check if the campaign should be displayed
*/
public function applies( $force_apply = false ) {
// Before anything let's check if the campaign has started if not let's end it all
if ( ! $this->is_past( $this->settings['start'] ) ) {
return false;
}
// Let's check if the campaign will ever end
if ( null !== ( $end = $this->get_global_end_date() ) && ! $this->is_future( $end ) ) {
return false;
}
//check if end cookie is set for this campaign
if ( isset( $_COOKIE[ $this->cookie_end_name() ] ) ) {
return false;
}
// check if any conversion event meet the criteria and end the campaign if it does so
if ( ! empty( $this->conversion_events ) ) {
foreach ( $this->conversion_events as $event ) {
$trigger = $this->check_triggers( $event['trigger_options'] );
if ( ! $trigger ) {
return false;
}
}
}
// Check if it's a period where the campaign should repeat
$check_repeat = 'check_repeat_' . $this->settings['rolling_type'];
if ( ! method_exists( $this, $check_repeat ) ) {
return false;
}
return $this->$check_repeat();
}
/**
* returns the end date calculated for the campaign (the "global" end date - when the campaign is actually ending)
* if no end date or number of occurrences have been set, returns null
*
* the return date / time is constructed by adding time intervals to the start date, if the end date is not fixed
*
* @return array|null array with 2 keys:
* date - a date formatted with date('j F Y')
* time - time in the format H:i (no seconds)
*/
public function get_global_end_date() {
if ( empty( $this->settings['end'] ) ) {
/* this campaign will never end */
return null;
}
if ( is_array( $this->settings['end'] ) ) {
/* end is already a fixed date */
$absolute_end_date = $this->settings['end'];
} else {
$absolute_end_date = $this->set_after_occurrence_date( $this->settings['rolling_type'], $this->settings['start'], $this->settings['end'] * $this->settings['repeat'] );
}
return $absolute_end_date;
}
/**
* get the start and end date / time for the currently detected interval
*
* @return array with keys: date, time ( j F Y and H:i )
*/
public function get_current_daily_interval() {
// let's make our variable names shorter so the code is more readable
$start = $this->settings['start'];
$repeat = $this->settings['repeat'];
$duration = $this->settings['duration'];
// check for the difference in days between the start of the campaign and today
// in order to find the start of the roll interval we're in
$diff = floor( ( $this->now() - $this->date( $start ) ) / ( 60 * 60 * 24 ) );
$int_number = floor( $diff / $repeat );
// set the start date of this roll interval (for daily this will also be the start of the campaign on each roll)
$temp = $this->set_after_occurrence_date( $this->settings['rolling_type'], $start, $int_number * $repeat );
$interval = array(
'start' => array(
'date' => $temp['date'],
'time' => $start['time'],
),
);
$interval['end'] = tve_ult_add_to_date( $interval['start'], 0, $duration );
return $interval;
}
/**
* get all the applicable weekly intervals that can apply based on the current date
*
* @return array of intervals ( each interval with start and end date / time, formatted in j F Y and H:i )
*/
public function get_current_weekly_intervals() {
// let's make our variable names shorter so the code is more readable
$start = $this->settings['start'];
$repeat = (int) $this->settings['repeat'];
// get the first day of the week before the start date so we can do the week difference
$start_date = date( 'w', strtotime( $start['date'] ) );
//set the fake start date of the campaign
$week_start['date'] = date( 'j F Y', strtotime( $start['date'] . '-' . $start_date . ' days' ) );
$week_start['time'] = $start['time'];
//get the number of whole campaigns that rolled until today (weeks + repeat every x weeks)
$diff = floor( ( $this->now() - $this->date( $week_start ) ) / ( 60 * 60 * 24 * 7 ) );
$int_number = floor( $diff / $repeat );
// set the start date of this roll interval
$temp = $this->set_after_occurrence_date( $this->settings['rolling_type'], $week_start, $int_number * $repeat );
$int_start['date'] = $temp['date'];
$int_start['time'] = $this->settings['start']['time'];
//construct an array of all weekdays where the campaign should show
$display_intervals = $this->get_display_days( $int_start );
// check if the repeat is 1, and it's not the first week
// if we're in our first week this could cause erroneous displays of the campaign
if ( $repeat === 1 && $int_start !== $week_start ) {
// check if any end interval is in the next week
foreach ( $display_intervals as $day_id => $interval ) {
$partial_start = date( 'w', strtotime( $interval['start']['date'] ) );
$partial_end = date( 'w', strtotime( $interval['end']['date'] ) );
// if the start day is smaller and end week are not the same then the end
// is in the next month and should be shown at the beginning of
// this month too because we're already in the second month
if ( $partial_start >= $partial_end ) {
// create the new array with the correct interval
$display_intervals['new']['start']['date'] = date( 'j F Y', strtotime( 'last sunday', strtotime( $interval['start']['date'] ) ) );
$display_intervals['new']['start']['time'] = '00:00';
$display_intervals['new']['end']['date'] = date( 'j F Y', strtotime( $interval['end']['date'] . ' -1 week' ) );
$display_intervals['new']['end']['time'] = $interval['end']['time'];
}
}
}
return $display_intervals;
}
/**
* get all the applicable monthly intervals that can apply based on the current date
*
* @return array of intervals ( each interval with start and end date / time, formatted in j F Y and H:i )
*/
public function get_current_monthly_intervals() {
$start = $this->settings['start'];
$repeat = $this->settings['repeat'];
// get the first day of the month before the start date so we can do the month difference
$start_date = date( 'j', strtotime( $start['date'] ) );
//set the fake start date of the campaign
$month_start['date'] = date( '1 F Y', strtotime( $start['date'] ) );
$month_start['time'] = $start['time'];
//get the number of whole campaigns that rolled until today (moths + repeat every x months)
$start_date = $this->date( $month_start );
$now = $this->now();
$i = 0;
while ( ( $start_date = strtotime( '+1 MONTH', $start_date ) ) <= $now ) {
$i ++;
}
$int_number = floor( $i / $repeat );
// set the start date of this roll interval
$temp = $this->set_after_occurrence_date( $this->settings['rolling_type'], $month_start, $int_number * $repeat );
$int_start['date'] = $temp['date'];
$int_start['time'] = $start['time'];
//construct an array of all weekdays where the campaign should show
$display_intervals = $this->get_display_days( $int_start );
// check if the repeat is 1, and it's not the first month
// if we're in our first month this could cause erroneous displlays of the campaign
if ( $repeat === 1 && $int_start !== $month_start ) {
// check if any end interval is in the next month
foreach ( $display_intervals as $day_id => $interval ) {
$partial_start = date( 'F', strtotime( $interval['start']['date'] ) );
$partial_end = date( 'F', strtotime( $interval['end']['date'] ) );
// if the start month and end month are not the same then the end
// is in the next month and should be shown at the beginning of
// this month too because we're already in the second month
if ( $partial_start !== $partial_end ) {
// create the new array with the correct interval
$display_intervals['new']['start']['date'] = date( '1 F Y', strtotime( $interval['start']['date'] ) );
$display_intervals['new']['start']['time'] = '00:00';
$display_intervals['new']['end']['date'] = date( 'j F Y', strtotime( $interval['end']['date'] . ' -1 Month' ) );
$display_intervals['new']['end']['time'] = $interval['end']['time'];
}
}
}
return $display_intervals;
}
/**
* get the start and end date / time for the currently detected interval
*
* @return array with keys: date, time ( j F Y and H:i )
*/
public function get_current_yearly_interval() {
$start = $this->settings['start'];
$repeat = $this->settings['repeat'];
$duration = $this->settings['duration'];
// check for the difference in years between the start of the campaign and today
// in order to find the start of the roll interval we're in
$diff = floor( ( $this->now() - $this->date( $start ) ) / ( 60 * 60 * 24 * 365 ) );
$int_number = floor( $diff / $repeat );
// set the start date of this roll interval (for daily this will also be the start of the campaign on each roll)
$temp = $this->set_after_occurrence_date( $this->settings['rolling_type'], $start, $int_number * $repeat );
$int_start['date'] = $temp['date'];
$int_start['time'] = $start['time'];
// define the date where the campaign should stop showing in this rol;
$int_end = tve_ult_add_to_date( $int_start, $duration );
return array(
'start' => $int_start,
'end' => $int_end,
);
}
/**
* Check if the daily campaign should show
*
* @return bool
*/
public function check_repeat_daily() {
$interval = $this->get_current_daily_interval();
// check if we're in the interval if we are we'll show the campaign
return $this->is_future( $interval['end'] ) && $this->is_past( $interval['start'] );
}
/**
* Check if the weekly campaign should show
*
* @return bool
*/
public function check_repeat_weekly() {
$display_intervals = $this->get_current_weekly_intervals();
// check if today is in any of the display intervals
foreach ( $display_intervals as $interval ) {
if ( $this->is_future( $interval['end'] ) && $this->is_past( $interval['start'] ) ) {
return true;
}
}
return false;
}
/**
* Check if the monthly campaign should show
*
* @return bool
*/
public function check_repeat_monthly() {
$display_intervals = $this->get_current_monthly_intervals();
// check if today is in any of the display intervals
foreach ( $display_intervals as $interval ) {
if ( $this->is_future( $interval['end'] ) && $this->is_past( $interval['start'] ) ) {
return true;
}
}
return false;
}
/**
* Check if the yearly campaign should show
*
* @return bool
*/
public function check_repeat_yearly() {
$interval = $this->get_current_yearly_interval();
// check if we're in the interval if we are we'll show the campaign
return $this->is_future( $interval['end'] ) && $this->is_past( $interval['start'] );
}
/**
* Set the end date accordingly taking in consideration the rolling type
*
* @param string $rolling campaign type
* @param array $date with 2 indexes [date,time]
* @param int $occurrence in days|weeks|months|years
*
* @return mixed
*/
public function set_after_occurrence_date( $rolling, $date, $occurrence ) {
switch ( $rolling ) {
//append number of days
case TVE_Ult_Const::CAMPAIGN_ROLLING_TYPE_DAILY:
$date['date'] = date( 'j F Y', strtotime( $date['date'] . ' ' . $date['time'] . ' + ' . $occurrence . ' days' ) );
break;
//append number of weeks
case TVE_Ult_Const::CAMPAIGN_ROLLING_TYPE_WEEKLY:
$date['date'] = date( 'j F Y', strtotime( $date['date'] . ' ' . $date['time'] . ' + ' . $occurrence . ' weeks' ) );
break;
//append number of months
case TVE_Ult_Const::CAMPAIGN_ROLLING_TYPE_MONTHLY:
$date['date'] = date( 'j F Y', strtotime( $date['date'] . ' ' . $date['time'] . ' + ' . $occurrence . ' months' ) );
break;
//append number of years
case TVE_Ult_Const::CAMPAIGN_ROLLING_TYPE_YEARLY:
$date['date'] = date( 'j F Y', strtotime( $date['date'] . ' ' . $date['time'] . ' + ' . $occurrence . ' years' ) );
break;
}
return $date;
}
/**
* Get the days on which the campaign should show
*
* @return array
*/
public function get_display_days( $start_date ) {
$dates = array();
foreach ( $this->settings['repeatOn'] as $day ) {
$dates[ $day ]['start'] = tve_ult_add_to_date( $start_date, $day );
$dates[ $day ]['end'] = tve_ult_add_to_date( $start_date, $day + $this->settings['duration'] );
}
return $dates;
}
/**
* Returns the number of hours remained until the campaign/interval ends
*
* @return int
*/
public function hours_until_end() {
$method = "get_{$this->settings['rolling_type']}_end_date";
$now = date( 'Y-m-d H:i', $this->now() );
if ( method_exists( $this, $method ) ) {
$end = call_user_func( array( $this, $method ) );
} else {
$end = date( 'Y-m-d H:00:00', $this->now() );
}
$diff = tve_ult_date_diff( $now, $end );
return ( $diff['days'] * 24 ) + $diff['hours'];
}
/**
* Adds duration hours to start date and returns the string date
*
* @return bool|string
*/
public function get_daily_end_date() {
$start_date = date( 'Y-m-d' );
$start_hour = $this->settings['start']['time'];
$start = tve_ult_pre_format_date( $start_date, $start_hour );
$start_at = strtotime( $start );
if ( $start_at > $this->now( false ) ) {
// this means the campaign's end hour is after the current time - meaning that the current interval has actually started "yesterday"
$start_at -= DAY_IN_SECONDS;
$start = date( 'Y-m-d H:i:s', $start_at );
}
return date( 'Y-m-d H:i:s', strtotime( $start . ' +' . $this->settings['duration'] . ' hours' ) );
}
/**
* Adds duration days to start date and returns the string date
*
* @return string
*/
public function get_yearly_end_date() {
// check for the difference in years between the start of the campaign and today
// in order to find the start of the roll interval we're in
$diff = floor( ( $this->now() - $this->date( $this->settings['start'] ) ) / ( 60 * 60 * 24 * 365 ) );
$int_number = floor( $diff / $this->settings['repeat'] );
// set the start date of this roll interval (for daily this will also be the start of the campaign on each roll)
$temp = $this->set_after_occurrence_date( $this->settings['rolling_type'], $this->settings['start'], $int_number * $this->settings['repeat'] );
$int_start['date'] = $temp['date'];
$int_start['time'] = $this->settings['start']['time'];
$start = tve_ult_pre_format_date( $int_start['date'], $int_start['time'] );
$interval_end = date( 'Y-m-d H:i:s', strtotime( $start . ' +' . $this->settings['duration'] . ' days' ) );
if ( is_array( $this->settings['end'] ) ) {
$end_date = tve_ult_pre_format_date( $this->settings['end']['date'], $this->settings['end']['time'] );
}
return isset( $end_date ) && $end_date < $interval_end ? ( $end_date . ':00' ) : $interval_end;
}
/**
* Calculates the end date of the selected interval
* If the current date is not within any interval
* NOW() is returned. This will make the last event occur
*
* @return string
*/
public function get_weekly_end_date() {
$intervals = $this->get_current_weekly_intervals();
$now = $this->now();
/**
* Foreach possible display intervals - find the one that applies to the current time
* If now is between the interval that means
* we have to calculate how many hours we have to until
* the current interval ends.
* Based on that we select the current event.
*/
foreach ( $intervals as $possible_option ) {
$interval_start = $this->date( $possible_option['start'] );
$interval_end = $this->date( $possible_option['end'] );
if ( $interval_start <= $now && $now < $interval_end ) {
$interval = array(
'start' => date( 'Y-m-d H:i', $interval_start ),
'end' => date( 'Y-m-d H:i:00', $interval_end ),
);
}
}
if ( ! isset( $interval ) ) {
/**
* this will make the last event to be selected because the events
* are ordered by duration asc and last event has smallest duration
*
*/
return date( 'Y-m-d H:00', $this->now() );
}
if ( is_array( $this->settings['end'] ) ) {
$end_date = tve_ult_pre_format_date( $this->settings['end']['date'], $this->settings['end']['time'] );
}
return isset( $end_date ) && $end_date < $interval['end'] ? ( $end_date . ':00' ) : $interval['end'];
}
/**
* Calculates the end date of the selected interval
* If the current date is not within any interval
* NOW() is returned. This will make the last event occur
*
* @return string
*/
public function get_monthly_end_date() {
$campaign_start = date( 'Y-m-01 ' . $this->settings['start']['time'] . ':00', $this->now() );
foreach ( $this->settings['repeatOn'] as $day ) {
$interval_start = date( 'Y-m-d H:i', strtotime( $campaign_start . ' +' . ( $day ) . ' days' ) );
$interval_end = date( 'Y-m-d H:i:00', strtotime( $interval_start . ' +' . (int) $this->settings['duration'] . ' days' ) );
if ( strtotime( $interval_start ) <= $this->now() && $this->now() < strtotime( $interval_end ) ) {
$interval = array(
'start' => $interval_start,
'end' => $interval_end,
);
break;
}
}
if ( ! isset( $interval ) ) {
/**
* this will make the last event to be selected because the events
* are ordered by duration asc and last event has smallest duration
*/
return date( 'Y-m-d H:00:00', $this->now() );
}
if ( is_array( $this->settings['end'] ) ) {
$end_date = tve_ult_pre_format_date( $this->settings['end']['date'], $this->settings['end']['time'] );
}
return isset( $end_date ) && $end_date < $interval['end'] ? ( $end_date . ':00' ) : $interval['end'];
}
/**
* get the end date of the current campaign instance (interval)
*
* should return a date in the format: Y-m-d H:i:s
*
* @return string
*/
public function get_end_date() {
$method = "get_{$this->settings['rolling_type']}_end_date";
if ( empty( $this->settings['rolling_type'] ) || ! method_exists( $this, $method ) ) {
return '';
}
return call_user_func( array( $this, $method ) );
}
/**
* @inheritdoc
*/
public function get_duration() {
$duration = 0;
switch ( $this->settings['rolling_type'] ) {
case TVE_Ult_Const::CAMPAIGN_ROLLING_TYPE_DAILY:
$duration = $this->settings['duration'];
break;
case TVE_Ult_Const::CAMPAIGN_ROLLING_TYPE_WEEKLY:
case TVE_Ult_Const::CAMPAIGN_ROLLING_TYPE_MONTHLY:
case TVE_Ult_Const::CAMPAIGN_ROLLING_TYPE_YEARLY:
$duration = $this->settings['duration'] * 24;
break;
}
return $duration;
}
/**
* checks performed for a daily campaign - pre access page
*
* @return bool
*/
protected function should_redirect_pre_access_daily() {
$interval = $this->get_current_daily_interval();
/* if the currently detected interval has ended, this means that there is at least one more interval (global settings are checked in a previous step) */
return $this->is_past( $interval['end'] );
}
/**
* checks performed for a weekly campaign - pre-access
*
* @return bool
*/
protected function should_redirect_pre_access_weekly() {
/**
* pre-access redirection is achieved when the campaign did not end and it currently does not apply
*/
if ( $this->should_redirect_expired() || $this->applies() ) {
return false;
}
return true;
}
/**
* checks performed for a monthly campaign
*
* @return bool
*/
protected function should_redirect_pre_access_monthly() {
/**
* use the expired and applies functionalities for this
*/
if ( $this->should_redirect_expired() || $this->applies() ) {
return false;
}
return true;
}
/**
* checks for pre-access redirects for yearly campaigns
*
* @return bool
*/
protected function should_redirect_pre_access_yearly() {
/**
* use the expires and applies functionalities
*/
if ( $this->should_redirect_expired_yearly() || $this->applies() ) {
return false;
}
return true;
}
/**
* checks if a weekly campaign is completely ended at this point
*
* the global end date is not sufficient, because it actually represents the actual and date of the last week in which this campaign occurs
*/
public function should_redirect_expired_weekly() {
$end_date = $this->get_global_end_date();
$end_timestamp = $this->date( $end_date );
/* if end date is farther in the future than one cycle from now, this campaign is not ended */
if ( $end_timestamp > $this->now() + ( $this->settings['repeat'] * 7 * DAY_IN_SECONDS ) ) {
return false;
}
/* if the campaign ends a less than one cycle from now and if all intervals have ended, the campaign is finished */
foreach ( $this->get_current_weekly_intervals() as $interval ) {
if ( $this->is_future( $interval['end'] ) ) {
return false;
}
}
return true;
}
/**
* checks performed for a monthly campaign expired page redirection
*
* @return bool
*/
public function should_redirect_expired_monthly() {
$end_date = $this->get_global_end_date();
if ( $this->is_past( $end_date ) ) {
return true;
}
$end_timestamp = strtotime( tve_ult_pre_format_date( $end_date['date'], $end_date['time'] ) . " -{$this->settings['repeat']} months" );
/* if end date is farther in the future than one cycle from now, this campaign is not ended */
if ( $end_timestamp > $this->now() ) {
return false;
}
/* if we have at least one interval that has not ended yet between now and the end date, the campaign is not expired */
foreach ( $this->get_current_monthly_intervals() as $interval ) {
if ( $this->is_future( $interval['end'] ) && $this->date( $interval['end'] ) < $this->date( $end_date ) ) {
return false;
}
}
return true;
}
/**
* checks performed for redirects to the expired page of a yearly campaign
*
* @return bool
*/
protected function should_redirect_expired_yearly() {
$end_date = $this->get_global_end_date();
$end_timestamp = strtotime( tve_ult_pre_format_date( $end_date['date'], $end_date['time'] ) . " -{$this->settings['repeat']} years" );
/* if end date is farther in the future than one cycle from now, this campaign is not ended */
if ( $end_timestamp > $this->now() ) {
return false;
}
/* if we have at least one interval that has not ended yet between now and the end date, the campaign is not expired */
$interval = $this->get_current_yearly_interval();
if ( $this->is_future( $interval['end'] ) ) {
return false;
}
return true;
}
/**
* the redirection to the pre-access page should happen:
*
* a) when the campaign has not yet started
* b) when a cycle is finished and another cycle is yet to begin
*
* @return bool
*/
public function should_redirect_pre_access() {
/* first, some global checks */
if ( $this->is_future( $this->settings['start'] ) ) {
return true;
}
if ( isset( $_COOKIE[ $this->cookie_end_name() ] ) ) {
return false;
}
/* if the campaign has ended, return false */
if ( null !== ( $end_date = $this->get_global_end_date() ) && ! $this->is_future( $end_date ) ) {
return false;
}
$method = 'should_redirect_pre_access_' . $this->settings['rolling_type'];
if ( ! method_exists( $this, $method ) ) {
return false;
}
return $this->{$method}();
}
/**
* checks performed for a daily campaign - expired page
*
* the redirection to the expired page should only happen after the campaign has ended
*
* @return bool
*/
public function should_redirect_expired() {
/* first, some global checks */
if ( $this->is_future( $this->settings['start'] ) ) {
return false;
}
if ( isset( $_COOKIE[ $this->cookie_end_name() ] ) ) {
return true;
}
/*
* short-circuit if the campaign never ends
*/
if ( empty( $this->settings['end'] ) ) {
return false;
}
/* if the campaign has ended, return false */
if ( null !== ( $end_date = $this->get_global_end_date() ) && $this->is_past( $end_date ) ) {
return true;
}
$method = 'should_redirect_expired_' . $this->settings['rolling_type'];
if ( method_exists( $this, $method ) ) {
return $this->{$method}();
}
return false;
}
}