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>
This commit is contained in:
root
2025-11-03 21:04:30 -06:00
commit a22573bf0b
24068 changed files with 4993111 additions and 0 deletions

View File

@@ -0,0 +1,63 @@
<?php
/**
* Created by PhpStorm.
* User: Pop Aurelian
* Date: 10-Mar-16
* Time: 12:32 PM
*/
class TU_Campaign_Event {
const TRIGGER_SPECIFIC = 'specific';
const TRIGGER_CONVERSION = 'conversion';
const TYPE_END = 'end';
const TYPE_MOVE = 'move';
/**
* TU_Campaign_Event constructor.
*/
public function __construct() {
}
/**
* Get triggers
*
* @return array
*/
public static function get_triggers() {
if ( function_exists( 'tve_leads_get_groups' ) ) {
$items[ self::TRIGGER_CONVERSION ] = array(
'title' => __( 'User subscription', 'thrive-ult' ),
);
}
$items[ self::TRIGGER_SPECIFIC ] = array(
'title' => __( 'Visit to conversion page', 'thrive-ult' ),
);
return $items;
}
/**
* Get triggers
*
* @return array
*/
public static function get_types() {
$items = array(
self::TYPE_END => array(
'title' => __( 'End Campaign', 'thrive-ult' ),
),
self::TYPE_MOVE => array(
'title' => __( 'Move to another Campaign', 'thrive-ult' ),
),
);
return $items;
}
}

View File

@@ -0,0 +1,167 @@
<?php
/**
* Handles the WIDGET design type
*/
class TU_Campaign_Widget extends WP_Widget {
/**
* TU_Campaign_Widget constructor.
*/
public function __construct() {
parent::__construct( 'tve_ult_widget', __( 'Thrive Ultimatum', 'thrive-ult' ) );
}
/**
* Echoes the widget content.
* This will just output a placeholder for the widget, the widget design will be loaded via ajax
*
* @param array $args Display arguments including 'before_title', 'after_title',
* 'before_widget', and 'after_widget'.
* @param array $instance The settings for the particular instance of the widget.
*/
public function widget( $args, $instance ) {
if ( ! isset( $instance['campaign_ids'] ) || ! is_array( $instance['campaign_ids'] ) ) {
return;
}
global $tve_ult_frontend;
if ( empty( $tve_ult_frontend ) ) {
require_once TVE_Ult_Const::plugin_path() . 'inc/classes/class-tu-frontend-handler.php';
$tve_ult_frontend = new TU_Frontend_Handler();
}
if ( ! ( $matched = $tve_ult_frontend->get_campaigns() ) ) {
return;
}
/**
* calculate an intersection between the matched campaigns and the campaigns setup from admin for this widget
*/
$matched_ids = array();
foreach ( $matched as $campaign ) {
$matched_ids [] = $campaign->ID;
}
$diff = array_intersect( $matched_ids, $instance['campaign_ids'] );
/* if no campaign setup from widget -> bail */
if ( empty( $diff ) ) {
return;
}
/* get the height from any of the widgets from the campaign - doesn't matter which one because at this point we don't know which one will be displayed */
$widgets = array_values( array_filter( $campaign->designs, static function ( $design ) {
return ! empty( $design['post_type'] ) && $design['post_type'] === 'widget';
} ) );
if ( empty( $widgets[0]['id'] ) ) {
$placeholder_style = 'display:none';
} else {
$placeholder_style = tve_ultimatum_get_lightspeed_placeholder( $campaign->ID, $widgets[0]['id'] );
}
$class = '';
if ( $placeholder_style !== 'display:none' ) {
$class = 'tve-ult-preload-form';
}
// add id to wrapper to be used in js
echo '<div id="tve-ult-widget-container" style="' . $placeholder_style . '" class="' . $class . '" data-widget-id="' . $this->id . '">';
if ( ! empty( $args['before_widget'] ) ) {
echo $args['before_widget'];
}
echo '<span id="tve-ult-widget-placeholder"></span>';
if ( ! empty( $args['after_widget'] ) ) {
echo $args['after_widget'];
}
echo '</div>';
}
/**
* Outputs the settings update form.
*
* @access public
*
* @param array $instance Current settings.
*
* @return string Default return is 'noform'.
*/
public function form( $instance ) {
$ids = empty( $instance['campaign_ids'] ) ? array() : $instance['campaign_ids'];
if ( empty( $ids ) || ! is_array( $ids ) ) {
$ids = array();
}
$campaigns = tve_ult_get_campaigns( array(
'get_settings' => false,
) );
echo '<p><label>' . __( 'Choose the applicable campaigns for the widget', 'thrive-ult' ) . '</label></p>';
if ( empty( $campaigns ) ) {
echo '<p class="no-options-widget">' .
sprintf( __( 'You have no campaigns setup yet. %sSetup your campaigns first%s', 'thrive-ult' ), '<a href="' . admin_url( 'admin.php?page=tve_ult_dashboard' ) . '">', '</a>' ) .
'</p>';
return '';
}
echo '<p><label id="tve-ult-select-all" style="cursor: pointer; font-weight: bold;">' . __( 'Select all/none', 'thrive-ult' ) . '</label></p>';
?>
<script type="text/javascript">
( function ( $ ) {
$( function () {
$( 'body' ).off( 'click', '#tve-ult-select-all' ).on( 'click', '#tve-ult-select-all', function () {
var $this = $( this ),
check = $this.data( 'checked' ) !== undefined ? ! $this.data( 'checked' ) : true,
$checkboxes = $this.parents( 'form' ).first().find( '.tve-ult-campaign' );
var $checked = $checkboxes.filter( function ( index, element ) {
return $( element ).is( ':checked' );
} );
check = check && $checkboxes.length === $checked.length ? false : check;
$checkboxes.prop( 'checked', check );
$this.data( 'checked', check );
} );
} );
} )( jQuery )
</script>
<?php
$field_name = $this->get_field_name( 'campaign_ids' );
foreach ( $campaigns as $c ) {
echo '<p><label><input class="tve-ult-campaign" type="checkbox" value="'
. $c->ID . '" name="' . $field_name . '[]"'
. ( in_array( $c->ID, $ids ) ? ' checked' : '' )
. '>&nbsp; ' . $c->post_title . '</label></p>';
}
return '';
}
/**
* Updates a particular instance of a widget.
*
* This function should check that `$new_instance` is set correctly. The newly-calculated
* value of `$instance` should be returned. If false is returned, the instance won't be
* saved/updated.
*
*
* @param array $new_instance New settings for this instance as input by the user via
* WP_Widget::form().
* @param array $old_instance Old settings for this instance.
*
* @return array Settings to save or bool false to cancel saving.
*/
public function update( $new_instance, $old_instance ) {
if ( ! isset( $new_instance['campaign_ids'] ) || ! is_array( $new_instance['campaign_ids'] ) ) {
$new_instance['campaign_ids'] = array();
}
return $new_instance;
}
}

View File

@@ -0,0 +1,287 @@
<?php
class TU_Event_Action {
/**
* If you change this keys make sure you review the Action Model validation
*/
const DESIGN_SHOW = 'design_show';
const DESIGN_SWITCH_STATE = 'design_switch_state';
const CAMPAIGN_END = 'campaign_end';
const CAMPAIGN_MOVE = 'campaign_move';
/**
* @var TU_Event_Action
*/
protected static $instance;
/**
* Private to make sure of its singleton pattern
* TU_Event_Action constructor.
*/
private function __construct() {
}
/**
* Returns the params from $_POST or $_REQUEST
*
* @param $key
* @param null $default
*
* @return mixed|null|$default
*/
protected function param( $key, $default = null ) {
return isset( $_POST[ $key ] ) ? $_POST[ $key ] : ( isset( $_REQUEST[ $key ] ) ? $_REQUEST[ $key ] : $default );
}
/**
* @return TU_Event_Action
*/
public static function getInstance() {
if ( ! self::$instance ) {
self::$instance = new self();
}
return self::$instance;
}
public static function get_keys() {
return array(
self::DESIGN_SHOW,
self::DESIGN_SWITCH_STATE,
self::CAMPAIGN_END,
self::CAMPAIGN_MOVE,
);
}
/**
* @return array with non-associative indexes with all actions
*/
public static function get_model_list() {
$models = array();
foreach ( self::get_detailed_list() as $key => $prop ) {
$prop['key'] = $key;
$models[] = $prop;
}
return $models;
}
public static function get_detailed_list() {
return array(
self::DESIGN_SHOW => array(
'key' => self::DESIGN_SHOW,
'name' => __( 'Display Countdown Design', 'thrive-ult' ),
'description' => __( 'Displays a countdown design. If the design has multiple states, you can also choose a design state', 'thrive-ult' ),
),
// self::DESIGN_SWITCH_STATE => array(
// 'key' => self::DESIGN_SWITCH_STATE,
// 'name' => __( 'Switch Countdown Design State', 'thrive-ult'),
// 'description' => __( 'Simply allows the user to switch from one state to another.', 'thrive-ult'),
// ),
// self::CAMPAIGN_END => array(
// 'key' => self::CAMPAIGN_END,
// 'name' => __( 'End Current Campaign', 'thrive-ult'),
// 'description' => __( 'Completely ends the Campaign so that no more triggers and actions are performed in the current timeline.', 'thrive-ult'),
// ),
// self::CAMPAIGN_MOVE => array(
// 'key' => self::CAMPAIGN_MOVE,
// 'name' => __( 'Move to new campaign', 'thrive-ult'),
// 'description' => __( 'Ends the current campaign and starts a new one.', 'thrive-ult'),
// ),
);
}
/**
* Gets details of an action based on an action_key
*
* @param $action_key
*
* @return null
*/
public static function get_details( $action_key ) {
if ( ! in_array( $action_key, self::get_keys() ) ) {
return null;
}
$actions = self::get_detailed_list();
return $actions[ $action_key ];
}
/**
* Gets the html options for a specific action
* This html is used when a user wants to add/edit an event and selects an action
*
* @param string|array $action
*
* @return string html
*/
public function get_options_html( $action ) {
if ( ! is_array( $action ) ) {
$action['key'] = $action;
}
if ( empty( $action['key'] ) || ! in_array( $action['key'], self::get_keys() ) ) {
return '';
}
$method = "{$action['key']}_options";
if ( ! method_exists( $this, $method ) ) {
return $this->default_options();
}
return call_user_func( array( $this, $method ), $action );
}
protected function default_options() {
return $this->view( 'default' );
}
/**
* Gets the options html for action
*
* @param array $action optional
*
* @return string html
*/
protected function design_show_options( $action = array() ) {
$results = tve_ult_get_designs_and_states( $action['campaign'], array( 'id', 'post_title' ) );
$designs = $results['designs'];
$action = array_merge( self::get_details( $action['key'] ), $action );
$used_actions = $this->param( 'used_actions' );
if ( ! isset( $event['actions'] ) ) {
$event['actions'] = array();
}
$all_used = false;
if ( $this->param( 'mode' ) === 'AddMode' && count( $designs ) === count( $event['actions'] ) ) {
$all_used = true;
}
/**
* Assure unique design action per event
* (cannot be possible to have more actions that show the same design)
*/
if ( is_array( $used_actions ) && ! empty( $used_actions ) ) {
foreach ( $results['designs'] as $key => $design ) {
foreach ( $used_actions as $used ) {
if ( isset( $action['design'] ) && $action['design'] == $design['id'] ) {
continue;
}
if ( $used['design'] == $design['id'] ) {
unset( $designs[ $key ] );
}
}
}
}
return $this->view( self::DESIGN_SHOW, array(
'designs' => $designs,
'states' => json_encode( $results['states'] ),
'action' => $action,
'all_used' => $all_used,
) );
}
/**
* Gets the options html for action
*
* @param array $action optional
*
* @return string html
*/
protected function design_hide_options( $action = array() ) {
$action = array_merge( self::get_details( $action['key'] ), $action );
return $this->view( self::DESIGN_HIDE, array(
'designs' => tve_ult_get_designs( $_REQUEST['campaign_id'] ),
'action' => $action,
) );
}
/**
* Gets the options html for action
*
* @param array $action optional
*
* @return string html
*/
protected function campaign_move_options( $action = array() ) {
$campaigns = tve_ult_get_campaigns( array( 'get_settings' => false ) );
$action = array_merge( self::get_details( $action['key'] ), $action );
return $this->view( self::CAMPAIGN_MOVE, array(
'campaigns' => $campaigns,
'action' => $action,
) );
}
/**
* Gets the options html for action
*
* @param array $action optional
*
* @return string html
*/
protected function campaign_end_options( $action = array() ) {
$action = array_merge( self::get_details( $action['key'] ), $action );
return $this->view( self::CAMPAIGN_END, array(
'action' => $action,
) );
}
/**
* Gets the options html for action
*
* @param array $action optional
*
* @return string html
*/
protected function design_switch_state_options( $action = array() ) {
$results = tve_ult_get_designs_and_states( $_REQUEST['campaign_id'], array( 'id', 'post_title' ) );
$action = array_merge( self::get_details( $action['key'] ), $action );
return $this->view( self::DESIGN_SWITCH_STATE, array(
'designs' => $results['designs'],
'states' => json_encode( $results['states'] ),
'action' => $action,
) );
}
/**
* Renders a view and returns its html
* based on $data
*
* @param $view
* @param array $data
*
* @return string
*/
protected function view( $view, $data = array() ) {
$file = TVE_Ult_Const::plugin_path( "admin/views/action/options/" . $view . ".phtml" );
if ( ! file_exists( $file ) ) {
return '';
}
extract( $data );
ob_start();
include $file;
$html = ob_get_contents();
ob_end_clean();
return $html;
}
}

View File

@@ -0,0 +1,53 @@
<?php
class TU_Event {
/**
* @var WP_Post
*/
protected $campaign;
public function __construct( $campaign ) {
$this->campaign = $campaign;
}
public function get_designs() {
$data = $this->get_data();
if ( empty( $data['actions'] ) ) {
return array();
}
$designs = array();
foreach ( $data['actions'] as $action ) {
if ( $action['key'] === TU_Event_Action::DESIGN_SHOW ) {
$designs[] = tve_ult_get_design( $action['design'] == $action['state'] ? $action['design'] : $action['state'] );
}
}
/**
* Call also a filter function from dashboard before showing the designs
*/
return tve_filter_intrusive_forms( 'tu', $designs );
}
/**
* Returns the event's data from DB
*
* @return array|null|object|void
*/
protected function get_data() {
$hours = $this->campaign->tu_schedule_instance->hours_until_end();
global $tve_ult_db;
$data = $tve_ult_db->get_closest_event( $this->campaign->ID, $hours );
if ( $data ) {
$data['actions'] = unserialize( $data['actions'] );
}
return $data;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,90 @@
<?php
class TU_Product extends TVE_Dash_Product_Abstract {
protected $tag = 'tu';
protected $title = 'Thrive Ultimatum';
protected $slug = 'thrive-ultimatum';
protected $productIds = array();
protected $type = 'plugin';
protected $version = TVE_Ult_Const::PLUGIN_VERSION;
protected $needs_architect = true;
public function __construct( $data = array() ) {
parent::__construct( $data );
$this->logoUrl = TVE_Ult_Const::plugin_url( 'admin/img/logo_90x90.png' );
$this->logoUrlWhite = TVE_Ult_Const::plugin_url( 'admin/img/logo_90x90-white.png' );
$this->incompatible_architect_version = ! tve_ult_check_tcb_version();
$this->description = __( 'Ultimate scarcity plugin for WordPress', 'thrive-ult' );
$this->button = array(
'active' => true,
'url' => admin_url( 'admin.php?page=tve_ult_dashboard' ),
'label' => __( 'Ultimatum Dashboard', 'thrive-ult' ),
);
$this->moreLinks = array(
'tutorials' => array(
'class' => '',
'icon_class' => 'tvd-icon-graduation-cap',
'href' => 'https://thrivethemes.com/thrive-ultimatum-tutorials/',
'target' => '_blank',
'text' => __( 'Tutorials', 'thrive-cb' ),
),
'support' => array(
'class' => '',
'icon_class' => 'tvd-icon-life-bouy',
'href' => 'https://thrivethemes.com/support/',
'target' => '_blank',
'text' => __( 'Support', 'thrive-ult' ),
),
);
}
public static function reset_plugin() {
global $wpdb;
$query = new WP_Query( array(
'post_type' => array(
TVE_Ult_Const::POST_TYPE_NAME_FOR_SCHEDULE,
TVE_Ult_Const::POST_TYPE_NAME_FOR_CAMPAIGN,
),
'fields' => 'ids',
'posts_per_page' => '-1',
)
);
$post_ids = $query->posts;
foreach ( $post_ids as $id ) {
wp_delete_post( $id, true );
}
$tables = array(
'event_log',
'events',
'emails',
'designs',
'settings_campaign',
'settings_templates',
);
foreach ( $tables as $table ) {
$table_name = tve_ult_table_name( $table );
$sql = "TRUNCATE TABLE $table_name";
$wpdb->query( $sql );
}
$wpdb->query(
"DELETE FROM $wpdb->options WHERE
`option_name` LIKE '%tve_ult%';"
);
}
}

View File

@@ -0,0 +1,30 @@
<?php
class TU_Request_Handler {
/**
* Search the key in request and returns it
* If the key does not exists default value is returned
*
* @param string $key
* @param mixed $default
*
* @return mixed
*/
protected function param( $key, $default = null ) {
return isset( $_POST[ $key ] ) ? $_POST[ $key ] : ( isset( $_REQUEST[ $key ] ) ? $_REQUEST[ $key ] : $default );
}
/**
* forward the call based on the $action parameter
* API entry-point for the template chooser lightbox (from the editor)
*
* @param string $action
*/
public function api( $action ) {
$method = 'api_' . $action;
$result = call_user_func( array( $this, $method ) );
wp_send_json( $result );
}
}

View File

@@ -0,0 +1,100 @@
<?php
/**
* Created by PhpStorm.
* User: radu
* Date: 06.02.2016
* Time: 15:05
*/
class TU_Schedule_Absolute extends TU_Schedule_Abstract {
/**
* check if the campaign should be displayed
*/
public function applies( $force_apply = false ) {
//check if end cookie is set for this campaign
if ( isset( $_COOKIE[ $this->cookie_end_name() ] ) ) {
return false;
}
if ( $this->is_future( $this->settings['end'] ) && $this->is_past( $this->settings['start'] ) ) {
// 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;
}
}
}
return true;
}
return false;
}
/**
* Returns the number of hours remained until the campaign/interval ends
*
* @return int
*/
public function hours_until_end() {
$now = date( 'Y-m-d H:i', $this->now() );
$end = date( 'Y-m-d H:i', $this->date( $this->settings['end'] ) );
$diff = tve_ult_date_diff( $now, $end );
return ( $diff['days'] * 24 ) + $diff['hours'];
}
/**
* 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() {
return date( 'Y-m-d H:i:00', $this->date( $this->settings['end'] ) );
}
/**
* @inheritdoc
*/
public function get_duration() {
$start_date = tve_ult_pre_format_date( $this->settings['start']['date'], $this->settings['start']['time'] );
$end_date = tve_ult_pre_format_date( $this->settings['end']['date'], $this->settings['end']['time'] );
$diff = tve_ult_date_diff( $start_date, $end_date );
return $diff['days'] * 24 + $diff['hours'];
}
/**
* checks if the campaign is not yet started
*
* @return bool
*/
public function should_redirect_pre_access() {
if ( isset( $_GET['tu_id'] ) && $_GET['tu_id'] != $this->campaign_id ) {
return false;
}
return $this->is_future( $this->settings['start'] );
}
/**
* checks if the campaign has ended - either the end date is in the past, or this campaign has ended due to a conversion event
*
* @return bool
*/
public function should_redirect_expired() {
if ( isset( $_COOKIE[ $this->cookie_end_name() ] ) ) {
return true;
}
return $this->is_past( $this->settings['end'] );
}
}

