<?php
// Load dependencies.
require_once PO_INC_DIR . 'class-popup-base.php';
/**
* Defines the popup class for front end pages
*
* @since 4.6
*/
class IncPopup extends IncPopupBase {
/**
* Data added to the page via wp_localize_script()
* @var array
*/
protected $script_data = array();
/**
* Lists all popups that have been enqueued via the footer loading method.
* @var array
*/
protected $enqueued = array();
/**
* Returns the singleton instance of the popup (front end) class.
*
* @since 4.6
*/
static public function instance() {
static $Inst = null;
// In theory the "public" class does not need this, but to avoid
// unexpected problems we initialize only after current user is known...
if ( ! did_action( 'set_current_user' ) ) {
add_action( 'set_current_user', array( __CLASS__, 'instance' ) );
return null;
}
if ( null === $Inst ) {
$Inst = new IncPopup();
}
return $Inst;
}
/**
* Private constructor (singleton)
*
* @since 4.6
*/
protected function __construct() {
parent::__construct();
// Init loading-process of the PopUp.
add_action(
'wp', // "wp", not "init"!
array( $this, 'init_public' )
);
/**
* Experimental hook to dynamically create popups on your site.
* Call the action hook `wdev-popup` with param 1 being the content and
* param 2 is an optional array of popup options.
*
* Note that currently this plays nice with existing popups if FOOTER
* loading method is used, but all other loading methods will interfere
* with this hook and only show either the dynamic or predefined popups.
*
* @since 4.7.1
* @param string $content The popup contents (HTML code allowed).
* @param array $options Optional. List of popup configuration options.
*/
add_action(
'wdev-popup',
array( $this, 'show_popup' ),
10, 2
);
}
/**
* Initialize the public part of the plugin on every front-end page:
* Determine how the popup is loaded.
*
* @since 4.6
*/
public function init_public() {
// Load plugin settings.
$settings = IncPopupDatabase::get_settings();
// Initialize javascript-data.
$this->script_data['ajaxurl'] = '';
$this->script_data['do'] = 'get_data';
$this->script_data['ajax_data'] = array();
// Find the current loading method.
$cur_method = isset( $settings['loadingmethod'] ) ? $settings['loadingmethod'] : 'ajax';
if ( empty( $cur_method ) ) { $cur_method = 'ajax'; }
if ( isset( $_POST['_po_method_'] ) ) { $cur_method = $_POST['_po_method_']; }
/*
* Apply the specific loading method to include the popup on the page.
* Details to the loading methods are documented in the header comment
* of the "load_method_xyz()" functions.
*/
switch ( $cur_method ) {
case 'ajax': // former 'external'
$this->load_method_ajax();
break;
case 'front': // former 'frontloading'
$this->load_method_front();
if ( isset( $_GET['action'] )
&& 'inc_popup' == $_GET['action']
) {
$this->ajax_load_popup();
}
break;
case 'footer':
$this->load_method_footer();
break;
case 'raw': // Set via form field "_po_method_"
$this->load_method_raw();
break;
default:
/**
* Custom loading handler can be processed by an add-on.
*/
do_action( 'popup-init-loading-method', $cur_method, $this );
break;
}
}
/**
* Action handler that allows us to add a popup via WordPress hook.
*
* @since 4.7.1
* @param string $contents The PopUp contents.
* @param array $options PopUp options.
*/
public function show_popup( $contents, $options = array() ) {
$this->script_data['popup'] = lib2()->array->get( $this->script_data['popup'] );
$popup = new IncPopupItem();
$data = lib2()->array->get( $options );
$data['content'] = $contents;
$popup->populate( $data );
$popup->script_data['manual'] = true;
// 1. Add the popup to the global popup-list.
$this->popups[] = $popup;
// 2. Enqueue the popup in the page footer.
$item = $popup->get_script_data( false );
unset( $item['html'] );
unset( $item['styles'] );
$this->script_data['popup'][] = $item;
$this->load_scripts();
$this->enqueue_footer();
}
/**
* Enqueues the PopUp javascripts and data.
*
* @since 4.6
*/
public function load_scripts() {
static $Loaded = false;
if ( ! did_action( 'wp' ) ) {
// We have to make sure that wp is fully initialized:
// Some rules that use filter 'popup-ajax-data' depend on this.
add_action(
'wp',
array( $this, 'load_scripts' )
);
return;
}
if ( ! $Loaded ) {
if ( is_array( $this->script_data ) && ! empty( $this->script_data ) ) {
$popup_data = apply_filters( 'popup-ajax-data', $this->script_data );
lib2()->ui->data( '_popup_data', $popup_data, 'front' );
$popup_data['popup'] = lib2()->array->get( $popup_data['popup'] );
foreach ( $popup_data['popup'] as $item ) {
$this->enqueued[] = $item['html_id'];
}
}
lib2()->ui->add( PO_JS_URL . 'public.min.js', 'front' );
lib2()->ui->add( PO_CSS_URL . 'animate.min.css', 'front' );
} else {
if ( is_array( $this->script_data ) && is_array( $this->script_data['popup'] ) ) {
foreach ( $this->script_data['popup'] as $popup ) {
if ( in_array( $popup['html_id'], $this->enqueued ) ) {
continue;
}
$script = 'window._popup_data.popup.push(' . json_encode( $popup ) . ')';
lib2()->ui->script( $script );
$this->enqueued[] = $popup['html_id'];
}
}
}
$Loaded = true;
}
/*==================================*\
======================================
== ==
== LOAD METHODS ==
== ==
======================================
\*==================================*/
/**
* Load-Method: External
*
* IS AJAX
* IS ADMIN
*
* PopUp data is loaded via a normal WordPress ajax request, directed at
* the admin-ajax.php handler.
*
* @since 4.6
*/
protected function load_method_ajax() {
global $pagenow;
if ( ! in_array( $pagenow, array( 'wp-login.php', 'wp-register.php' ) ) ) {
// Data is loaded via a normal WordPress ajax request.
$this->script_data['ajaxurl'] = admin_url( 'admin-ajax.php' );
$this->script_data['ajax_data']['orig_request_uri'] = $_SERVER['REQUEST_URI'];
$this->load_scripts();
}
}
/**
* Load-Method: Front/Frontloading
*
* NOT AJAX
* NOT ADMIN
*
* PopUp data is loaded in an ajax request. The ajax request is directed
* at the same URL that is currently displayed, but a few URL-parameters are
* added to instruct the plugin to return popup-data instead the the normal
* webpage.
*
* @since 4.6
*/
protected function load_method_front() {
global $pagenow;
if ( ! in_array( $pagenow, array( 'wp-login.php', 'wp-register.php' ) ) ) {
/*
* Data is loaded via the public URL of the page, simply by adding
* some URL parameters.
*/
$this->script_data['ajaxurl'] = '';
$this->script_data['ajax_data']['request_uri'] = $_SERVER['REQUEST_URI'];
$this->load_scripts();
}
}
/**
* Load-Method: Footer
*
* NOT AJAX
* NOT ADMIN
*
* The PopUp styles and html is directly injected into the webpage header
* and footer. The PopUp is ready when the page is loaded. No ajax request
* is made.
*
* @since 4.6
*/
protected function load_method_footer() {
/**
* Set up the rquest information from here.
* These values are used by some rules and need to be set manually here
* In an ajax request they would already be defined by the ajax url.
*/
$_REQUEST['thereferrer'] = isset( $_SERVER['HTTP_REFERER'] ) ? $_SERVER['HTTP_REFERER'] : '';
$_REQUEST['thefrom'] = lib2()->net->current_url();
// Populates $this->popups
$this->select_popup();
if ( empty( $this->popups ) ) { return; }
$data = $this->get_popup_data();
foreach ( $data as $item ) {
if ( ! empty( $item['manual'] ) ) { continue; }
if ( in_array( $item['html_id'], $this->enqueued ) ) { continue; }
unset( $item['html'] );
unset( $item['styles'] );
$this->script_data['popup'][] = $item;
}
$this->load_scripts();
$this->enqueue_footer();
}
/**
* Load-Method: Raw
*
* This is used when a form is submitted inside a PopUp - it means that we
* should only return the contents of the PopUp(s) and not the whole page.
* Set via form field "_po_method_".
*
* @since 4.6.1.2
*/
protected function load_method_raw() {
/**
* Set up the rquest information from here.
* These values are used by some rules and need to be set manually here
* In an ajax request they would already be defined by the ajax url.
*/
$_REQUEST['thereferrer'] = isset( $_SERVER['HTTP_REFERER'] ) ? $_SERVER['HTTP_REFERER'] : '';
$_REQUEST['thefrom'] = lib2()->net->current_url();
// Populates $this->popups
$this->select_popup();
if ( empty( $this->popups ) ) { die(); }
echo '<div>';
$this->show_footer();
echo '</div>';
die();
}
/*======================================*\
==========================================
== ==
== HELPER FUNCTIONS ==
== ==
==========================================
\*======================================*/
/**
* Adds the wp_header/wp_footer actions to the action queue.
*
* @since 4.7.1
*/
protected function enqueue_footer() {
static $Did_Enqueue = false;
if ( $Did_Enqueue ) { return; }
$Did_Enqueue = true;
add_action(
'wp_head',
array( $this, 'show_header')
);
add_action(
'wp_footer',
array( $this, 'show_footer')
);
}
/**
* Used by "load_method_footer" to print the popup CSS styles.
*
* @since 4.6
*/
public function show_header() {
if ( empty( $this->popups ) ) { return; }
$code = '';
$data = $this->get_popup_data();
foreach ( $data as $ind => $item ) {
$code .= $item['styles'];
}
echo '<style type="text/css">' . $code . '</style>';
}
/**
* Used by "load_method_footer" to print the popup HTML code.
*
* @since 4.6
*/
public function show_footer() {
if ( empty( $this->popups ) ) { return; }
$code = '';
$data = $this->get_popup_data();
foreach ( $data as $ind => $item ) {
$code .= $item['html'];
}
echo $code;
}
};