View File

@@ -0,0 +1,445 @@
<?php
/**
* Base class for campaign schedules
*/
abstract class TU_Schedule_Abstract {
/**
* Campaign schedule settings
*
* @var array
*/
protected $settings = array();
protected $conversion_events = array();
protected $lockdown = '';
/**
* Campaign for which this schedule applies
*
* @var int
*/
protected $campaign_id;
protected static $types = array(
TVE_Ult_Const::CAMPAIGN_TYPE_ABSOLUTE => 'TU_Schedule_Absolute',
TVE_Ult_Const::CAMPAIGN_TYPE_ROLLING => 'TU_Schedule_Rolling',
TVE_Ult_Const::CAMPAIGN_TYPE_EVERGREEN => 'TU_Schedule_Evergreen',
);
/**
* TVE_Ult_Schedule_Abstract constructor.
*
* @param int $campaign_id
*/
public function __construct( $campaign_id ) {
$this->campaign_id = $campaign_id;
}
/**
* Instantiates a campaign schedule based on campaign type
*
* @param string $campaign_id
*
* @return TU_Schedule_Abstract
*/
public static function factory( $campaign_id ) {
$campaign_type = get_post_meta( $campaign_id, TVE_Ult_Const::META_NAME_FOR_CAMPAIGN_TYPE, true );
/**
* if nothing is set for a campaign, return an empty container
*/
if ( ! isset( self::$types[ $campaign_type ] ) ) {
require_once TVE_Ult_Const::plugin_path() . 'inc/classes/class-tu-schedule-none.php';
return new TU_Schedule_None( $campaign_id );
}
return new static::$types[ $campaign_type ]( $campaign_id );
}
/**
* Check if the schedule for a campaign applies (for the current date)
*
* @return bool
*/
public abstract function applies( $force_apply = false );
/**
* set schedule settings
*
* @param array $settings
*
* @return $this
*/
public function set( $settings = null ) {
if ( is_null( $settings ) ) {
$settings = tve_ult_get_campaign_settings( $this->campaign_id );
}
$this->settings = $settings;
return $this;
}
/**
* Getter for schedule settings
*
* @return array schedule settings
*/
public function get() {
return $this->settings;
}
/**
* Getter for conversion events
*
* @return array
*/
public function get_conversion_events() {
return $this->conversion_events;
}
/**
* Setter for conversion events
*
* @param array $conversion_events
*/
public function set_conversion_events( $conversion_events ) {
$this->conversion_events = $conversion_events;
}
/**
* Getter for lockdown
*
* @return array
*/
public function get_lockdown() {
return $this->lockdown;
}
/**
* Setter for lockdown
*
* @param array $lockdown
*/
public function set_lockdown( $lockdown ) {
$this->lockdown = $lockdown;
}
/**
* @param $offset
*
* @return string
*/
protected function format_gmt_offset( $offset ) {
$h = (int) $offset;
$remainder = $offset - $h;
return ( ( $h < 0 ) ? '-' : '+' ) .
str_pad( abs( $h ), 2, '0', STR_PAD_LEFT ) . ':' .
str_pad( abs( $remainder ) * 60, 2, STR_PAD_LEFT );
}
/**
* Returns the current date / time as a timestamp
* it takes into account also the default timezone on the server
*
* @param bool $strip_seconds
* @param bool $gmt
*
* @return int $timestamp
*/
public function now( $strip_seconds = true, $gmt = false ) {
/**
* this will return the current time set from the server, with the difference set in gmt_offset option added / substracted from the time
*
* floor this value to the :00 seconds
*/
if ( $strip_seconds ) {
$time = floor( tve_ult_current_time( 'timestamp', $gmt ) / 60 ) * 60;
} else {
$time = tve_ult_current_time( 'timestamp', $gmt );
}
return $time;
}
/**
* Gets the timestamp for the given date, based on the gmt_offset option from WP admin
*
* @param string|array $date
*
* @return int timestamp
*/
protected function date( $date ) {
//TODO: is there anything else needed here ?
// if the date is coming from our meta let's make it a string
if ( is_array( $date ) ) {
$date = tve_ult_pre_format_date( $date['date'], $date['time'] );
}
return strtotime( $date );
}
/**
* Checks if a date is in the past
*
* @param string $date Y-m-d H:i:s representation of the date
*
* @return bool
*/
public function is_past( $date ) {
return $this->date( $date ) < $this->now();
}
/**
* Checks if a date received as parameter is in the future
*
* @param string $date Y-m-d H:i:s representation of the date
*
* @return bool
*/
public function is_future( $date ) {
return $this->date( $date ) > $this->now();
}
/**
* Check if any of the triggers match for ending the campaign
*
* @param $options
*
* @return bool
*/
public function check_triggers( $options ) {
// check if the trigger is a specific page or a conversion
if ( $options['trigger'] === TVE_Ult_Const::TRIGGER_OPTION_CONVERSION ) {
return true;
} else {
$post_id = $this->param( 'post_id' );
if ( $post_id !== $options['trigger_ids'] ) {
return true;
}
}
$this->do_conversion( $options );
return false;
}
/**
* Based on triggers update the email log saved in cookie
* with options sent as parameter;
*
* To be implemented in child classes
*
* @param array $trigger_options
* @param array $options
*/
public function update_email_log( $trigger_options = array(), $options = array() ) {
}
/**
*
* checks if a conversion event is fulfilled for a campaign
* if the action is "move to a new campaign" - we need to force the display of that campaign
* to do this, we set a special cookie - tu_force_campaign
*
* @param array $options trigger options
*/
public function do_conversion( $options ) {
if ( $options['event'] === TVE_Ult_Const::TRIGGER_OPTION_MOVE ) {
$campaign = tve_ult_get_campaign( $options['end_id'], array(
'get_settings' => true,
) );
/** @var TU_Schedule_Abstract $related_campaign_schedule */
$related_campaign_schedule = $campaign->tu_schedule_instance;
// cannot start a campaign if its status is not running
// check if the campaign didn't already start for this user
if ( $campaign->status === TVE_Ult_Const::CAMPAIGN_STATUS_RUNNING && ! isset( $_COOKIE[ $this->cookie_name( $options['end_id'] ) ] ) ) {
// get campaign settings
$settings = get_post_meta( $options['end_id'], TVE_Ult_Const::META_NAME_FOR_CAMPAIGN_SETTINGS, true );
// set cookie
$start_date['date'] = date( 'j F Y', $this->now() );
$start_date['time'] = date( 'H:i:s', $this->now() );
$value = maybe_serialize( array( 'start_date' => $start_date ) );
//set the cookie expiration date
// there are issues on 32 bit platforms using this: we need to make sure that this is not in the past (something like 1907)
$expire = strtotime( '+' . ( $settings['end'] + $settings['duration'] ) . ' days', $this->date( $start_date ) );
if ( $expire < tve_ult_current_time( 'timestamp' ) ) { // overflow
$expire = strtotime( '2038-01-01 ' );
}
/**
* This means that a new evergreen campaign is started for a conversion event of this campaign
* this takes priority over any other campaign that should be displayed on this request - regardless of the priority settings (order of the campaigns)
*/
setcookie( $related_campaign_schedule->cookie_name(), $value, $expire, '/' );
$_COOKIE[ $related_campaign_schedule->cookie_name() ] = $value;
/**
* set a cookie that will force the display of this campaign
*/
$now_wp_time = tve_ult_current_time( 'Y-m-d H:i:s' );
setcookie( $related_campaign_schedule->cookie_force_display(), $now_wp_time, $expire, '/' );
$_COOKIE[ $related_campaign_schedule->cookie_force_display() ] = $now_wp_time;
}
}
if ( ! isset( $_COOKIE[ $this->cookie_end_name() ] ) ) {
/**
* the conversion can be made only if the campaign is not ended
*/
$this->register_conversion();
setcookie( $this->cookie_end_name(), 'end', time() + ( YEAR_IN_SECONDS * 10 ), '/' );
/**
* also, unset the "force_campaign" cookie
*/
setcookie( $this->cookie_force_display(), '', time() - DAY_IN_SECONDS * 200, '/' );
unset( $_COOKIE[ $this->cookie_force_display() ] );
}
}
/**
* Register conversion and
* Set cookie for conversion
*/
public function register_conversion() {
if ( ! isset( $_COOKIE[ TVE_Ult_Const::COOKIE_IMPRESSION . $this->campaign_id ] ) ) {
return;
}
if ( isset( $_COOKIE[ TVE_Ult_Const::COOKIE_CONVERSION . $this->campaign_id ] ) ) {
return;
}
if ( tve_dash_is_crawler() ) {
return;
}
tve_ult_register_conversion( $this->campaign_id );
$expire = tve_ult_current_time( 'timestamp' ) + YEAR_IN_SECONDS;
$value = date( 'Y-m-d H:i:s' );
/*
* expiration dates for cookies:
* - for evergreen campaigns: the number of days entered in the "Don't show this campaign until" field
* - for others: 1 year
* also modifies the global $_COOKIE variable - so that it's available later in the same request if required
*/
if ( $this instanceof TU_Schedule_Evergreen && ! empty( $this->settings ) && ! empty( $this->settings['end'] ) ) {
$start_date = $_COOKIE[ TVE_Ult_Const::COOKIE_IMPRESSION . $this->campaign_id ];
$expire = strtotime( $start_date ) + $this->settings['end'] * DAY_IN_SECONDS;
}
setcookie( TVE_Ult_Const::COOKIE_CONVERSION . $this->campaign_id, $value, $expire, '/' );
$_COOKIE[ TVE_Ult_Const::COOKIE_CONVERSION . $this->campaign_id ] = $value;
}
/**
* Loops through conversion events of campaign
* And if there are specific trigger that match the post_id
* does the conversion
*
* If an event is executed then the design should not be displayed
*
* @param WP_Post $campaign
* @param int $post_id
*
* @return bool if any conversion event was executed
* @see do_conversion()
*
*/
public function check_specific_events( $campaign, $post_id ) {
$event_executed = false;
foreach ( $campaign->conversion_events as $event ) {
if ( $event['trigger_options']['trigger'] === TVE_Ult_Const::TRIGGER_OPTION_SPECIFIC && $post_id == $event['trigger_options']['trigger_ids'] ) {
/** @var TU_Schedule_Abstract $schedule */
$schedule = $campaign->tu_schedule_instance;
$schedule->do_conversion( $event['trigger_options'] );
$event_executed = true;
}
}
return $event_executed;
}
/**
* @param mixed $id a campaign id
*
* @return string
*/
public function cookie_name( $id = null ) {
return TVE_Ult_Const::COOKIE_NAME . ( is_null( $id ) ? $this->campaign_id : $id );
}
/**
*
* @return string
*/
public function cookie_end_name() {
return TVE_Ult_Const::COOKIE_END_NAME . $this->campaign_id;
}
protected function param( $key, $default = null ) {
return isset( $_POST[ $key ] ) ? $_POST[ $key ] : ( isset( $_REQUEST[ $key ] ) ? $_REQUEST[ $key ] : $default );
}
/**
* get the force display cookie for a campaign
*
* @return string
*/
public function cookie_force_display() {
return TVE_Ult_Const::COOKIE_FORCE_DISPLAY . $this->campaign_id;
}
/**
* @return string
*/
public function get_redirect_cookie_key(){
return TVE_Ult_Const::COOKIE_REDIRECT . $this->campaign_id;
}
/**
* 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 abstract function get_end_date();
/**
* Returns how many hours a schedule occurs
*
* @return int
*/
public abstract function get_duration();
/**
* Should check whether or not this campaign should redirect the user to a pre-access page
*
* @return bool
*/
public abstract function should_redirect_pre_access();
/**
* Should check whether or not this campaign has ended and the user should be redirected to the expired page
*
* @return bool
*/
public abstract function should_redirect_expired();
}

View File

@@ -0,0 +1,770 @@
<?php
/**
* Created by PhpStorm.
* User: radu
* Date: 08.02.2016
* Time: 10:24
*/
class TU_Schedule_Evergreen extends TU_Schedule_Abstract {
/**
* Check if we have a special gmt set on this campaign
*
* @return bool
*/
public function use_gmt() {
/**
* Either is an absolute campaign so we need to use WP timezone
* Either is real and have a timezone set
*/
return empty( $this->settings['real'] ) || ( ! empty( $this->settings['real'] ) && ! empty( $this->settings['gmt_offset'] ) );
}
public function applies( $force_apply = false ) {
$apply = false;
$args = func_get_args();
$email = $this->param( 'email' );
if ( empty( $email ) && isset( $args[1] ) && filter_var( $args[1], FILTER_VALIDATE_EMAIL ) ) {
$email = $args[1];
}
// check if we have a cookie set
if ( ! isset( $_COOKIE[ $this->cookie_name( $this->campaign_id ) ] ) ) {
$use_gmt = $this->use_gmt();
// set the start date of the campaign
$start_date['date'] = date( 'j F Y', $this->now( true, $use_gmt ) );
$start_date['time'] = date( 'H:i:s', $this->now( false, $use_gmt ) );
$mysql_start_date = date( 'Y-m-d H:i:s', $this->now( false, $use_gmt ) );
$value = array(
'start_date' => $start_date,
);
$value = maybe_serialize( $value );
if ( empty( $this->settings['evergreen_repeat'] ) ) {
$expire = strtotime( '2038-01-01 ' );
} else {
$end_after = (int) $this->settings['end'] + (int) $this->settings['duration'];
$expire = $this->calc_real_end_time( strtotime( '+' . $end_after . ' days', $this->date( $start_date ) ) );
}
//check the cookie trigger
if ( $this->settings['trigger']['type'] === TVE_Ult_Const::TRIGGER_TYPE_FIRST_VISIT ) {
//set the cookie
$apply = $this->setCookie( $value, $expire );
}
// get the current post ID, we need to check if the trigger matches
$post_id = (int) $this->param( 'post_id', 0 );
$days = empty( $this->settings['days_duration'] ) ? 0 : (int) $this->settings['days_duration'];
$hours = empty( $this->settings['hours_duration'] ) ? 0 : (int) $this->settings['hours_duration'];
$minutes = empty( $this->settings['minutes_duration'] ) ? 0 : (int) $this->settings['minutes_duration'];
$seconds = empty( $this->settings['seconds_duration'] ) ? 0 : (int) $this->settings['seconds_duration'];
if ( empty( $days ) && empty( $hours ) && empty( $minutes ) && empty( $seconds ) ) {
/* this is for old campaigns that didn't had a specific end date set, so we're using only days */
$days = empty( $this->settings['duration'] ) ? 0 : (int) $this->settings['duration'];
}
/* duration in seconds */
$duration = $days * DAY_IN_SECONDS + $hours * HOUR_IN_SECONDS + $minutes * MINUTE_IN_SECONDS + $seconds;
$start_date = date( 'Y-m-d H:i:s', $this->now( false, $use_gmt ) );
$end_date = date( 'Y-m-d H:i:s', strtotime( $start_date . ' +' . $duration . ' seconds' ) );
$end_date = date( 'Y-m-d H:i:s', $this->calc_real_end_time( strtotime( $end_date ) ) );
if ( $this->settings['trigger']['type'] === TVE_Ult_Const::TRIGGER_TYPE_PAGE_VISIT && $post_id === $this->settings['trigger']['ids'] ) {
$apply = $this->setCookie( $value, $expire );
if ( ! isset( $_COOKIE[ $this->get_redirect_cookie_key() ] ) && ! empty( $this->settings['redirect'] ) && ! empty( $this->settings['redirect_url'] ) ) {
$redirect_value = [
'start_date' => $start_date,
'redirect_url' => $this->settings['redirect_url'],
'promotion' => $post_id,
'end_date' => $end_date,
];
$redirect_value = maybe_serialize( $redirect_value );
$this->setCookieRedirect( $redirect_value, $expire );
}
}
/* check if a conversion has been done during a form submit */
if ( $this->settings['trigger']['type'] === TVE_Ult_Const::TRIGGER_OPTION_CONVERSION && $this->param( 'action' ) === 'tve_api_form_submit' ) {
$quiz_page_id = (int) $this->param( 'tqb-variation-page_id', 0 );
if ( in_array( $post_id, $this->settings['trigger']['ids'] ) || in_array( $quiz_page_id, $this->settings['trigger']['ids'] ) ) {
$apply = $this->setCookie( $value, $expire );
if ( $apply && $this->param( 'email' ) ) {
// save the email log to the database
tve_ult_save_email_log( array(
'campaign_id' => $this->campaign_id,
'email' => $this->param( 'email' ),
'started' => $mysql_start_date,
) );
}
}
}
/**
* Force is used on automation where the campaign should triggered no matter what the settings are
*/
if ( $force_apply && ! $apply ) {
$apply = $this->setCookie( $value, $expire );
}
if ( $apply || $force_apply ) {
tve_ult_send_evergreen_campaign_start_hook( $this->campaign_id, $email );
}
/**
* if there is a campaign's cookie then we need to read it and update the email log's {end} prop with {0}
* mark it as non-ended
*/
$this->update_email_log( array(), array( 'end' => 0 ) );
}
//check if end cookie is set for this campaign
if ( isset( $_COOKIE[ $this->cookie_end_name() ] ) ) {
return false;
}
//get the start date from cookie
$data = $this->get_cookie_data();
// check if the campaign should be shown
if ( isset( $data['end_date'], $data['start_date'] ) && $this->is_future( $data['end_date'] ) && $this->is_past( $data['start_date'] ) ) {
// 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;
}
}
}
$apply = true;
}
return $apply;
}
/**
* Overwrite the function so we can add our own offset
*
* @param bool $strip_seconds
* @param bool $use_gmt
*
* @return int $timestamp
*/
public function now( $strip_seconds = true, $use_gmt = false ) {
if ( $use_gmt ) {
$time = time();
if ( empty( $this->settings['gmt_offset'] ) ) {
$gmt_offset = tve_ult_gmt_offset() * HOUR_IN_SECONDS;
} else {
$gmt_offset = tve_ult_gmt_offset_from_tzstring( $this->settings['gmt_offset'] ) * HOUR_IN_SECONDS;
}
$time += (int) $gmt_offset;
if ( $strip_seconds ) {
$time = floor( $time / 60 ) * 60;
}
} else {
$time = parent::now( $strip_seconds );
}
return $time;
}
/**
* Checks if a date received as parameter is in the future
*
* @param string $date Y-m-d H:i:s representation of the date
*
* @return bool
*/
public function is_future( $date ) {
return $this->date( $date ) > $this->now( true, $this->use_gmt() );
}
/**
* Checks if realTime option is set and
* adds calculates the real time
*
* @param int $end_time
*
* @return int timestamp
*/
public function calc_real_end_time( $end_time ) {
if ( empty( $this->settings['real'] ) ) {
return $end_time;
}
$realtime = empty( $this->settings['realtime'] ) ? '00:00' : $this->settings['realtime'];
//for the expiration date set the real time
$real = date( 'Y-m-d', $end_time ) . ' ' . $realtime . ':00';
$real = strtotime( $real );
//if the real is behind expiration add +1 day
if ( $real < $end_time ) {
$real = strtotime( '+1day', $real );
}
return $real;
}
/**
* Un-serializes and read in the cookie data
*
* @return array
*/
public function get_cookie_data() {
if ( ! isset( $_COOKIE[ $this->cookie_name( $this->campaign_id ) ] ) ) {
return array();
}
$value = stripcslashes( $_COOKIE[ $this->cookie_name( $this->campaign_id ) ] );
if ( is_serialized( $value ) ) {
$value = thrive_safe_unserialize( trim( $value ) );
}
$value['start_date']['date'] = urldecode( $value['start_date']['date'] );
$start_date = tve_ult_pre_format_date( $value['start_date']['date'], $value['start_date']['time'] );
$start_end_dates = $this->get_start_end_dates( $start_date );
$start_end_dates['cookie'] = $value;
return $start_end_dates;
}
/**
* Un-serializes and read in the cookie redirect data
*
* @return array
*/
public function get_cookie_redirect_data() {
if ( ! isset( $_COOKIE[ $this->get_redirect_cookie_key() ] ) ) {
return array();
}
$value = stripcslashes( $_COOKIE[ $this->get_redirect_cookie_key() ] );
if ( is_serialized( $value ) ) {
$value = thrive_safe_unserialize( trim( $value ) );
}
$value['start_date'] = urldecode( $value['start_date'] );
$start_end_dates = $this->get_start_end_dates( $value['start_date'] );
$start_end_dates['cookie'] = $value;
return $start_end_dates;
}
/**
* Return an array of start and end dates from the start date
*
* @param $start_date
*
* @return array
*/
public function get_start_end_dates( $start_date ) {
$days = empty( $this->settings['days_duration'] ) ? 0 : (int) $this->settings['days_duration'];
$hours = empty( $this->settings['hours_duration'] ) ? 0 : (int) $this->settings['hours_duration'];
$minutes = empty( $this->settings['minutes_duration'] ) ? 0 : (int) $this->settings['minutes_duration'];
$seconds = empty( $this->settings['seconds_duration'] ) ? 0 : (int) $this->settings['seconds_duration'];
if ( empty( $days ) && empty( $hours ) && empty( $minutes ) && empty( $seconds ) ) {
/* this is for old campaigns that didn't had a specific end date set, so we're using only days */
$days = empty( $this->settings['duration'] ) ? 0 : (int) $this->settings['duration'];
}
$duration = $days * DAY_IN_SECONDS + $hours * HOUR_IN_SECONDS + $minutes * MINUTE_IN_SECONDS + $seconds;
$end_date = date( 'Y-m-d H:i:s', strtotime( $start_date . ' +' . $duration . ' seconds' ) );
$end_date = date( 'Y-m-d H:i:s', $this->calc_real_end_time( strtotime( $end_date ) ) );
return array(
'start_date' => $start_date,
'end_date' => $end_date,
);
}
/**
* Updates the email log set in campaign's COOKIE
* By default sets the {end} property to {1}
*
* If email_log_id is not saved in COOKIE then nothing happens
*
* @param array $trigger_options
* @param array $options
*
* @return false|int
*/
public function update_email_log( $trigger_options = array(), $options = array() ) {
if ( ! isset( $_COOKIE[ $this->cookie_name() ] ) ) {
return false;
}
$data = $this->get_cookie_data();
if ( ! isset( $data['cookie']['lockdown'] ) || empty( $data['cookie']['lockdown']['log_id'] ) ) {
return false;
}
$updates = array(
'end' => 1,
);
$updates = array_merge( $updates, $options );
global $tve_ult_db;
$model = $tve_ult_db->get_email_log_by_id( $data['cookie']['lockdown']['log_id'] );
$model = array_merge( $model, $updates );
return $tve_ult_db->save_email_log( $model );
}
/**
* Returns the number of hours remained until the campaign/interval ends
*
* @return int
*/
public function hours_until_end() {
if ( ! isset( $_COOKIE[ $this->cookie_name( $this->campaign_id ) ] ) ) {
return $this->now();
}
$value = stripcslashes( $_COOKIE[ $this->cookie_name( $this->campaign_id ) ] );
if ( is_serialized( $value ) ) {
$value = thrive_safe_unserialize( $value );
}
$start_date = tve_ult_pre_format_date( $value['start_date']['date'], $value['start_date']['time'] );
$now = date( 'Y-m-d H:i:s', $this->now() );
$end = date( 'Y-m-d H:i:s', strtotime( $start_date ) + $this->duration_in_seconds() );
/**
* calc the real end time
*/
$end = date( 'Y-m-d H:i:s', $this->calc_real_end_time( strtotime( $end ) ) );
$diff = tve_ult_date_diff( $now, $end );
return ( $diff['days'] * 24 ) + $diff['hours'];
}
/**
* get the end date of the current campaign instance (interval)
* based on campaign's cookie
*
* should return a date in the format: Y-m-d H:i:s
*
* @return string
*/
public function get_end_date() {
if ( ! ( $data = $this->get_cookie_data() ) ) {
return '';
}
// for evergreen campaigns, we need to also take into account the exact second at which the campaign was started
$start_parts = explode( ':', isset( $data['cookie']['start_date']['time'] ) ? $data['cookie']['start_date']['time'] : '00:00:00' );
$seconds = count( $start_parts ) === 2 ? '00' : $start_parts[2];
$has_seconds = count( explode( ':', $data['end_date'] ) ) === 3;
return $data['end_date'] . ( ! $has_seconds ? ':' . $seconds : '' ); // we also need seconds
}
/**
* Get the duration
*
* @return mixed
*/
public function get_duration() {
return $this->settings['duration'] * 24;
}
/**
* Check if we should redirect to pre-access page or not
*
* @return bool:
* - true: there is no valid request or there is no cookie or, in case of webhook-triggered campaigns, the webhook has not been received yet
* - false: if there is valid request or the is valid cookie
*/
public function should_redirect_pre_access() {
$email = isset( $_GET['tu_em'] ) ? sanitize_email( $_GET['tu_em'] ) : '';
$email = filter_var( $email, FILTER_VALIDATE_EMAIL );
$valid_request = ! empty( $email ) && ! empty( $_GET['tu_id'] ) && $_GET['tu_id'] == $this->campaign_id;
$valid_cookie = isset( $_COOKIE[ $this->cookie_name() ] );
/**
* For campaigns triggered by webhooks, we also need to check if we have a email log entry with this email. if not, redirect to pre-access page
*/
if ( $valid_request && ! empty( $this->settings['trigger']['type'] ) && $this->settings['trigger']['type'] === 'webhook' ) {
$webhook_log = tve_ult_get_email_log( $this->campaign_id, $email );
if ( empty( $webhook_log ) ) {
$valid_request = false;
}
}
if ( $valid_request || $valid_cookie ) {
/**
* do not redirect because we have request or cookie
*/
return false;
}
/**
* redirect because we have no request ether cookie
*/
return true;
}
/**
* if the campaign has started and is currently ended, redirect the user to the expired page
*
* TODO: this needs more tweaks: I think we need to better identify the end date
*
* @return bool
*/
public function should_redirect_expired() {
if ( isset( $_COOKIE[ $this->cookie_end_name() ] ) ) {
return true;
}
//we need to check the end date from the db too
$cookie_end_date = $this->get_end_date();
if ( empty( $cookie_end_date ) && empty( $_GET['tu_em'] ) ) {
return true;
}
$should_redirect = false;
$email = isset( $_GET['tu_em'] ) ? $_GET['tu_em'] : null;
if ( $email_log = tve_ult_get_email_log( $this->campaign_id, $email ) ) {
$log_end_date = date( 'Y-m-d H:i:s', strtotime( $email_log['started'] ) + $this->duration_in_seconds() );
$log_end_date = $this->calc_real_end_time( strtotime( $log_end_date ) );
$log_end_date = date( 'Y-m-d H:i:s', $log_end_date );
$should_redirect = $email_log['end'] == 1 || $this->is_past( $log_end_date );
}
$should_redirect = $should_redirect || ! empty( $cookie_end_date ) && $this->is_past( $cookie_end_date );
if ( $should_redirect && ! isset( $_COOKIE[ $this->cookie_end_name() ] ) ) {
$this->set_end_cookie();
}
return $should_redirect;
}
/**
*
* checks if a conversion event is fulfilled for a campaign
* if the action is "move to a new campaign" - we need to force the display of that campaign
* to do this, we set a special cookie - tu_force_campaign
*
* @param array $options trigger options
*/
public function do_conversion( $options ) {
if ( $options['event'] === TVE_Ult_Const::TRIGGER_OPTION_MOVE ) {
$related_campaign = tve_ult_get_campaign( $options['end_id'], array(
'get_settings' => true,
) );
/** @var TU_Schedule_Abstract $related_campaign_schedule */
$related_campaign_schedule = $related_campaign->tu_schedule_instance;
// cannot start a campaign if its status is not running
// check if the campaign didn't already start for this user
if ( $related_campaign->status === TVE_Ult_Const::CAMPAIGN_STATUS_RUNNING && ! isset( $_COOKIE[ $this->cookie_name( $options['end_id'] ) ] ) ) {
// get campaign settings
$settings = get_post_meta( $options['end_id'], TVE_Ult_Const::META_NAME_FOR_CAMPAIGN_SETTINGS, true );
// set cookie
$start_date['date'] = date( 'j F Y', $this->now() );
$start_date['time'] = date( 'H:i:s', $this->now( false ) );
$value = maybe_serialize( array( 'start_date' => $start_date ) );
//set the cookie expiration date
// there are issues on 32 bit platforms using this: we need to make sure that this is not in the past (something like 1907)
$expire = strtotime( '+' . ( $settings['end'] + $settings['duration'] ) . ' days', $this->date( $start_date ) );
$expire = $this->calc_real_end_time( $expire );
if ( $expire < tve_ult_current_time( 'timestamp' ) ) { // overflow
$expire = strtotime( '2038-01-01 ' );
}
/**
* This means that a new evergreen campaign is started for a conversion event of this campaign
* this takes priority over any other campaign that should be displayed on this request - regardless of the priority settings (order of the campaigns)
*/
setcookie( $related_campaign_schedule->cookie_name(), $value, $expire, '/' );
$_COOKIE[ $related_campaign_schedule->cookie_name() ] = $value;
/**
* set a cookie that will force the display of this campaign
*/
$now_wp_time = tve_ult_current_time( 'Y-m-d H:i:s' );
setcookie( $related_campaign_schedule->cookie_force_display(), $now_wp_time, $expire, '/' );
$_COOKIE[ $related_campaign_schedule->cookie_force_display() ] = $now_wp_time;
/**
* for linked lockdown campaign we need to save a email log in DB
* in this way when the user triggers the linked campaign in new browser we know him and we know that time to show
*/
$data = $this->get_cookie_data();
if ( ! empty( $data['cookie'] ) && ( $cookie_data = $data['cookie'] ) && ! empty( $cookie_data['lockdown'] ) ) {
tve_ult_save_email_log( array(
'campaign_id' => $related_campaign->ID,
'email' => ! empty( $cookie_data['lockdown']['email'] ) ? $cookie_data['lockdown']['email'] : null,
'started' => tve_ult_pre_format_date( date( 'j F Y', $this->now() ), date( 'H:i:s', $this->now( false ) ) ),
'has_impression' => 1,
) );
}
}
}
if ( ! isset( $_COOKIE[ $this->cookie_end_name() ] ) ) {
/**
* the conversion can be made only if the campaign is not ended
*/
$this->register_conversion();
$this->set_end_cookie();
}
$this->update_email_log( $options );
}
/**
* Save the email in the db
*
* @param data
*
* @return false|int
*/
public function save_email_log( $data ) {
$model['campaign_id'] = $this->campaign_id;
isset( $data['date'] ) ? $model['started'] = $data['date'] : $model['started'] = date( 'Y-m-d H:i:s', $this->now( false ) );
isset( $_GET['tu_em'] ) && ! isset( $data['email'] ) ? $model['email'] = $_GET['tu_em'] : $model['email'] = $data['email'];
if ( isset( $data['type'] ) ) {
$model['type'] = $data['type'];
}
return tve_ult_save_email_log( $model );
}
/**
* Create the cookie for the user
*
* @param $value
* @param $expire
*
* @return bool
*/
public function setCookie( $value, $expire ) {
if ( ! headers_sent() ) {
setcookie( $this->cookie_name( $this->campaign_id ), $value, $expire, '/' );
}
if ( $expire <= $this->now( false ) ) {
unset( $_COOKIE[ $this->cookie_name( $this->campaign_id ) ] );
return false;
}
$_COOKIE[ $this->cookie_name( $this->campaign_id ) ] = $value;
return true;
}
public function setCookieRedirect( $value, $expire ) {
if ( ! headers_sent() ) {
setcookie( $this->get_redirect_cookie_key(), $value, $expire, '/' );
}
if ( $expire <= $this->now( false ) ) {
unset( $_COOKIE[ $this->get_redirect_cookie_key() ] );
return false;
}
$_COOKIE[ $this->get_redirect_cookie_key() ] = $value;
return true;
}
/**
* Check if the cookie has the lockdown options
*
* @return bool
*/
public function verify_cookie() {
$cookie = $this->get_cookie_data();
return ! empty( $cookie['cookie']['lockdown']['email'] ) && ! empty( $cookie['cookie']['lockdown']['log_id'] );
}
/**
* Check if we have data in the db and save it, also save the cookie
*
* @param $params
*/
public function set_cookie_and_save_log( $params ) {
if ( empty( $params['start_date'] ) ) {
/* calculate gmt for start date only when we also have gmt for end date */
$use_gmt = $this->use_gmt();
$params['start_date']['date'] = date( 'j F Y', $this->now( true, $use_gmt ) );
$params['start_date']['time'] = date( 'H:i:s', $this->now( false, $use_gmt ) );
}
$db = tve_ult_get_email_log( $this->campaign_id, $params['lockdown']['email'] );
$date = tve_ult_pre_format_date( $params['start_date']['date'], $params['start_date']['time'] );
/**
* Checks performed for a repeating evergreen campaign:
* if a repeating evergreen campaign has been shown before to the user and the required amount of time has passed, the campaign should be shown again*
* *only if the time setup form "Repeat after" has passed
*/
if ( ! empty( $db ) && ! isset( $_COOKIE[ $this->cookie_name() ] ) && ! empty( $this->settings['evergreen_repeat'] ) ) {
/* check if the required amount of time has passed since the previous campaign has been displayed */
$end_after_days = (int) $this->settings['end'] + (int) $this->settings['duration'];
/*
* a "cycle" ends when the campaign has ended and the time setup in "Display this campaign again after x days" has also passed
*/
$cycle_end = $this->calc_real_end_time( strtotime( '+' . $end_after_days . ' days', $this->date( $db['started'] ) ) );
if ( $cycle_end < tve_ult_current_time( 'timestamp' ) ) {
$db['started'] = date( 'Y-m-d H:i:s', $this->now( false ) );
tve_ult_save_email_log( $db );
}
}
if ( ! isset( $db ) ) {
$data = array(
'date' => $date,
'email' => $params['lockdown']['email'],
);
if ( isset( $params['lockdown']['type'] ) ) {
$data['type'] = $params['lockdown']['type'];
unset( $params['lockdown']['type'] );
}
$params['lockdown']['log_id'] = $this->save_email_log( $data );
} else {
$params['lockdown']['log_id'] = $db['id'];
if ( $db['started'] != $date ) {
$parts = explode( ' ', $db['started'] );
//split the date
$params['start_date']['date'] = $parts[0];
$params['start_date']['time'] = $parts[1];
}
}
$data = $this->set_cookie_data( $params );
unset( $_COOKIE[ $this->cookie_name( $this->campaign_id ) ] );
$this->setCookie( $data['value'], $data['expire'] );
tve_ult_send_evergreen_campaign_start_hook( $this->campaign_id, $params['lockdown']['email'] );
}
/**
* Set the cookie for he end of the campaign
*/
public function set_end_cookie() {
if ( empty( $this->settings['evergreen_repeat'] ) ) {
$expire = strtotime( '2038-01-01 ' );
} else {
$end_after_days = $this->settings['end'] + $this->settings['duration'];
$data = $this->get_cookie_data();
$expire = $this->calc_real_end_time( strtotime( '+' . $end_after_days . ' days', $this->date( $data['cookie']['start_date'] ) ) );
}
if ( ! headers_sent() ) {
setcookie( $this->cookie_end_name(), 'end', $expire, '/' );
/**
* also, unset the "force_campaign" cookie
*/
setcookie( $this->cookie_force_display(), '', time() - DAY_IN_SECONDS * 200, '/' );
}
$_COOKIE[ $this->cookie_end_name( $this->campaign_id ) ] = 'end';
unset( $_COOKIE[ $this->cookie_force_display() ] );
}
/**
* Prepare the cookie data for the setCookie function
*
* @param array $params
*
* @return array
*/
public function set_cookie_data( $params ) {
if ( ! isset( $params['start_date'] ) ) {
// set the start date of the campaign
$use_gmt = $this->use_gmt();
$params['start_date']['date'] = date( 'j F Y', $this->now( true, $use_gmt ) );
$params['start_date']['time'] = date( 'H:i:s', $this->now( false, $use_gmt ) );
}
$lockdown = array(
'email' => is_email( $params['lockdown']['email'] ) ? md5( $params['lockdown']['email'] ) : $params['lockdown']['email'],
'log_id' => $params['lockdown']['log_id'],
);
$params['lockdown'] = $lockdown;
$value = maybe_serialize( $params );
if ( empty( $this->settings['evergreen_repeat'] ) ) {
$expire = strtotime( '2038-01-01 ' );
} else {
$end_after = $this->settings['end'] + $this->settings['duration'];
$expire = $this->calc_real_end_time( strtotime( '+' . $end_after . ' days', $this->date( $params['start_date'] ) ) );
}
return array(
'value' => $value,
'expire' => $expire,
);
}
/**
* Extend the is past to check the past time to also be equal to now
*
* @param string $date
*
* @return bool
*/
public function is_past( $date ) {
return is_string( $date ) && $this->date( $date ) <= $this->now( false, $this->use_gmt() );
}
/**
* Get the duration in seconds set for this campaign. Handles both backwards-compatible cases and new cases
*
* @return int
*/
public function duration_in_seconds() {
if ( ! isset( $this->settings['days_duration'] ) ) {
return $this->settings['duration'] * DAY_IN_SECONDS;
}
return $this->settings['days_duration'] * DAY_IN_SECONDS +
( isset( $this->settings['hours_duration'] ) ? $this->settings['hours_duration'] : 0 ) * HOUR_IN_SECONDS +
( isset( $this->settings['minutes_duration'] ) ? $this->settings['minutes_duration'] : 0 ) * MINUTE_IN_SECONDS +
( isset( $this->settings['seconds_duration'] ) ? $this->settings['seconds_duration'] : 0 );
}
}

View File

@@ -0,0 +1,32 @@
<?php
/**
* Created by PhpStorm.
* User: radu
* Date: 08.02.2016
* Time: 11:02
*/
class TU_Schedule_None extends TU_Schedule_Abstract {
public function applies( $force_apply = false ) {
return false;
}
public function get_end_date() {
return '';
}
public function get_duration() {
return 0;
}
public function should_redirect_pre_access() {
return false;
}
public function should_redirect_expired() {
return false;
}
}

View File

@@ -0,0 +1,743 @@
<?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;
}
}

View File

@@ -0,0 +1,133 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ultimatum
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
/**
* Class TU_Shortcodes
*
* Main wrapper for all shortcodes that are/will be implemented in TU plugin
*/
class TU_Shortcodes {
protected static $campaigns_ids = array();
/**
* Usually called on {init} WP hook
* Ads the required hooks for shortcodes
*/
public static function init() {
$shortcodes = array(
'tu_countdown' => __CLASS__ . '::countdown',
);
foreach ( $shortcodes as $code => $function ) {
add_shortcode( $code, $function );
}
}
/**
* Save the shortcode's campaign in list and
* renders the required placeholder
*
* @param array $args
*
* @return string
*/
public static function countdown( $args ) {
/* this can also be called during a lazy-loading of a thrive leads form. $is_lazy_load is used to check this case */
$is_lazy_load = doing_action( 'wp_ajax_nopriv_tve_dash_front_ajax' ) || doing_action( 'wp_ajax_tve_dash_front_ajax' );
/**
* Usually shortcodes are rendered on single pages or posts,
* but for cases like archive/terms/courses we assign a global post
* Even though WP does not see it as a single a post/page the shortcode should be rendered.
* - E.g.: Course overview post
*
* @param bool $is_tve_exception
*/
$is_tve_exception = apply_filters( 'tve_ult_shortcode_render_exception', false );
/**
* if not post or page do not render shortcode and do not save the campaign globally
* cos we don't want to render the shortcode in lists
*/
if ( ! $is_tve_exception && ! $is_lazy_load && ! is_single() && ! is_page() && ! is_home() ) {
return '';
}
if ( empty( $args['id'] ) || empty( $args['design'] ) ) {
return '';
}
/**
* check if the campaigns is running
*/
$status = get_post_meta( $args['id'], TVE_Ult_Const::META_NAME_FOR_STATUS, true );
if ( $status !== TVE_Ult_Const::CAMPAIGN_STATUS_RUNNING ) {
return '';
}
self::push_campaign( $args['id'] );
require_once trailingslashit( __DIR__ ) . 'shortcodes/class-tu-shortcode-countdown.php';
ob_start();
echo TU_Shortcode_Countdown::instance()->placeholder( $args['design'], $args['id'] );
return ob_get_clean();
}
/**
* Returns the list of campaign ids used by all shortcodes in current request
*
* @return array
*/
public static function get_campaigns() {
return self::$campaigns_ids;
}
/**
* Push an campaign id into global array if it does not exists
*
* @param $id
*
* @return bool pushed or not
*/
protected static function push_campaign( $id ) {
$id = intval( $id );
if ( empty( $id ) || in_array( $id, self::$campaigns_ids ) ) {
return false;
}
self::$campaigns_ids[] = (int) $id;
return true;
}
/**
* Generates code for countdown shortcode
*
* @param int $campaign
* @param int $design
*
* @return string
*/
public static function get_countdown_shortcode( $campaign, $design ) {
if ( empty( $campaign ) || empty( $design ) ) {
return '';
}
require_once trailingslashit( dirname( __FILE__ ) ) . 'shortcodes/class-tu-shortcode-countdown.php';
return TU_Shortcode_Countdown::instance()->get_code( $campaign, $design );
}
}

View File

@@ -0,0 +1,309 @@
<?php
/**
* Handles AJAX calls related to design states
*
* Class TU_State_Manager
*/
class TU_State_Manager extends TU_Request_Handler {
/**
* @var $instance self
*/
protected static $instance = null;
/**
* Row from DB
*
* @var $design array always the main (default) state for a design
*/
protected $design = null;
/**
* TU_State_Manager constructor.
*
* @param $design
*/
private function __construct( $design ) {
$this->design = $design;
}
/**
* Returns the instance of the design
*
* @param $design array the design being edited - this is always the main (default) state for a design
*
* @return self
*/
public static function getInstance( $design ) {
if ( ! empty( self::$instance ) && self::$instance->design['id'] === $design['id'] ) {
return self::$instance;
}
if ( ! empty( $design ) && ! empty( $design['parent_id'] ) ) {
$design = tve_ult_get_design( $design['parent_id'] );
}
return new self( $design );
}
/**
* get the html for the state bar
*
* @param array $current_design the design currently being displayed
*
* @return string
*/
protected function state_bar( $current_design ) {
global $design;
ob_start();
$do_not_wrap = true;
include TVE_Ult_Const::plugin_path() . 'tcb-bridge/editor/states.php';
$state_bar = ob_get_contents();
ob_end_clean();
return $state_bar;
}
/**
* Compose all the data that's required on a page after the content has been changed
* (editor content / CSS links / fonts etc)
*
* @param array $current_design
*
* @return array
*/
public function state_data( $current_design ) {
global $design;
$design = $this->design;
$state_bar = $this->state_bar( $current_design );
$config = tve_ult_editor_get_template_config( $current_design[ TVE_Ult_Const::FIELD_TEMPLATE ] );
/** $css is an array with 2 keys fonts and css which need to be included in the page, if they do not already exist */
$css_links = array();
$enqueued_scripts = tve_ult_enqueue_design_scripts( $current_design );
foreach ( $enqueued_scripts ['fonts'] as $_id => $_font ) {
$css_links[ $_id ] = $_font;
}
foreach ( $enqueued_scripts ['css'] as $_id => $_css ) {
if ( $_id == 'tve_ult_design' ) {
continue;
}
$css_links[ $_id ] = $_css;
}
/** javascript global page data (that will overwrite parts of the global tve_path_params variable) */
$javascript_data = array(
'custom_post_data' => array(
TVE_Ult_Const::DESIGN_QUERY_KEY_NAME => $current_design['id'],
'design_id' => $current_design['id'],
),
'tve_globals' => isset( $design[ TVE_Ult_Const::FIELD_GLOBALS ] ) ? $design[ TVE_Ult_Const::FIELD_GLOBALS ] : array( 'e' => 1 ),
);
/** javascript global page data for the TU - editor part */
$editor_js = array(
TVE_Ult_Const::FIELD_GLOBALS => $current_design[ TVE_Ult_Const::FIELD_GLOBALS ],
'design_id' => $current_design['id'],
'current_css' => empty( $config['css'] ) ? '' : ( 'tve-ult-' . TU_Template_Manager::type( $current_design[ TVE_Ult_Const::FIELD_TEMPLATE ] ) . '-' . str_replace( '.css', '', $config['css'] ) ),
);
/**
* remember the latest edited for this design so that the next time the user will open the parent design
* we can show him directly this child
*/
update_post_meta( $current_design['post_parent'], TVE_Ult_Const::META_PREFIX_NAME_FOR_EDIT_STATE . $this->design['id'], $current_design['id'] );
ob_start();
tve_ult_editor_output_custom_css( $current_design, false );
$custom_css = ob_get_contents();
ob_end_clean();
return array(
'state_bar' => $state_bar,
'main_page_content' => trim( $this->render_ajax_content( $current_design ) ),
'custom_css' => $custom_css,
'css' => $css_links,
'tve_path_params' => $javascript_data,
'tve_ult_page_data' => $editor_js,
);
}
/**
* Renders the html contents for a new design to replace the previously edited one
*
* @param $current_design array
*
* @return string html
*/
public function render_ajax_content( $current_design ) {
global $design;
$design = $current_design;
list( $type, $key ) = TU_Template_Manager::tpl_type_key( $current_design[ TVE_Ult_Const::FIELD_TEMPLATE ] );
if ( $key === 'cloud' ) {
$type = TU_Template_Manager::get_cloud_type( $type );
}
ob_start();
$is_ajax_render = true;
include TVE_Ult_Const::plugin_path() . 'tcb-bridge/editor/campaign/' . $type . '.php';
$html = ob_get_contents();
ob_end_clean();
return $html;
}
/**
* API-calls after this point
* --------------------------------------------------------------------
*/
/**
* Add a new state
*/
public function api_add() {
$child = $this->design;
unset( $child['id'] );
$child[ TVE_Ult_Const::FIELD_USER_CSS ] = '';
$child['parent_id'] = $this->design['id'];
$child['post_title'] = $this->param( 'post_title' );
if ( ! ( $child = tve_ult_save_design( $child ) ) ) {
return array(
'error' => 'Could not save the new design',
);
}
return $this->state_data( $child );
}
/**
* Change the name for a state
*/
public function api_edit_name() {
if ( ! ( $state = tve_ult_get_design( $this->param( 'id' ) ) ) ) {
return array();
}
global $design;
$design = $this->design;
$state['post_title'] = $this->param( 'post_title' );
tve_ult_save_design( $state );
return array(
'state_bar' => $this->state_bar( tve_ult_get_design( $this->param( 'design_id' ) ) ),
);
}
/**
* display a state
*
* @return array
*/
public function api_display() {
if ( ! ( $id = $this->param( 'id' ) ) || ! ( $design = tve_ult_get_design( $id ) ) ) {
return $this->state_data( $this->design );
}
return $this->state_data( $design );
}
/**
* duplicate a state
*/
public function api_duplicate() {
if ( ! ( $id = $this->param( 'id' ) ) ) {
return $this->state_data( $this->design );
}
if ( ! ( $design = tve_ult_get_design( $id ) ) ) {
return array(
'error' => __( 'Design not found', 'thrive-ult' ),
);
}
$child = $design;
if ( empty( $child['parent_id'] ) ) {
/** if the default one gets duplicated, this means adding the new design as a child of the main one */
$child['parent_id'] = $design['id'];
}
unset( $child['id'] );
/**
* the user custom CSS is only saved in the parent state
*/
$child[ TVE_Ult_Const::FIELD_USER_CSS ] = '';
if ( ! ( $child = tve_ult_save_design( $child ) ) ) {
return array(
'error' => __( 'Design could not be saved', 'thrive-ult' ),
);
}
return $this->state_data( $child );
}
/**
* delete a child state
*/
public function api_delete() {
if ( ! ( $id = $this->param( 'id' ) ) ) {
return $this->state_data( $this->design );
}
$active_state = $this->param( 'design_id' );
$all = tve_ult_get_child_states( $this->design['id'] );
$to_display = $this->design;
$previous = $this->design;
/**
* handle designs like this, because we'll display the previous one if the user deletes the currently active state
*/
foreach ( $all as $v ) {
if ( $active_state == $v['id'] ) {
$active_state = $v;
}
/**
* make sure we don't delete the parent / default state for a design
*/
if ( $v['id'] == $id && ! empty( $v['parent_id'] ) ) {
tve_ult_delete_design( $v['id'] );
$to_display = $previous;
}
$previous = $v;
}
if ( ! is_array( $active_state ) ) {
/**
* this means the default state is currently displayed
*/
$to_display = $this->design;
} elseif ( $active_state['id'] != $id ) {
/**
* if we just deleted the active state, we need to display the previous one
*/
$to_display = $active_state;
}
return $this->state_data( $to_display );
}
}

View File

@@ -0,0 +1,527 @@
<?php
class TU_Template_Manager extends TU_Request_Handler {
const OPTION_TPL_META = 'tve_ult_saved_tpl_meta';
const OPTION_TPL_CONTENT = 'tve_ult_saved_tpl';
/**
* map of design types over templates
*
* @var array
*/
protected static $map = array(
TVE_Ult_Const::DESIGN_TYPE_HEADER_BAR => 'ribbon',
TVE_Ult_Const::DESIGN_TYPE_FOOTER_BAR => 'ribbon',
);
/**
* @var $instance TU_Template_Manager
*/
protected static $instance = null;
/**
* Row from DB
*
* @var $design array
*/
protected $design;
/**
* Templates config for design templates
*
* @var array
*/
protected $config = array();
public static $file_name = null;
/**
* TU_Template_Manager constructor.
*
* @param $design
*/
protected function __construct( $design ) {
$this->design = $design;
$this->config();
}
protected function config() {
$this->config = include TVE_Ult_Const::plugin_path() . 'tcb-bridge/editor-templates/_config.php';
}
/**
* header bars and footer bars should have the same templates
*
* @param string $tpl
*
* @return string
*/
public static function type( $tpl ) {
if ( empty( $tpl ) ) {
return '';
}
if ( strpos( $tpl, 'cloud' ) !== false ) {
$type = str_replace( 'cloud_', '', $tpl );
} else {
$parts = explode( '|', $tpl );
$type = $parts[0];
}
return isset( self::$map[ $type ] ) ? self::$map[ $type ] : $type;
}
/**
* get the design key (actual design name) from a template formatted like 'ribbon|one_set'
*
* @param string $tpl
*/
public static function key( $tpl ) {
if ( empty( $tpl ) ) {
return '';
}
list( $type, $key ) = explode( '|', $tpl );
return $key;
}
/**
* Get the proper type for cloud templates
*
* @param $type
*
* @return string
*/
public static function get_cloud_type( $type ) {
if ( strpos( $type, 'ultimatum' ) !== false ) {
if ( strpos( $type, 'widget' ) !== false ) {
$type = 'widget';
} elseif ( strpos( $type, 'shortcode' ) !== false ) {
$type = 'shortcode';
} else {
$type = 'ribbon';
}
}
return $type;
}
/**
* get the type and tpl name from a design template name
*
* @param string $tpl
*
* @return array
*/
public static function tpl_type_key( $tpl ) {
if ( empty( $tpl ) ) {
return array( '', '' );
}
if ( strpos( $tpl, 'cloud' ) !== false ) {
$type = str_replace( 'cloud_', '', $tpl );
$key = 'cloud';
} else {
list( $type, $key ) = explode( '|', $tpl );
}
return array(
isset( self::$map[ $type ] ) ? self::$map[ $type ] : $type,
$key,
);
}
public static function upload_dir( $upload ) {
$sub_dir = '/thrive-ultimatum/thumbnails';
$upload['path'] = $upload['basedir'] . $sub_dir;
$upload['url'] = $upload['baseurl'] . $sub_dir;
$upload['subdir'] = $sub_dir;
return $upload;
}
public static function get_preview_filename() {
return self::$file_name . '.png';
}
/**
* Returns the instance of the design
*
* @param null $design
*
* @return TU_Template_Manager
*/
public static function getInstance( $design = null ) {
if ( ! is_array( $design ) || empty( $design ) ) {
$design = array();
}
if ( ! self::$instance ) {
self::$instance = new self( $design );
}
if ( isset( $design['id'] ) && self::$instance->design['id'] != $design['id'] ) {
self::$instance = new self( $design );
}
return self::$instance;
}
/**
* Returns the design templates set in _config.php for a specific design type
*
* @param $design_type
*
* @return array
*/
public static function get_templates( $design_type = '' ) {
$design_type = self::type( $design_type );
$templates = self::getInstance()->config[ $design_type ];
foreach ( $templates as $tpl => $tpl_data ) {
$templates[ $tpl ]['key'] = $design_type . '|' . $tpl;
$templates[ $tpl ]['thumbnail'] = TVE_Ult_Const::plugin_url( 'tcb-bridge/editor-templates/' . $design_type . '/thumbnails/' . $tpl . '.png' );
}
return $templates;
}
/**
* API entry point for templates
*
* @param $action
*
* @return false|string json
*/
public function api( $action ) {
$method = 'api_' . strtolower( $action );
if ( ! method_exists( $this, $method ) ) {
return false;
}
$result = call_user_func( array( $this, $method ) );
exit( json_encode( $result ) );
}
/**
* exchange data from $template to this->variation or vice-versa
*
* @param array $template
* @param string $dir can either be left-right or right-left
*
* @return array
*/
protected function interchange_data( $template, $dir = 'left -> right' ) {
$fields = array(
TVE_Ult_Const::FIELD_CONTENT,
TVE_Ult_Const::FIELD_INLINE_CSS,
TVE_Ult_Const::FIELD_USER_CSS,
TVE_Ult_Const::FIELD_GLOBALS,
TVE_Ult_Const::FIELD_CUSTOM_FONTS,
TVE_Ult_Const::FIELD_ICON_PACK,
TVE_Ult_Const::FIELD_MASONRY,
TVE_Ult_Const::FIELD_TYPEFOCUS,
);
foreach ( $fields as $field ) {
if ( strpos( $dir, 'left' ) === 0 ) {
$this->design[ $field ] = $template[ $field ];
} else {
$template[ $field ] = $this->design[ $field ];
}
}
return $template;
}
public function api_get_saved_tpl() {
$id = $this->param( 'tpl_id', '' );
$data = array();
if ( ! empty( $id ) ) {
$contents = get_option( self::OPTION_TPL_CONTENT );
$data = $contents[ array_search( $id, array_column( $contents, 'id' ) ) ];
}
return $data;
}
/**
* --------------------------------------------------------------------
* -------------------- API-calls after this point -------------------- :)
* --------------------------------------------------------------------
*/
/**
* Choose a new template
*/
public function api_choose() {
if ( ! ( $template = $this->param( 'tpl' ) ) ) {
return false;
}
if ( strpos( $template, 'user-saved-template-' ) === 0 ) {
/* at this point, the template is one of the previously saved templates (saved by the user) -
it holds the index from the option array which needs to be loaded */
$contents = get_option( self::OPTION_TPL_CONTENT );
$meta = get_option( self::OPTION_TPL_META );
$template_index = intval( str_replace( 'user-saved-template-', '', $template ) );
/* make sure we don't mess anything up */
if ( empty( $contents ) || empty( $meta ) || ! isset( $contents[ $template_index ] ) ) {
return '';
}
$tpl_data = $contents[ $template_index ];
$template = $meta[ $template_index ]['tpl'];
$this->interchange_data( $tpl_data, 'left -> right' );
$this->design[ TVE_Ult_Const::FIELD_TEMPLATE ] = $template;
} else {
$this->design[ TVE_Ult_Const::FIELD_TEMPLATE ] = $template;
$this->design[ TVE_Ult_Const::FIELD_CONTENT ] = tve_ult_editor_get_template_content( $this->design, $template );
tve_ult_save_design( $this->design );
}
$parent_design = empty( $this->design['parent_id'] ) ? $this->design : tve_ult_get_design( $this->design['parent_id'] );
return TU_State_Manager::getInstance( $parent_design )->state_data( $this->design );
}
/**
* reset contents for the current template
*/
public function api_reset() {
$this->design[ TVE_Ult_Const::FIELD_CONTENT ] = tve_ult_editor_get_template_content( $this->design );
tve_ult_save_design( $this->design );
return TU_State_Manager::getInstance( $this->design )->state_data( $this->design );
}
/**
* Save the current variation config and content as a template so that it can later be applied to other variation
*/
public function api_save() {
/**
* we keep the template content separately from the template meta data (name and date)
*/
if ( empty( $this->design[ TVE_Ult_Const::FIELD_GLOBALS ] ) ) {
$this->design[ TVE_Ult_Const::FIELD_GLOBALS ] = array( 'e' => 1 );
}
$id = 'tvu-tpl-' . substr( uniqid( '', true ), 0, 7 );
$template_content = $this->interchange_data( array(), 'right -> left' );
$template_content['id'] = $id;
list( $type, $key ) = self::tpl_type_key( $this->design[ TVE_Ult_Const::FIELD_TEMPLATE ] );
$name = $this->param( 'name', '' );
$template_meta = array(
'name' => $name,
'tpl' => $this->design[ TVE_Ult_Const::FIELD_TEMPLATE ],
'type' => $type,
'key' => $key,
'date' => date( 'Y-m-d' ),
'id' => $id,
);
$templates_content = get_option( self::OPTION_TPL_CONTENT, array() );
$templates_meta = get_option( self::OPTION_TPL_META, array() );
/**
* In some instances those return empty strings
*/
if ( empty( $templates_content ) ) {
$templates_content = array();
}
if ( empty( $templates_meta ) ) {
$templates_meta = array();
}
$templates_content [] = $template_content;
$templates_meta [] = $template_meta;
// make sure these are not autoloaded, as it is a potentially huge array
add_option( self::OPTION_TPL_CONTENT, null, '', 'no' );
update_option( self::OPTION_TPL_CONTENT, $templates_content );
update_option( self::OPTION_TPL_META, $templates_meta );
$template_type = tve_ult_get_template_name( $this->design['post_type'] );
return array(
'message' => __( 'Template saved.', 'thrive-ult' ),
'list' => $this->api_get_saved( true ),
'saved_tpls' => TU_Template_Manager::get_saved_templates_data( $template_type ),
);
}
public static function get_saved_templates_data( $type ) {
$tpls = array();
$templates = get_option( self::OPTION_TPL_META );
$templates = empty( $templates ) ? array() : array_reverse( $templates, true ); // order by date DESC
$img = TVE_Ult_Const::plugin_url() . 'tcb-bridge/editor-templates/%s/thumbnails/%s';
foreach ( $templates as $index => $template ) {
if ( strpos( $template['type'], $type ) === false ) {
continue;
}
if ( $template['key'] === 'cloud' ) {
$template['thumb'] = tve_ult_get_design_thumbnail( $template['name'] );
if ( ! empty( $template['thumb'] ) ) {
$template['thumb_size']['w'] = getimagesize( $template['thumb'] )[0];
$template['thumb_size']['h'] = getimagesize( $template['thumb'] )[1];
}
} else {
$template['thumb'] = sprintf( $img, $template['type'], $template['key'] . '.png' );
}
$template['date'] = date( 'd.m.y', strtotime( $template['date'] ));
$tpls[] = $template;
}
return $tpls;
}
/**
* get user-saved templates
*
* @param bool $return whether or not to return the $html or output it and exit
*/
public function api_get_saved( $return = false ) {
$only_current_template = (int) $this->param( 'current_template' );
$html = '';
/**
* prepare for multiple templates applying to the same design type
*/
$types = array( self::type( $this->design['post_type'] ) );
$templates = get_option( self::OPTION_TPL_META );
$templates = empty( $templates ) ? array() : array_reverse( $templates, true ); // order by date DESC
$img = TVE_Ult_Const::plugin_url() . 'tcb-bridge/editor-templates/%s/thumbnails/%s';
foreach ( $templates as $index => $template ) {
/* make sure we only load the same type, e.g. ribbon */
if ( ! in_array( $template['type'], $types ) ) {
continue;
}
if ( ! empty( $only_current_template ) && $this->design[ TVE_Ult_Const::FIELD_TEMPLATE ] != $template[ TVE_Ult_Const::FIELD_TEMPLATE ] ) {
continue;
}
$item = '';
$item .= '<div class="tve-template-item">';
$item .= '<div class="template-wrapper click" data-fn="select_template" data-key="user-saved-template-' . $index . '">';
$item .= '<div class="template-thumbnail" style="background-image: url(' . $img . ')">';
$item .= '<div class="template-thumbnail-overlay">';
$item .= '<div class="tcb-right margin-right-5 tcb-delete-saved-template click" data-fn="delete_confirmation">';
$item .= tcb_icon( 'trash', true );
$item .= '</div>';
$item .= '</div>';
$item .= '</div>';
$item .= '<div class="template-name">' . $template['name'] . '<br>(' . date( 'd.m.y', strtotime( $template['date'] )) . ')</div>';
$item .= '<div class="selected"></div>';
$item .= '</div>';
$item .= '</div>';
$item = sprintf( $item, $template['type'], $template['key'] . '.png' );
$html .= $item;
}
$html = $html ? $html : __( 'No saved templates found', 'thrive-ult' );
if ( $return ) {
return $html;
}
echo $html;
exit();
}
public function api_delete() {
$tpl_index = (int) str_replace( 'user-saved-template-', '', $this->param( 'tpl' ) );
$contents = get_option( self::OPTION_TPL_CONTENT );
$meta = get_option( self::OPTION_TPL_META );
if ( ! isset( $contents[ $tpl_index ] ) || ! isset( $meta[ $tpl_index ] ) ) {
return $this->api_get_saved();
}
array_splice( $contents, $tpl_index, 1 );
array_splice( $meta, $tpl_index, 1 );
update_option( self::OPTION_TPL_CONTENT, array_values( $contents ) );
update_option( self::OPTION_TPL_META, array_values( $meta ) );
return $this->api_get_saved();
}
public function api_save_thumbnail() {
$allowed_extension = array( 'png', 'jpg' );
if ( ! isset( $_FILES['preview_file'] ) || ! in_array( pathinfo( $_FILES['preview_file']['name'], PATHINFO_EXTENSION ), $allowed_extension ) ) {
return array(
'success' => false,
);
}
if ( ! function_exists( 'wp_handle_upload' ) ) {
require_once( ABSPATH . 'wp-admin/includes/file.php' );
}
self::$file_name = sanitize_file_name( $this->param( 'file_name' ) );
add_filter( 'upload_dir', array( __CLASS__, 'upload_dir' ) );
$moved_file = wp_handle_upload( $_FILES['preview_file'], array(
'action' => TVE_Ult_Const::ACTION_TEMPLATE,
'unique_filename_callback' => array( __CLASS__, 'get_preview_filename' ),
) );
remove_filter( 'upload_dir', array( __CLASS__, 'upload_dir' ) );
if ( empty( $moved_file['url'] ) ) {
return array(
'success' => false,
);
}
/**
* resize ribbon previews
*/
$design = tve_ult_get_design( $this->param( 'design_id' ) );
$template_type = tve_ult_get_template_name( $design['post_type'] );
if ( $template_type === 'bar' ) {
$preview = wp_get_image_editor( $moved_file['file'] );
if ( ! is_wp_error( $preview ) ) {
$preview->resize( 600, null );
$preview->save( $moved_file['file'] );
}
$editor = wp_get_image_editor( $moved_file['file'] );
$editor->save( $moved_file['file'] );
}
list( $width, $height ) = getimagesize( $moved_file['file'] );
return array(
'success' => true,
'thumb' => $moved_file['url'],
'thumb_sizes' => array(
'width' => $width,
'height' => $height,
),
);
}
}

View File

@@ -0,0 +1,41 @@
<?php
class TU_Timeline {
/**
* @var WP_Post with few more extra fields added
* @see tve_ult_get_campaign
*/
protected $campaign;
/**
* TU_Timeline constructor.
*
* @param WP_Post $campaign
*/
public function __construct( $campaign ) {
$this->campaign = $campaign;
}
public function prepare_events() {
if ( empty( $this->campaign->settings ) || empty( $this->campaign->type )
|| ! in_array( $this->campaign->type, TVE_Ult_Const::campaign_types() )
) {
return;
}
if ( isset( $this->campaign->timeline[0] ) && $this->campaign->timeline[0]['type'] === TVE_Ult_Const::EVENT_TYPE_START ) {
$this->campaign->timeline[0]['name'] = __( 'Campaign Start', 'thrive-ult' );
}
array_push( $this->campaign->timeline, array(
'name' => __( 'End Campaign', 'thrive-ult' ),
'campaign_id' => $this->campaign->ID,
'days' => 0,
'hours' => 0,
'is_end' => true,
'type' => TVE_Ult_Const::EVENT_TYPE_END,
'label' => '0',
) );
}
}

View File

@@ -0,0 +1,208 @@
<?php
class Thrive_Ult_Display_Settings_Manager {
/** @var int */
protected $campaign_id;
/** @var Thrive_Ult_Campaign_Options */
protected $saved_options;
public function __construct( $campaign_id = null ) {
if ( isset( $campaign_id ) ) {
$this->campaign_id = $campaign_id;
}
}
public function initHangers( $campaign_id ) {
$hangers[] = new Thrive_Ult_Hanger( 'show_options', $campaign_id );
$hangers[] = new Thrive_Ult_Hanger( 'hide_options', $campaign_id );
$tabs = array(
'other_screens' => __( 'Basic Settings', 'thrive-ult' ),
'taxonomy_terms' => __( 'Categories etc.', 'thrive-ult' ),
'posts' => __( 'Posts', 'thrive-ult' ),
'pages' => __( 'Pages', 'thrive-ult' ),
'page_templates' => __( 'Page Templates', 'thrive-ult' ),
'post_types' => __( 'Post Types', 'thrive-ult' ),
'taxonomy_archives' => __( 'Archive Pages', 'thrive-ult' ),
'others' => __( 'Other', 'thrive-ult' ),
);
/**
* @var $hanger Thrive_Ult_Hanger
*/
foreach ( $hangers as $hanger ) {
$hanger->initTabs( $tabs, $this->saved_options );
}
return $hangers;
}
/**
* Call this only once
* Saved options for a campaign are the same for all tabs
*/
protected function load_saved_options() {
$this->saved_options = new Thrive_Ult_Campaign_Options( $this->campaign_id );
$this->saved_options->initOptions();
}
public function get_popup_data() {
$this->load_dependencies();
$this->load_saved_options();
$group = isset( $_GET['campaign_id'] ) ? $_GET['campaign_id'] : $this->campaign_id;
$hangers = $this->initHangers( $group );
//used in file included at the end of this function
$saved_templates = apply_filters( 'thrive_display_options_get_templates', array() );
return array(
'hangers' => $hangers,
'savedTemplates' => $saved_templates,
);
}
public function load_template() {
$this->load_dependencies();
$templates = new Thrive_Ult_Saved_Options();
$template_id = $_REQUEST['template_id'];
if ( strpos( $template_id, 'TU-' ) === 0 ) {
$template_id = str_replace( 'TU-', '', $template_id );
} else {
$template = apply_filters( 'thrive_display_options_get_template', array(), $template_id );
}
$templates->initOptions( isset( $template ) ? false : $template_id, isset( $template ) ? $template : null );
$hangers = array(
new Thrive_Ult_Hanger( 'show_options', $_REQUEST['campaign_id'] ),
new Thrive_Ult_Hanger( 'hide_options', $_REQUEST['campaign_id'] ),
);
$identifiers = array(
'other_screens' => __( 'Basic Settings', 'thrive-ult' ),
'taxonomy_terms' => __( 'Categories etc.', 'thrive-ult' ),
'posts' => __( 'Posts', 'thrive-ult' ),
'pages' => __( 'Pages', 'thrive-ult' ),
'page_templates' => __( 'Page Templates', 'thrive-ult' ),
'post_types' => __( 'Post Types', 'thrive-ult' ),
'taxonomy_archives' => __( 'Archive Pages', 'thrive-ult' ),
'others' => __( 'Other', 'thrive-ult' ),
);
/**
* @var $hanger Thrive_Ult_Hanger
*/
foreach ( $hangers as $hanger ) {
/**
* @var $tab Thrive_Ult_Tab
*/
foreach ( $identifiers as $identifier => $label ) {
$tab = Thrive_Ult_Tab_Factory::build( $identifier );
$tab->setGroup( $_REQUEST['campaign_id'] )
->setIdentifier( $identifier )
->setSavedOptions( new Thrive_Ult_Campaign_Options( $_REQUEST['campaign_id'], $templates->getShowGroupOptions(), $templates->getHideGroupOptions() ) )
->setLabel( $label )
->setHanger( $hanger->identifier )
->initOptions()
->initFilters();
$hanger->tabs[] = $tab;
}
}
wp_send_json( $hangers );
}
public function getSavedTemplates() {
$savedTemplates = new Thrive_Ult_Saved_Options();
$templates = $savedTemplates->getAll();
foreach ( $templates as $template ) {
$template->id = TVE_Dash_Product_LicenseManager::TU_TAG . $template->id;
$template->show_options = $this->processTpl( json_decode( stripcslashes( $template->show_options ), true ) );
$template->hide_options = $this->processTpl( json_decode( stripcslashes( $template->hide_options ), true ) );
}
return $templates;
}
protected function processTpl( $savedOptions ) {
$return = array();
foreach ( $savedOptions['tabs'] as $index => $tab ) {
$options = $this->checkBackwardsComp( $tab['options'] );
$return[] = array(
'options' => $options,
'index' => $index,
);
}
return $return;
}
public function checkBackwardsComp( $options ) {
$return = array();
foreach ( $options as $o ) {
if ( is_array( $o ) ) {
if ( ! empty( $o['isChecked'] ) || ( ! empty( $o['type'] ) && $o['type'] == 'direct_url' ) ) {
$return [] = $o['id'];
}
} else {
$return [] = $o;
}
}
return $return;
}
public function save_options() {
if ( empty( $_POST['options'] ) || empty( $_POST['campaign_id'] ) ) {
return __( 'Empty values', 'thrive-ult' );
}
require_once plugin_dir_path( __FILE__ ) . 'class-thrive-ult-campaign-options.php';
$campaign_id = new Thrive_Ult_Campaign_Options( $_POST['campaign_id'], $_POST['options'][0], $_POST['options'][1] );
return $campaign_id->save();
}
public function save_template() {
if ( empty( $_POST['options'] ) || empty( $_POST['name'] ) ) {
return false;
}
require_once plugin_dir_path( __FILE__ ) . 'class-thrive-ult-saved-options.php';
$template = new Thrive_Ult_Saved_Options( $_POST['name'], $_POST['options'][0], $_POST['options'][1], '' );
return $template->save();
}
/**
* Load all the dependencies that are needed for this manager
*/
public function load_dependencies() {
require_once plugin_dir_path( __FILE__ ) . 'class-thrive-ult-filter.php';
require_once plugin_dir_path( __FILE__ ) . 'class-thrive-ult-action.php';
require_once plugin_dir_path( __FILE__ ) . 'class-thrive-ult-option.php';
require_once plugin_dir_path( __FILE__ ) . 'class-thrive-ult-hanger.php';
require_once plugin_dir_path( __FILE__ ) . 'class-thrive-ult-tab-interface.php';
require_once plugin_dir_path( __FILE__ ) . 'class-thrive-ult-tab.php';
require_once plugin_dir_path( __FILE__ ) . 'class-thrive-ult-tab-factory.php';
require_once plugin_dir_path( __FILE__ ) . 'class-thrive-ult-posts-tab.php';
require_once plugin_dir_path( __FILE__ ) . 'class-thrive-ult-pages-tab.php';
require_once plugin_dir_path( __FILE__ ) . 'class-thrive-ult-page-templates-tab.php';
require_once plugin_dir_path( __FILE__ ) . 'class-thrive-ult-post-types-tab.php';
require_once plugin_dir_path( __FILE__ ) . 'class-thrive-ult-taxonomy-archives-tab.php';
require_once plugin_dir_path( __FILE__ ) . 'class-thrive-ult-taxonomy-terms-tab.php';
require_once plugin_dir_path( __FILE__ ) . 'class-thrive-ult-other-screens-tab.php';
require_once plugin_dir_path( __FILE__ ) . 'class-thrive-ult-direct-urls-tab.php';
require_once plugin_dir_path( __FILE__ ) . 'class-thrive-ult-visitors-status-tab.php';
require_once plugin_dir_path( __FILE__ ) . 'class-thrive-ult-campaign-options.php';
require_once plugin_dir_path( __FILE__ ) . 'class-thrive-ult-saved-options.php';
require_once plugin_dir_path( __FILE__ ) . 'class-thrive-others-tab.php';
}
}

View File

@@ -0,0 +1,102 @@
<?php
/**
* Created by PhpStorm.
* User: radu
* Date: 22.01.2015
* Time: 11:50
*/
class Thrive_Ult_Others_Tab extends Thrive_Ult_Tab {
/** @var Thrive_Ult_Visitors_Status_Tab */
protected $visitor_status;
/** @var Thrive_Ult_Direct_Urls_Tab */
protected $direct_urls;
public function __construct() {
$this->visitor_status = new Thrive_Ult_Visitors_Status_Tab();
$this->direct_urls = new Thrive_Ult_Direct_Urls_Tab();
$this->direct_urls->setExclusions( $this->visitor_status->getItems() );
parent::__construct();
}
/**
* Specific tab has to implement this function which transforms
* items(pages, posts, post types) into Option models
*
* @return array
*/
protected function matchItems() {
$this->visitor_status->matchItems();
$this->direct_urls->matchItems();
$this->options = array_merge(
$this->visitor_status->options,
$this->direct_urls->options
);
return $this;
}
/**
* Has to get the Option from json string based on the $item
*
* @param $item
*
* @return Option
*/
protected function getSavedOption( $item ) {
return new Thrive_Ult_Option();
}
/**
* Read items from the database and initiate them
*
* @return $this
*/
protected function initItems() {
$this->visitor_status->getItems();
$this->direct_urls->getItems();
return $this;
}
public function setHanger( $hanger ) {
$this->hanger = $hanger;
$this->visitor_status->setHanger( $hanger );
$this->direct_urls->setHanger( $hanger );
return $this;
}
/**
* @param string $campaign_id
*
* @return $this
*/
public function setGroup( $campaign_id ) {
$this->campaign_id = $campaign_id;
$this->visitor_status->setGroup( $campaign_id );
$this->direct_urls->setGroup( $campaign_id );
return $this;
}
/**
* set the options individually for the 2 subtabs from here
*
* @param Thrive_Ult_Campaign_Options $savedOptions
*
* @return $this
*/
public function setSavedOptions( Thrive_Ult_Campaign_Options $savedOptions ) {
$this->visitor_status->setSavedOptions( $savedOptions );
$this->direct_urls->setSavedOptions( $savedOptions );
return parent::setSavedOptions( $savedOptions );
}
}

View File

@@ -0,0 +1,75 @@
<?php
/**
* Class Action Model
*/
class Thrive_Ult_Action {
/**
* @var string css class
*/
public $cssClass;
/**
* @var string html element id
*/
public $identifier;
/**
* @var string html text
*/
public $label;
/**
* @param string $cssClass
* @param string $identifier
* @param string $label
*/
public function __construct( $cssClass = '', $identifier = '', $label = '' ) {
$this->cssClass = $cssClass;
$this->identifier = $identifier;
$this->label = $label;
}
/**
* @param mixed $cssClass
*/
public function setCssClass( $cssClass ) {
$this->cssClass = $cssClass;
}
/**
* @return mixed
*/
public function getCssClass() {
return $this->cssClass;
}
/**
* @param mixed $identifier
*/
public function setIdentifier( $identifier ) {
$this->identifier = $identifier;
}
/**
* @return mixed
*/
public function getIdentifier() {
return $this->identifier;
}
/**
* @param mixed $label
*/
public function setLabel( $label ) {
$this->label = $label;
}
/**
* @return mixed
*/
public function getLabel() {
return $this->label;
}
}

View File

@@ -0,0 +1,556 @@
<?php
/**
* Class GroupOptions
* JSON options saved by user in database
* Mapper model over database table
*/
class Thrive_Ult_Campaign_Options {
private $table_name = 'settings_campaign';
private $campaign_id;
private $description;
public $show_options;
public $hide_options;
private $db;
protected $init_done = false;
/**
* Store a cache of saved options per request
*
* @var array
*/
protected static $option_cache = [];
public function __construct( $campaign_id, $show_options = '', $hide_options = '' ) {
/**
* @var $wpdb wpdb
*/
global $wpdb;
$this->db = $wpdb;
$this->table_name = tve_ult_table_name( $this->table_name );
$this->campaign_id = $campaign_id;
$this->show_options = $show_options;
$this->hide_options = $hide_options;
}
protected function _processPreSave( $jsonOptions ) {
$options = @json_decode( stripcslashes( $jsonOptions ), true );
if ( empty( $options ) || empty( $options['tabs'] ) ) {
return json_encode( array( 'identifier' => $jsonOptions['identifier'] ) );
}
$clean_options = array();
foreach ( $options['tabs'] as $index => $tabOptions ) {
$clean_options['tabs'][ $index ]['options'] = $tabOptions;
}
return json_encode( $clean_options );
}
public function save() {
if ( $this->delete() === false ) {
return $this->db->last_error;
}
$this->db->suppress_errors();
$show_options = $this->_processPreSave( $this->show_options );
$hide_options = $this->_processPreSave( $this->hide_options );
return $this->db->insert( $this->table_name, array(
'campaign_id' => $this->campaign_id,
'description' => $this->description,
'show_options' => $show_options,
'hide_options' => $hide_options,
) ) !== false ? true : $this->db->last_error;
}
/**
* Deletes Group
*
* @return false|int Affected rows on success or false on error
*/
public function delete() {
//new code for WP 4.1.2
$result = $this->db->query(
$this->db->prepare( "DELETE FROM `{$this->table_name}` WHERE `campaign_id` = %d", $this->campaign_id )
);
return $result;
}
/**
* Reads settings from db / cache.
* Saves a bunch of sql queries in frontend requests
*
* @param int|string $campaign_id
*
* @return stdClass
*/
public static function get( $campaign_id ) {
$campaign_id = (int) $campaign_id;
if ( ! isset( static::$option_cache[ $campaign_id ] ) ) {
global $wpdb;
$table = tve_ult_table_name( 'settings_campaign' );
$sql = "SELECT * FROM {$table} WHERE `campaign_id` = %d";
static::$option_cache[ $campaign_id ] = $wpdb->get_row( $wpdb->prepare( $sql, $campaign_id ) );
}
return static::$option_cache[ $campaign_id ];
}
/**
* Read options from database
*
* @return $this
*/
public function initOptions() {
if ( ! $this->init_done ) {
$row = static::get( $this->campaign_id );
if ( $row ) {
$this->show_options = $row->show_options;
$this->hide_options = $row->hide_options;
$this->description = $row->description;
}
$this->init_done = true;
}
return $this;
}
/**
* copy options from database to new campaign
*
* @Param int|string $from contains id of campaign to copy options from
*
* @return true|error
*/
public function copyOptions( $from ) {
$from = (int) $from;
$sql = "SELECT * FROM {$this->table_name} WHERE `campaign_id` = '{$from}'";
$row = $this->db->get_row( $sql );
if ( $row ) {
$this->show_options = $row->show_options;
$this->hide_options = $row->hide_options;
$this->description = $row->description;
}
return $this->db->insert( $this->table_name, array(
'campaign_id' => $this->campaign_id,
'description' => $this->description,
'show_options' => $this->show_options,
'hide_options' => $this->hide_options,
) ) !== false ? true : $this->db->last_error;
}
/**
* @return string
*/
public function getShowGroupOptions() {
return $this->show_options;
}
/**
* @return string
*/
public function getHideGroupOptions() {
return $this->hide_options;
}
/**
* @param mixed $description
*/
public function setDescription( $description ) {
$this->description = $description;
return $this;
}
/**
* @return mixed
*/
public function getDescription() {
return $this->description;
}
// get current URL
public function get_current_URL() {
$requested_url = is_ssl() ? 'https://' : 'http://';
$requested_url .= $_SERVER['HTTP_HOST'];
$requested_url .= $_SERVER['REQUEST_URI'];
return $requested_url;
}
/**
* Check if any option is checked
*
* @return bool
*/
public function checkForAnyOptionChecked() {
$this->initOptions();
$showingOptions = @json_decode( stripcslashes( $this->getShowGroupOptions() ) );
if ( empty( $showingOptions ) ) {
return false;
}
$optionsChecked = strpos( $this->getShowGroupOptions(), "true" );
if ( $optionsChecked ) {
return true;
}
foreach ( $showingOptions->tabs as $tab ) {
if ( ! empty( $tab->options ) ) {
foreach ( $tab->options as $opt ) {
if ( ! is_object( $opt ) ) {
return true;
}
}
}
}
if ( empty( $showingOptions->tabs[7] ) ) {
return false;
}
foreach ( $showingOptions->tabs[7]->options as $item ) {
if ( is_object( $item ) ) {
if ( $item->isChecked || $item->type == 'direct_url' ) {
return true;
}
} else {
return true;
}
}
return false;
}
/**
* @return bool
*/
public function displayCampaign() {
$display = true;
/**
* if none of the options is not selected do not sow the campaign
*/
if ( ! $this->checkForAnyOptionChecked() ) {
return false;
}
if ( is_front_page() ) {
/* @var $otherScreensTab OtherScreensTab */
$otherScreensTab = Thrive_Ult_Tab_Factory::build( 'other_screens' );
$otherScreensTab->setSavedOptions( $this );
/* @var $directUrlsTab DirectUrlsTab */
$directUrlsTab = Thrive_Ult_Tab_Factory::build( 'direct_urls' );
$directUrlsTab->setSavedOptions( $this );
/* @var $visitorsStatusTab VisitorsStatusTab */
$visitorsStatusTab = Thrive_Ult_Tab_Factory::build( 'visitors_status' );
$visitorsStatusTab->setSavedOptions( $this );
$visitorsStatus = is_user_logged_in() ? 'logged_in' : 'logged_out';
$inclusion = $otherScreensTab->isScreenAllowed( 'front_page' )
|| $directUrlsTab->isUrlAllowed( $this->get_current_URL() )
|| $visitorsStatusTab->isStatusAllowed( $visitorsStatus );
if ( $inclusion === false ) {
return false;
}
$exclusion = $otherScreensTab->isScreenDenied( 'front_page' )
|| $directUrlsTab->isUrlDenied( $this->get_current_URL() )
|| $visitorsStatusTab->isStatusDenied( $visitorsStatus );
if ( $exclusion === true ) {
$display = false;
}
//endif is_front_page
} else if ( is_home() ) {
/* @var $otherScreensTab OtherScreensTab */
$otherScreensTab = Thrive_Ult_Tab_Factory::build( 'other_screens' );
$otherScreensTab->setSavedOptions( $this );
/* @var $directUrlsTab DirectUrlsTab */
$directUrlsTab = Thrive_Ult_Tab_Factory::build( 'direct_urls' );
$directUrlsTab->setSavedOptions( $this );
/* @var $visitorsStatusTab VisitorsStatusTab */
$visitorsStatusTab = Thrive_Ult_Tab_Factory::build( 'visitors_status' );
$visitorsStatusTab->setSavedOptions( $this );
$visitorsStatus = is_user_logged_in() ? 'logged_in' : 'logged_out';
$inclusion = $otherScreensTab->isScreenAllowed( 'blog_index' )
|| $directUrlsTab->isUrlAllowed( $this->get_current_URL() )
|| $visitorsStatusTab->isStatusAllowed( $visitorsStatus );
if ( $inclusion === false ) {
return false;
}
$exclusion = $otherScreensTab->isScreenDenied( 'blog_index' )
|| $directUrlsTab->isUrlDenied( $this->get_current_URL() )
|| $visitorsStatusTab->isStatusDenied( $visitorsStatus );
if ( $exclusion === true ) {
$display = false;
}
} else if ( is_page() ) {
/* @var $post WP_Post */
global $post;
/**
* Filter current post that is used for the display manager
*
* @param WP_Post $post
*/
$_post = apply_filters( 'tve_display_manager_current_post', $post );
/** @var Thrive_Ult_Other_Screens_Tab $otherScreensTab */
$otherScreensTab = Thrive_Ult_Tab_Factory::build( 'other_screens' );
$otherScreensTab->setSavedOptions( $this );
/* @var $pagesTab PagesTab */
$pagesTab = Thrive_Ult_Tab_Factory::build( 'pages' );
$pagesTab->setSavedOptions( $this );
/* @var $pageTemplatesTab PageTemplatesTab */
$pageTemplatesTab = Thrive_Ult_Tab_Factory::build( 'page_templates' );
$pageTemplatesTab->setSavedOptions( $this );
/* @var $postTypesTab PostTypesTab */
$postTypesTab = Thrive_Ult_Tab_Factory::build( 'post_types' );
$postTypesTab->setSavedOptions( $this );
/* @var $directUrlsTab DirectUrlsTab */
$directUrlsTab = Thrive_Ult_Tab_Factory::build( 'direct_urls' );
$directUrlsTab->setSavedOptions( $this );
/* @var $visitorsStatusTab VisitorsStatusTab */
$visitorsStatusTab = Thrive_Ult_Tab_Factory::build( 'visitors_status' );
$visitorsStatusTab->setSavedOptions( $this );
$visitorsStatus = is_user_logged_in() ? 'logged_in' : 'logged_out';
/* @var $taxonomyTermsTab Thrive_Ult_Taxonomy_Terms_Tab */
$taxonomyTermsTab = Thrive_Ult_Tab_Factory::build( 'taxonomy_terms' );
$taxonomyTermsTab->setSavedOptions( $this );
$inclusion = $otherScreensTab->allTypesAllowed( get_post_type() ) || $pagesTab->isPageAllowed( $_post )
|| $postTypesTab->isTypeAllowed( get_post_type() )
|| $directUrlsTab->isUrlAllowed( $this->get_current_URL() )
|| $pageTemplatesTab->isTemplateAllowed( basename( get_page_template() ) )
|| $visitorsStatusTab->isStatusAllowed( $visitorsStatus )
|| $taxonomyTermsTab->isPostAllowed( $_post );
if ( $inclusion === false ) {
return false;
}
$exclusion = $otherScreensTab->allTypesDenied( get_post_type() ) || $pagesTab->isPageDenied( $_post )
|| $postTypesTab->isDeniedType( get_post_type() )
|| $directUrlsTab->isUrlDenied( $this->get_current_URL() )
|| $pageTemplatesTab->isTemplateDenied( basename( get_page_template() ) )
|| $visitorsStatusTab->isStatusDenied( $visitorsStatus )
|| $taxonomyTermsTab->isPostDenied( $_post );
if ( $exclusion === true ) {
$display = false;
}
//endif is_page
} else if ( is_single() ) {
/* @var $post WP_Post */
global $post;
/** @var Thrive_Ult_Other_Screens_Tab $otherScreensTab */
$otherScreensTab = Thrive_Ult_Tab_Factory::build( 'other_screens' );
$otherScreensTab->setSavedOptions( $this );
/* @var $postsTab PostsTab */
$postsTab = Thrive_Ult_Tab_Factory::build( 'posts' );
$postsTab->setSavedOptions( $this );
/* @var $postTypesTab PostTypesTab */
$postTypesTab = Thrive_Ult_Tab_Factory::build( 'post_types' );
$postTypesTab->setSavedOptions( $this );
/* @var $directUrlsTab DirectUrlsTab */
$directUrlsTab = Thrive_Ult_Tab_Factory::build( 'direct_urls' );
$directUrlsTab->setSavedOptions( $this );
/* @var $visitorsStatusTab VisitorsStatusTab */
$visitorsStatusTab = Thrive_Ult_Tab_Factory::build( 'visitors_status' );
$visitorsStatusTab->setSavedOptions( $this );
$visitorsStatus = is_user_logged_in() ? 'logged_in' : 'logged_out';
/* @var $taxonomyTermsTab Thrive_Ult_Taxonomy_Terms_Tab */
$taxonomyTermsTab = Thrive_Ult_Tab_Factory::build( 'taxonomy_terms' );
$taxonomyTermsTab->setSavedOptions( $this );
$inclusion = $otherScreensTab->allTypesAllowed( get_post_type() ) || $postsTab->isPostAllowed( $post )
|| $postTypesTab->isTypeAllowed( get_post_type() )
|| $directUrlsTab->isUrlAllowed( $this->get_current_URL() )
|| $visitorsStatusTab->isStatusAllowed( $visitorsStatus )
|| $taxonomyTermsTab->isPostAllowed( $post );
if ( $inclusion === false ) {
return false;
}
$exclusion = $otherScreensTab->allTypesDenied( get_post_type() ) || $postsTab->isPostDenied( $post )
|| $postTypesTab->isDeniedType( get_post_type() )
|| $directUrlsTab->isUrlDenied( $this->get_current_URL() )
|| $visitorsStatusTab->isStatusDenied( $visitorsStatus )
|| $taxonomyTermsTab->isPostDenied( $post );
if ( $exclusion === true ) {
$display = false;
}
//endif is_single
} else if ( is_archive() ) {
$taxonomy = get_queried_object();
/* @var $taxonomyArchivesTab TaxonomyArchivesTab */
$taxonomyArchivesTab = Thrive_Ult_Tab_Factory::build( 'taxonomy_archives' );
$taxonomyArchivesTab->setSavedOptions( $this );
/* @var $directUrlsTab DirectUrlsTab */
$directUrlsTab = Thrive_Ult_Tab_Factory::build( 'direct_urls' );
$directUrlsTab->setSavedOptions( $this );
/* @var $visitorsStatusTab VisitorsStatusTab */
$visitorsStatusTab = Thrive_Ult_Tab_Factory::build( 'visitors_status' );
$visitorsStatusTab->setSavedOptions( $this );
$visitorsStatus = is_user_logged_in() ? 'logged_in' : 'logged_out';
$inclusion = $taxonomyArchivesTab->isTaxonomyAllowed( $taxonomy )
|| $directUrlsTab->isUrlAllowed( $this->get_current_URL() )
|| $visitorsStatusTab->isStatusAllowed( $visitorsStatus );
if ( $inclusion === false ) {
return false;
}
$exclusion = $taxonomyArchivesTab->isTaxonomyDenied( $taxonomy )
|| $directUrlsTab->isUrlDenied( $this->get_current_URL() )
|| $visitorsStatusTab->isStatusDenied( $visitorsStatus );
if ( $exclusion === true ) {
$display = false;
}
//endif is_archive
} else if ( is_404() ) {
/* @var $otherScreensTab Thrive_Ult_Other_Screens_Tab */
$otherScreensTab = Thrive_Ult_Tab_Factory::build( 'other_screens' );
$otherScreensTab->setSavedOptions( $this );
/* @var $directUrlsTab DirectUrlsTab */
$directUrlsTab = Thrive_Ult_Tab_Factory::build( 'direct_urls' );
$directUrlsTab->setSavedOptions( $this );
/* @var $visitorsStatusTab VisitorsStatusTab */
$visitorsStatusTab = Thrive_Ult_Tab_Factory::build( 'visitors_status' );
$visitorsStatusTab->setSavedOptions( $this );
$visitorsStatus = is_user_logged_in() ? 'logged_in' : 'logged_out';
$inclusion = $otherScreensTab->isScreenAllowed( '404_error_page' )
|| $directUrlsTab->isUrlAllowed( $this->get_current_URL() )
|| $visitorsStatusTab->isStatusAllowed( $visitorsStatus );
if ( $inclusion === false ) {
return false;
}
$exclusion = $otherScreensTab->isScreenDenied( '404_error_page' )
|| $directUrlsTab->isUrlDenied( $this->get_current_URL() )
|| $visitorsStatusTab->isStatusDenied( $visitorsStatus );
if ( $exclusion === true ) {
$display = false;
}
//endif is_404
} else if ( is_search() ) {
/* @var $otherScreensTab OtherScreensTab */
$otherScreensTab = Thrive_Ult_Tab_Factory::build( 'other_screens' );
$otherScreensTab->setSavedOptions( $this );
/* @var $directUrlsTab DirectUrlsTab */
$directUrlsTab = Thrive_Ult_Tab_Factory::build( 'direct_urls' );
$directUrlsTab->setSavedOptions( $this );
/* @var $visitorsStatusTab VisitorsStatusTab */
$visitorsStatusTab = Thrive_Ult_Tab_Factory::build( 'visitors_status' );
$visitorsStatusTab->setSavedOptions( $this );
$visitorsStatus = is_user_logged_in() ? 'logged_in' : 'logged_out';
$inclusion = $otherScreensTab->isScreenAllowed( 'search_page' )
|| $directUrlsTab->isUrlAllowed( $this->get_current_URL() )
|| $visitorsStatusTab->isStatusAllowed( $visitorsStatus );
if ( $inclusion === false ) {
return false;
}
$exclusion = $otherScreensTab->isScreenDenied( 'search_page' )
|| $directUrlsTab->isUrlDenied( $this->get_current_URL() )
|| $visitorsStatusTab->isStatusDenied( $visitorsStatus );
if ( $exclusion === true ) {
$display = false;
}
//endif is_search
} else {
$current_url = $this->get_current_URL();
/* @var $directUrlsTab Thrive_Ult_Direct_Urls_Tab */
$directUrlsTab = Thrive_Ult_Tab_Factory::build( 'direct_urls' );
$directUrlsTab->setSavedOptions( $this );
$display = $directUrlsTab->isUrlAllowed( $current_url ) && ! $directUrlsTab->isUrlDenied( $current_url );
}
return $display;
}
public function getTabSavedOptions( $tabIndex, $hanger ) {
$options = json_decode( stripcslashes( $this->$hanger ) );
if ( empty( $options ) || empty( $options->tabs[ $tabIndex ] ) || empty( $options->tabs[ $tabIndex ]->options ) ) {
return array();
}
$opts = $options->tabs[ $tabIndex ]->options;
$return = array();
foreach ( $opts as $option ) {
if ( is_object( $option ) ) {
if ( ! $option->isChecked && $option->type != 'direct_url' ) {
continue;
}
$return [] = $option->id;
} else {
$return [] = $option;
}
}
return $return;
}
}

View File

@@ -0,0 +1,151 @@
<?php
/**
* Class DirectUrlsTab
*/
class Thrive_Ult_Direct_Urls_Tab extends Thrive_Ult_Tab implements Thrive_Ult_Tab_Interface {
const OPTION_TYPE = 'direct_url';
protected $exclusions = array();
public function __construct() {
//override the construct just to reset the actions array
}
public function setExclusions( $exclusions ) {
$this->exclusions = $exclusions;
}
protected function matchItems() {
if ( ! $this->getItems() ) {
return array();
}
foreach ( $this->getItems() as $id => $link ) {
$option = new Thrive_Ult_Option();
$option->setLabel( $link );
$option->setId( $id );
$option->setType( self::OPTION_TYPE );
$this->options[] = $option;
}
}
/**
* WordPress doesnt have a list of direct URLs
* and we dont have to match any item with any saved option
*
* @param $item
*
* @return Option|void
*/
protected function getSavedOption( $item ) {
}
/**
* User adds options|links
* Read them from DB and set as items
*
* @return $this
*/
protected function initItems() {
$savedOptions = $this->getSavedOptions()->getTabSavedOptions( 7, $this->hanger );
if ( ! $savedOptions ) {
$this->setItems( array() );
return $this;
}
$items = array();
foreach ( $savedOptions as $option ) {
if ( array_key_exists( $option, $this->exclusions ) ) {
continue;
}
$items[ $option ] = $option;
}
$this->setItems( $items );
return $this;
}
/**
* @param $url string
*
* @return bool
*/
public function displayWidget( $url ) {
$this->hanger = 'show_options';
$display = false;
foreach ( $this->getItems() as $showingUrl ) {
if ( $url === $showingUrl ) {
$display = true;
}
}
if ( $display === true ) {
$this->hanger = 'hide_options';
$this->initItems();
foreach ( $this->getItems() as $hidingUrl ) {
if ( $url === $hidingUrl ) {
$display = false;
}
}
}
return $display;
}
public function isUrlDenied( $url ) {
$denied = false;
$this->hanger = 'hide_options';
$this->initItems();
foreach ( $this->getItems() as $hidingUrl ) {
if ( $this->clearUrl( $url ) === $this->clearUrl( $hidingUrl ) ) {
$denied = true;
}
}
return $denied;
}
public function isUrlAllowed( $url ) {
$allowed = false;
$this->hanger = 'show_options';
$this->initItems();
foreach ( $this->getItems() as $hidingUrl ) {
if ( $this->clearUrl( $url ) === $this->clearUrl( $hidingUrl ) ) {
$allowed = true;
}
}
return $allowed;
}
protected function clearUrl( $url ) {
if ( strpos( $url, 'http://' ) !== false ) {
$url = substr( $url, strlen( 'http://' ) );
}
if ( strpos( $url, 'https://' ) !== false ) {
$url = substr( $url, strlen( 'https://' ) );
}
if ( strpos( $url, 'www.' ) !== false ) {
$url = substr( $url, strlen( 'www.' ) );
}
/**
* this allows urls to have query strings
*/
if ( strpos( $url, '?' ) !== false ) {
$url = explode( '?', $url );
$url = $url[0];
}
return trim( $url, '/ ' );
}
}

View File

@@ -0,0 +1,69 @@
<?php
/**
* Class Filter Model
*/
class Thrive_Ult_Filter {
/**
* @var string css class
*/
public $cssClass;
/**
* @var string html element id attribute
*/
public $identifier;
/**
* @var string html element's text
*/
public $label;
public function __construct( $cssClass = '', $identifier = '', $label = '' ) {
$this->cssClass = $cssClass;
$this->identifier = $identifier;
$this->label = $label;
}
/**
* @param mixed $cssClass
*/
public function setCssClass( $cssClass ) {
$this->cssClass = $cssClass;
}
/**
* @return mixed
*/
public function getCssClass() {
return $this->cssClass;
}
/**
* @param mixed $identifier
*/
public function setIdentifier( $identifier ) {
$this->identifier = $identifier;
}
/**
* @return mixed
*/
public function getIdentifier() {
return $this->identifier;
}
/**
* @param mixed $label
*/
public function setLabel( $label ) {
$this->label = $label;
}
/**
* @return mixed
*/
public function getLabel() {
return $this->label;
}
}

View File

@@ -0,0 +1,33 @@
<?php
class Thrive_Ult_Hanger {
public $identifier;
public $tabs = array();
protected $campaign_id;
public function __construct( $identifier, $campaign_id ) {
$this->identifier = $identifier;
$this->campaign_id = $campaign_id;
}
public function initTabs( array $identifiers, $saved_options = null ) {
$is_instance = $saved_options instanceof Thrive_Ult_Campaign_Options;
foreach ( $identifiers as $identifier => $label ) {
/** @var $tab Thrive_Ult_Tab */
$tab = Thrive_Ult_Tab_Factory::build( $identifier );
if ( $is_instance ) {
$tab->setSavedOptions( $saved_options );
}
$tab->setGroup( $this->campaign_id )
->setIdentifier( $identifier )
->setLabel( $label )
->setHanger( $this->identifier )
->initOptions()
->initFilters();
$this->tabs[] = $tab;
}
}
}

View File

@@ -0,0 +1,75 @@
<?php
/**
* Class Option Model
*/
class Thrive_Ult_Option {
/* These data members are public just for the serialization(json_encode/json_decode) */
public $id;
public $label;
public $isChecked = false;
/**
* Used to filter options by filters
* Used to render a specific template
*
* @var string
*/
public $type = '';
/**
* @param mixed $id
*/
public function setId( $id ) {
$this->id = $id;
}
/**
* @return mixed
*/
public function getId() {
return $this->id;
}
/**
* @param boolean $isChecked
*/
public function setIsChecked( $isChecked ) {
$this->isChecked = $isChecked;
}
/**
* @return boolean
*/
public function getIsChecked() {
return $this->isChecked;
}
/**
* @param mixed $label
*/
public function setLabel( $label ) {
$this->label = $label;
}
/**
* @return mixed
*/
public function getLabel() {
return $this->label;
}
/**
* @param string $type
*/
public function setType( $type ) {
$this->type = $type;
}
/**
* @return string
*/
public function getType() {
return $this->type;
}
}

View File

@@ -0,0 +1,101 @@
<?php
/**
* Class OtherScreensTab
*/
class Thrive_Ult_Other_Screens_Tab extends Thrive_Ult_Tab implements Thrive_Ult_Tab_Interface {
/**
* Predefined screens
*
* @var array
*/
protected $items;
protected function matchItems() {
if ( ! $this->getItems() ) {
return array();
}
$options = $this->getSavedOptions();
$optionArr = $options->getTabSavedOptions( 0, $this->hanger );
foreach ( $this->getItems() as $id => $label ) {
$option = new Thrive_Ult_Option();
$option->setLabel( $label );
$option->setId( $id );
$option->setIsChecked( in_array( $id, $optionArr ) );
$this->options[] = $option;
}
}
/**
* @param string $item
*
* @return Option|Thrive_Ult_Option
*/
protected function getSavedOption( $item ) {
return $this->getSavedOptionForTab( 0, $item );
}
/**
* All the $items are hardcoded in class property
*
* @return $this
*/
protected function initItems() {
$this->items = array(
'front_page' => __( 'Front Page', 'thrive-ult' ),
'all_post' => __( 'All Posts', 'thrive-ult' ),
'all_page' => __( 'All Pages', 'thrive-ult' ),
'blog_index' => __( 'Blog Index', 'thrive-ult' ),
'404_error_page' => __( '404 Error Page', 'thrive-ult' ),
'search_page' => __( 'Search page', 'thrive-ult' ),
);
return $this;
}
/**
* @param $screen string
*
* @return bool
*/
public function displayWidget( $screen ) {
$this->hanger = 'show_options';
$showOption = $this->getSavedOption( $screen );
$display = $showOption->isChecked;
if ( $display === true ) {
$this->hanger = 'hide_options';
$display = ! $this->getSavedOption( $screen )->isChecked;
}
return $display;
}
public function isScreenAllowed( $screen ) {
$this->hanger = 'show_options';
return $this->getSavedOption( $screen )->isChecked;
}
public function isScreenDenied( $screen ) {
$this->hanger = 'hide_options';
return $this->getSavedOption( $screen )->isChecked;
}
public function allTypesAllowed( $post_type = 'post' ) {
$this->hanger = 'show_options';
return $this->getSavedOption( 'all_' . $post_type )->isChecked;
}
public function allTypesDenied( $post_type = 'post' ) {
$this->hanger = 'hide_options';
return $this->getSavedOption( 'all_' . $post_type )->isChecked;
}
}

View File

@@ -0,0 +1,72 @@
<?php
/**
* Class PagesTab
*/
class Thrive_Ult_Page_Templates_Tab extends Thrive_Ult_Tab implements Thrive_Ult_Tab_Interface {
protected function matchItems() {
if ( ! $this->getItems() ) {
return array();
}
$optionArr = $this->getSavedOptions()->getTabSavedOptions( 4, $this->hanger );
foreach ( $this->getItems() as $pageFile => $pageName ) {
$option = new Thrive_Ult_Option();
$option->setLabel( $pageName );
$option->setId( basename( $pageFile ) );
$option->setIsChecked( in_array( basename( $pageFile ), $optionArr ) );
$this->options[] = $option;
}
}
protected function getSavedOption( $item ) {
return $this->getSavedOptionForTab( 4, $item );
}
/**
* @return $this
*/
protected function initItems() {
$templates = wp_get_theme()->get_page_templates();
$templates['page.php'] = __( 'Default', 'thrive-ult' );
$this->setItems( $templates );
return $this;
}
/**
* @param $template string
*
* @return bool
*/
public function displayWidget( $template ) {
$templateLabel = $this->getTemplateLabel( $template );
$this->hanger = 'show_options';
$showOption = $this->getSavedOption( $templateLabel );
$display = $showOption->isChecked;
if ( $display === true ) {
$this->hanger = 'hide_options';
$templateLabel = $this->getTemplateLabel( $template );
$display = ! $this->getSavedOption( $templateLabel )->isChecked;
}
return $display;
}
public function isTemplateDenied( $template ) {
$this->hanger = 'hide_options';
return $this->getSavedOption( $template )->isChecked;
}
public function isTemplateAllowed( $template ) {
$this->hanger = 'show_options';
return $this->getSavedOption( $template )->isChecked;
}
}

View File

@@ -0,0 +1,72 @@
<?php
/**
* Class PagesTab
*/
class Thrive_Ult_Pages_Tab extends Thrive_Ult_Tab implements Thrive_Ult_Tab_Interface {
protected function matchItems() {
if ( ! $this->getItems() ) {
return array();
}
$optionArr = $this->getSavedOptions()->getTabSavedOptions( 3, $this->hanger );
foreach ( $this->getItems() as $page ) {
$option = new Thrive_Ult_Option();
$option->setLabel( $page->post_title );
$option->setId( $page->ID );
$option->setType( 'item_page' );
$option->setIsChecked( in_array( $page->ID, $optionArr ) );
$this->options[] = $option;
}
}
protected function getSavedOption( $item ) {
return $this->getSavedOptionForTab( 3, $item->ID );
}
/**
* @return $this
*/
protected function initItems() {
$this->setItems( get_pages( array(
'sort_column' => 'post_title',
'sort_order' => 'ASC',
'hierarchical' => 0,
) ) );
return $this;
}
/**
* @param $post WP_Post
*
* @return bool
*/
public function displayWidget( WP_Post $post ) {
$this->hanger = 'show_options';
$showOption = $this->getSavedOption( $post );
$display = $showOption->isChecked;
if ( $display === true ) {
$this->hanger = 'hide_options';
$display = ! $this->getSavedOption( $post )->isChecked;
}
return $display;
}
public function isPageDenied( $page ) {
$this->hanger = 'hide_options';
return $this->getSavedOption( $page )->isChecked;
}
public function isPageAllowed( $page ) {
$this->hanger = 'show_options';
return apply_filters( 'tu_is_page_allowed', $this->getSavedOption( $page )->isChecked, $page, $this );
}
}

View File

@@ -0,0 +1,79 @@
<?php
/**
* Class PostTypesTab
*/
class Thrive_Ult_Post_Types_Tab extends Thrive_Ult_Tab implements Thrive_Ult_Tab_Interface {
protected function matchItems() {
if ( ! $this->getItems() ) {
return array();
}
$optionArr = $this->getSavedOptions()->getTabSavedOptions( 5, $this->hanger );
foreach ( $this->getItems() as $key => $item ) {
$option = new Thrive_Ult_Option();
$option->setLabel( $item );
$option->setId( $item );
$option->setIsChecked( in_array( $item, $optionArr ) );
$this->options[] = $option;
}
}
protected function getSavedOption( $item ) {
return $this->getSavedOptionForTab( 5, $item );
}
/**
* @return $this
*/
protected function initItems() {
$post_types = get_post_types( array(
'public' => true,
) );
$blacklist = apply_filters( 'tve_ult_settings_post_types_blacklist', array() );
if ( is_array( $blacklist ) && ! empty( $blacklist ) ) {
foreach ( $blacklist as $item ) {
unset( $post_types[ $item ] );
}
}
$this->setItems( $post_types );
return $this;
}
/**
* @param $type string
*
* @return bool
*/
public function displayWidget( $type ) {
$this->hanger = 'show_options';
$showOption = $this->getSavedOption( $type );
$display = $showOption->isChecked;
if ( $display === true ) {
$this->hanger = 'hide_options';
$display = ! $this->getSavedOption( $type )->isChecked;
}
return $display;
}
public function isDeniedType( $type ) {
$this->hanger = 'hide_options';
return $this->getSavedOption( $type )->isChecked;
}
public function isTypeAllowed( $type ) {
$this->hanger = 'show_options';
return $this->getSavedOption( $type )->isChecked;
}
}

View File

@@ -0,0 +1,91 @@
<?php
/**
* Class PostsTab
*/
class Thrive_Ult_Posts_Tab extends Thrive_Ult_Tab implements Thrive_Ult_Tab_Interface {
protected function matchItems() {
if ( ! $this->getItems() ) {
return array();
}
$optionArr = $this->getSavedOptions()->getTabSavedOptions( 2, $this->hanger );
foreach ( $this->getItems() as $post ) {
$option = new Thrive_Ult_Option();
$option->setLabel( $post->post_title );
$option->setId( $post->ID );
$option->setIsChecked( in_array( $post->ID, $optionArr ) );
$this->options[] = $option;
}
}
/**
* Overwrite this method to set a specific list of actions
*
* @return array of Action
*/
public function getActions() {
return array();
}
/**
* @param $item WP_Post
*
* @return Option
*/
protected function getSavedOption( $item ) {
return $this->getSavedOptionForTab( 2, $item->ID );
}
/**
* @return $this
*/
protected function initItems() {
$items = array();
$options = $this->getSavedOptions()->getTabSavedOptions( 2, $this->hanger );
if ( ! empty( $options ) ) {
$items = get_posts( array(
'posts_per_page' => - 1,
'include' => $options,
) );
}
$this->setItems( $items );
return $this;
}
/**
* @param $post WP_Post
*
* @return bool
*/
public function displayWidget( WP_Post $post ) {
$this->hanger = 'show_options';
$showOption = $this->getSavedOption( $post );
$display = $showOption->isChecked;
if ( $display === true ) {
$this->hanger = 'hide_options';
$display = ! $this->getSavedOption( $post )->isChecked;
}
return $display;
}
public function isPostDenied( $post ) {
$this->hanger = 'hide_options';
return $this->getSavedOption( $post )->isChecked;
}
public function isPostAllowed( $post ) {
$this->hanger = 'show_options';
return $this->getSavedOption( $post )->isChecked;
}
}

View File

@@ -0,0 +1,99 @@
<?php
class Thrive_Ult_Saved_Options {
private $table_name = 'settings_templates';
private $db;
private $name;
private $description;
public $show_options;
public $hide_options;
public function __construct( $name = '', $show_options = '', $hide_options = '', $description = '' ) {
/**
* @var $wpdb wpdb
*/
global $wpdb;
$this->db = $wpdb;
$this->table_name = tve_ult_table_name( $this->table_name );
$this->name = $name;
$this->description = $description;
$this->show_options = $show_options;
$this->hide_options = $hide_options;
}
protected function _processPreSave( $jsonOptions ) {
$options = @json_decode( stripcslashes( $jsonOptions ), true );
if ( empty( $options ) || empty( $options['tabs'] ) ) {
return json_encode( array( 'identifier' => $jsonOptions['identifier'] ) );
}
$clean_options = array();
foreach ( $options['tabs'] as $index => $tabOptions ) {
$clean_options['tabs'][ $index ]['options'] = $tabOptions;
}
return json_encode( $clean_options );
}
public function save() {
$this->delete();
$this->db->suppress_errors();
$show_options = $this->_processPreSave( $this->show_options );
$hide_options = $this->_processPreSave( $this->hide_options );
return $this->db->insert( $this->table_name, array(
'name' => $this->name,
'description' => $this->description,
'show_options' => $show_options,
'hide_options' => $hide_options,
) ) !== false ? true : $this->db->last_error;
}
public function delete() {
$this->db->delete( $this->table_name, array( 'name' => $this->name ) );
}
/**
* Read options from database
*
* @return $this
*/
public function initOptions( $byId = false, $from_data = null ) {
if ( $from_data !== null ) {
$row = $from_data;
} else {
$where = $byId === false ? "name = '{$this->name}'" : "id = {$byId}";
$sql = "SELECT * FROM {$this->table_name} WHERE {$where}";
$row = $this->db->get_row( $sql );
}
if ( $row ) {
$this->show_options = $row->show_options;
$this->hide_options = $row->hide_options;
}
return $this;
}
/**
* @return string
*/
public function getShowGroupOptions() {
return $this->show_options;
}
/**
* @return string
*/
public function getHideGroupOptions() {
return $this->hide_options;
}
public function getAll() {
$sql = "SELECT * FROM {$this->table_name} ORDER BY name";
$results = $this->db->get_results( $sql );
return $results;
}
}

View File

@@ -0,0 +1,18 @@
<?php
/**
* Class Thrive_Ult_Tab_Factory
* Based on $type a specific tab object is returned
*/
class Thrive_Ult_Tab_Factory {
public static function build( $type ) {
$class = "Thrive_Ult_";
$chunks = explode( "_", $type );
foreach ( $chunks as $chunk ) {
$class .= ucfirst( $chunk ) . "_";
}
$class .= "Tab";
return new $class;
}
}

View File

@@ -0,0 +1,9 @@
<?php
/**
* Interface TabInterface
* Any class that implements this interface has to have options to be displayed
*/
interface Thrive_Ult_Tab_Interface {
public function getOptions();
}

View File

@@ -0,0 +1,284 @@
<?php
/**
* Class Tab
* Basic implementation of a tab
*/
abstract class Thrive_Ult_Tab implements Thrive_Ult_Tab_Interface {
/**
* @var array of items from the wordpress database
*/
protected $items = array();
/**
* @var array of Options build based on the items
*/
public $options = array();
/**
* @var array "Select All, Select None, etc"
*/
public $actions = array();
/**
* @var array
*/
public $filters = array();
/**
* @var int campaign post ID identifier
*/
protected $campaign_id;
/**
* @var Thrive_Ult_Campaign_Options saved by user
*/
protected $savedOptions;
/**
* @var string tab identifier
*/
public $identifier;
/**
* @var string tab label
*/
public $label;
/**
* @var string hanger identifier
*/
protected $hanger;
public function __construct() {
$this->actions = $this->getActions();
}
/**
* @return array of Option models
*/
final public function getOptions() {
if ( empty( $this->options ) ) {
$this->matchItems();
}
return $this->options;
}
/**
* Get the items from database once
* If the $items is not initialized initItems is called which is an abstract method
* and has to be implemented for each tab
*
* @return array
*/
protected function getItems() {
if ( empty( $this->items ) ) {
$this->initItems();
}
return $this->items;
}
/**
* Read the options from the database once
* Init GroupOptions with json strings
*
* @return Thrive_Ult_Campaign_Options
*/
protected function getSavedOptions() {
if ( $this->savedOptions ) {
return $this->savedOptions;
}
$campaign_idOptions = new Thrive_Ult_Campaign_Options( $this->getGroup() );
$campaign_idOptions->initOptions();
$this->savedOptions = $campaign_idOptions;
return $campaign_idOptions;
}
public function setSavedOptions( Thrive_Ult_Campaign_Options $savedOptions ) {
$this->savedOptions = $savedOptions;
return $this;
}
/**
* Overwrite this method to set a specific list of actions
*
* @return array of Action
*/
public function getActions() {
return array(
new Thrive_Ult_Action( 'selectAll tvd-btn-flat-primary', '', 'Select All' ),
new Thrive_Ult_Action( 'selectNone tvd-btn-flat-secondary', '', 'Select None' ),
);
}
/**
* Overwrite this method for specific list of filters
*
* @return array empty
*/
public function getFilters() {
return $this->filters;
}
/**
* Set the items outside the box
*
* @param array $items
*
* @return $this
*/
public function setItems( array $items ) {
$this->items = $items;
return $this;
}
/**
* Can be called outside the box
*
* @return $this
*/
public function initFilters() {
$this->filters = $this->getFilters();
return $this;
}
/**
* @param string $campaign_id
*
* @return $this
*/
public function setGroup( $campaign_id ) {
$this->campaign_id = $campaign_id;
return $this;
}
/**
* @return string
*/
public function getGroup() {
return $this->campaign_id;
}
/**
* @param mixed $identifier
*
* @return $this
*/
public function setIdentifier( $identifier ) {
$this->identifier = $identifier;
return $this;
}
/**
* @return string
*/
public function getIdentifier() {
return $this->identifier;
}
/**
* @param string $label
*
* @return $this;
*/
public function setLabel( $label ) {
$this->label = $label;
return $this;
}
/**
* @return string
*/
public function getLabel() {
return $this->label;
}
/**
* @param string $hanger
*
* @return $this
*/
public function setHanger( $hanger ) {
$this->hanger = $hanger;
return $this;
}
/**
* @return string
*/
public function getHanger() {
return $this->hanger;
}
/**
* Callable from outside the box
* Init the items and options in one call
*
* @return $this
*/
public function initOptions() {
$this->initItems();
$this->matchItems();
return $this;
}
protected function getSavedOptionForTab( $tabIndex, $id ) {
$savedOptions = $this->getSavedOptions();
$optionArr = $savedOptions->getTabSavedOptions( $tabIndex, $this->hanger );
$tlOption = new Thrive_Ult_Option();
if ( empty( $optionArr ) ) {
return $tlOption;
}
$hanger = $this->hanger;
$options = json_decode( stripcslashes( $savedOptions->$hanger ) );
if ( ! $options ) {
return new Thrive_Ult_Option();
}
$tlOption->setId( $id );
$tlOption->setLabel( isset( $this->items[ $id ] ) ? $this->items[ $id ] : '' );
$tlOption->setIsChecked( in_array( $id, $optionArr ) );
return $tlOption;
}
/**
* Specific tab has to implement this function which transforms
* items(pages, posts, post types) into Option models
*
* @return void
*/
abstract protected function matchItems();
/**
* Has to get the Option from json string based on the $item
*
* @param $item
*
* @return Option
*/
abstract protected function getSavedOption( $item );
/**
* Read items from the database and initiate them
*
* @return $this
*/
abstract protected function initItems();
}

View File

@@ -0,0 +1,78 @@
<?php
/**
* Class Thrive_Ult_Taxonomy_Archives_Tab
*/
class Thrive_Ult_Taxonomy_Archives_Tab extends Thrive_Ult_Tab implements Thrive_Ult_Tab_Interface {
protected function matchItems() {
if ( ! $this->getItems() ) {
return array();
}
$optionArr = $this->getSavedOptions()->getTabSavedOptions( 6, $this->hanger );
foreach ( $this->getItems() as $id => $taxonomy ) {
$option = new Thrive_Ult_Option();
$option->setLabel( $taxonomy->label );
$option->setId( $id );
$option->setIsChecked( in_array( $id, $optionArr ) );
$this->options[] = $option;
}
}
protected function getSavedOption( $item ) {
return $this->getSavedOptionForTab( 6, $item );
}
/**
* @return $this
*/
protected function initItems() {
$this->setItems( get_taxonomies( array(
'public' => true,
), 'objects' ) );
return $this;
}
/**
* @param $taxonomy
*
* @return bool
*/
public function displayWidget( $taxonomy = null ) {
if ( ! $taxonomy ) {
return false;
}
$this->hanger = 'show_options';
$showOption = $this->getSavedOption( $taxonomy->taxonomy );
$display = $showOption->isChecked;
if ( $display === true ) {
$this->hanger = 'hide_options';
$display = ! $this->getSavedOption( $taxonomy->taxonomy )->isChecked;
}
return $display;
}
public function isTaxonomyAllowed( $taxonomy = null ) {
$this->hanger = 'show_options';
if ( empty( $taxonomy->taxonomy ) ) {
return false;
}
return $this->getSavedOption( $taxonomy->taxonomy )->isChecked;
}
public function isTaxonomyDenied( $taxonomy = null ) {
if ( empty( $taxonomy->taxonomy ) ) {
return false;
}
$this->hanger = 'hide_options';
return $this->getSavedOption( $taxonomy->taxonomy )->isChecked;
}
}

View File

@@ -0,0 +1,168 @@
<?php
/**
* Class TaxonomyTermsTab
*/
class Thrive_Ult_Taxonomy_Terms_Tab extends Thrive_Ult_Tab implements Thrive_Ult_Tab_Interface {
public function __construct() {
}
protected function matchItems() {
if ( ! $this->getItems() ) {
return array();
}
$optionArr = $this->getSavedOptions()->getTabSavedOptions( 1, $this->hanger );
foreach ( $this->getItems() as $key => $term ) {
$option = new Thrive_Ult_Option();
$option->setLabel( $term->name );
$option->setId( $term->term_id );
$option->setType( $term->taxonomy );
$option->setIsChecked( in_array( $term->term_id, $optionArr ) );
$this->options[] = $option;
}
}
protected function getSavedOption( $item ) {
return $this->getSavedOptionForTab( 1, $item->term_id );
}
/**
* @return $this
*/
protected function initItems() {
$taxonomies = get_taxonomies( array( 'public' => true ) );
/* exclude taxonomies that can be "too many" - a user once had 10.000 tags => breaks the ajax */
$exclude = array( 'post_tag' );
$tag_found = false;
foreach ( $taxonomies as $i => $t ) {
if ( in_array( $t, $exclude ) !== false ) {
if ( empty( $tag_found ) ) {
$tag_found = $t;
}
unset( $taxonomies[ $i ] );
}
}
$this->setItems( get_terms( $taxonomies ) );
/**
* include the post_tag taxonomy
*/
$options = $this->getSavedOptions()->getTabSavedOptions( 1, $this->hanger );
if ( isset( $tag_found ) && ! empty( $options ) ) {
$this->items = array_merge( $this->items, get_terms( $tag_found, array(
'include' => $options,
) ) );
}
return $this;
}
/**
* For this case the filters are the taxonomies
*
* @return array of Filter elements
*/
public function getFilters() {
if ( ! empty( $this->filters ) ) {
return $this->filters;
}
$filters = array();
foreach ( get_taxonomies( array( 'public' => true ), 'objects' ) as $taxonomy ) {
$filters[] = new Thrive_Ult_Filter( 'taxonomyFilter', $taxonomy->name, $taxonomy->label );
}
return $filters;
}
/**
* @param $taxonomyName
*
* @return bool|object
*/
public function getTaxonomy( $taxonomyName ) {
return get_taxonomy( $taxonomyName );
}
/**
* @param $taxonomy
*
* @return bool
*/
public function displayWidget( $taxonomy = null ) {
if ( ! $taxonomy ) {
return false;
}
$this->hanger = 'show_options';
$showOption = $this->getSavedOption( $taxonomy );
$display = $showOption->isChecked;
if ( $display === true ) {
$this->hanger = 'hide_options';
$display = ! $this->getSavedOption( $taxonomy )->isChecked;
}
return $display;
}
public function isTaxonomyAllowed( $taxonomy = null ) {
$this->hanger = 'show_options';
return $this->getSavedOption( $taxonomy )->isChecked;
}
public function isTaxonomyDenied( $taxonomy = null ) {
$this->hanger = 'hide_options';
return $this->getSavedOption( $taxonomy )->isChecked;
}
public function isPostAllowed( $post ) {
//get all taxonomy terms for all taxonomies the $post has
$taxonomies = get_taxonomies( array( 'public' => true ) );
$post_terms = array();
foreach ( $taxonomies as $taxonomy ) {
foreach ( wp_get_post_terms( $post->ID, $taxonomy ) as $term ) {
$post_terms[] = $term;
}
}
//check if any of the posts taxonomy terms is checked
$this->hanger = 'show_options';
foreach ( $post_terms as $post_term ) {
if ( $this->getSavedOption( $post_term )->isChecked ) {
return true;
}
}
return false;
}
public function isPostDenied( $post ) {
//get all taxonomy terms for all taxonomies the $post has
$taxonomies = get_taxonomies( array( 'public' => true ) );
$post_terms = array();
foreach ( $taxonomies as $taxonomy ) {
foreach ( wp_get_post_terms( $post->ID, $taxonomy ) as $term ) {
$post_terms[] = $term;
}
}
//check if any of the posts taxonomy terms is checked
$this->hanger = 'hide_options';
foreach ( $post_terms as $post_term ) {
if ( $this->getSavedOption( $post_term )->isChecked ) {
return true;
}
}
return false;
}
}

View File

@@ -0,0 +1,65 @@
<?php
class Thrive_Ult_Visitors_Status_Tab extends Thrive_Ult_Tab {
protected $items;
/**
* Specific tab has to implement this function which transforms
* items(pages, posts, post types) into Option models
*
* @return void
*/
protected function matchItems() {
if ( ! $this->getItems() ) {
return;
}
$optionArr = $this->getSavedOptions()->getTabSavedOptions( 7, $this->hanger );
foreach ( $this->getItems() as $id => $label ) {
$option = new Thrive_Ult_Option();
$option->setLabel( $label );
$option->setId( $id );
$option->setIsChecked( in_array( $id, $optionArr ) );
$this->options[] = $option;
}
}
/**
* Has to get the Option from json string based on the $item
*
* @param $item
*
* @return Option
*/
protected function getSavedOption( $item ) {
return $this->getSavedOptionForTab( 7, $item );
}
/**
* Read items from the database and initiate them
*
* @return $this
*/
protected function initItems() {
$this->items = array(
'logged_in' => __( 'Logged in', 'thrive-ult' ),
'logged_out' => __( 'Logged out', 'thrive-ult' ),
);
return $this;
}
public function isStatusAllowed( $status ) {
$this->hanger = 'show_options';
return $this->getSavedOption( $status )->isChecked;
}
public function isStatusDenied( $status ) {
$this->hanger = 'hide_options';
return $this->getSavedOption( $status )->isChecked;
}
}

View File

@@ -0,0 +1,86 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ultimatum
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
class TU_Shortcode_Countdown {
protected static $instance;
/**
* Protected construct to ensure the singleton pattern
*
* TU_Shortcode_Countdown constructor.
*/
protected function __construct() {
}
/**
* Access to instance
*
* @return TU_Shortcode_Countdown
*/
public static function instance() {
if ( is_null( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Generates the shortcode code
*
* @param $campaign
* @param $design
*
* @return string
*/
public function code( $campaign, $design ) {
return '[tu_countdown id=' . $campaign . ' design=' . $design . '][/tu_countdown]';
}
/**
* Render the placeholder when the shortcode need to be rendered
* This placeholder will pe replaced with corresponding HTML based on campaign settings when
* the main ajax request is made
*
* @param $design_id
* @param $campaign_id
*
* @return string
*/
public function placeholder( $design_id, $campaign_id ) {
$class = "tu-shortcode-$design_id";
$placeholder_style = tve_ultimatum_get_lightspeed_placeholder( $campaign_id, $design_id );
if ( $placeholder_style !== 'display:none' ) {
$class .= ' tve-ult-preload-form';
}
return '<div style="' . $placeholder_style . '" class="' . $class . '"></div>';
}
/**
* Generates countdown shortcode
*
* @param int $campaign
* @param int $design
*
* @return string
*/
public function get_code( $campaign, $design ) {
$campaign = (int) $campaign;
$design = (int) $design;
return '[tu_countdown id=' . $campaign . ' design=' . $design . '][/tu_countdown]';
}
}