/home/arranoyd/magicraft/wp-content/plugins/popover/inc/class-popup-database.php
<?php
/**
* Provides the database level functions for the popups.
*/
class IncPopupDatabase {
// Use `self::db_prefix( IP_TABLE );` to get the full table name.
const IP_TABLE = 'popover_ip_cache';
/**
* Returns the singleton instance of the popup database class.
*
* @since 4.6
*/
static public function instance() {
static $Inst = null;
if ( null === $Inst ) {
$Inst = new IncPopupDatabase();
}
return $Inst;
}
/**
* Checks the database version and migrates to latest version is required.
*
* @since 4.6
*/
static public function check_db() {
// Update the DB if required.
if ( ! IncPopupDatabase::db_is_current() ) {
IncPopupDatabase::db_update();
}
}
/**
* Checks the state of the database and returns true when the DB has a valid
* format for the current plugin version.
*
* @since 4.6
* @return boolean Database state (true = everything okay)
*/
static public function db_is_current() {
$cur_version = self::_get_option( 'popover_installed', 0 );
// When no DB-Values exist yet then don't even show the notice in
// the Network dashboard.
if ( ! $cur_version ) {
IncPopupDatabase::set_flag( 'network_dismiss', true );
}
return $cur_version == PO_BUILD;
}
/**
* Adds the correct DB prefix to the table and returns the full name.
* Takes the setting PO_GLOBAL into account.
*
* @since 4.6
* @param string $table Table name without prefix.
* @return string The prefixed table name.
*/
static public function db_prefix( $table ) {
global $wpdb;
static $Prefixed = array();
// Handle issues where the blog is switched in code (switch_to_blog)
if ( is_multisite() ) {
global $blog_id;
} else {
$blog_id = 0;
}
if ( ! isset( $Prefixed[ $blog_id ] ) ) {
$Prefixed[ $blog_id ] = array();
}
if ( ! isset( $Prefixed[ $blog_id ][ $table ] ) ) {
$Prefixed[$table] = $table;
if ( defined( 'PO_GLOBAL' ) && true == PO_GLOBAL ) {
if ( ! empty( $wpdb->base_prefix ) ) {
$Prefixed[ $blog_id ][ $table ] = $wpdb->base_prefix . $table;
} else {
$Prefixed[ $blog_id ][ $table ] = $wpdb->prefix . $table;
}
} else {
$Prefixed[ $blog_id ][ $table ] = $wpdb->prefix . $table;
}
}
return $Prefixed[ $blog_id ][ $table ];
}
/**
* Setup or migrate the database to current plugin version.
*
* This function uses error suppression on purpose.
*
* @since 4.6
*/
static public function db_update() {
// Required for dbDelta()
require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
global $wpdb;
$charset_collate = '';
if ( ! empty( $wpdb->charset ) ) {
$charset_collate = ' DEFAULT CHARACTER SET ' . $wpdb->charset;
}
if ( ! empty( $wpdb->collate ) ) {
$charset_collate .= ' COLLATE ' . $wpdb->collate;
}
$tbl_popover = self::db_prefix( 'popover' );
$tbl_ip_cache = self::db_prefix( 'popover_ip_cache' );
$count = 0;
if ( $wpdb->get_var( 'SHOW TABLES LIKE "' . $tbl_popover . '" ' ) == $tbl_popover ) {
// Create a column in old table to monitor migration status.
$sql = "CREATE TABLE {$tbl_popover} (
id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
popover_title varchar(250) DEFAULT NULL,
popover_content text,
popover_settings text,
popover_order bigint(20) DEFAULT '0',
popover_active int(11) DEFAULT '0',
migrated tinyint DEFAULT '0',
PRIMARY KEY (id)
) {$charset_collate};";
dbDelta( $sql );
// Migrate to custom post type.
$sql = "
SELECT
id,
popover_title,
popover_content,
popover_settings,
popover_order,
popover_active
FROM {$tbl_popover}
WHERE migrated=0
";
$res = $wpdb->get_results( $sql );
// Name mapping of conditions/rules from build 5 -> 6.
$mapping = array(
'isloggedin' => 'login', 'loggedin' => 'no_login',
'onurl' => 'url', 'notonurl' => 'no_url',
'incountry' => 'country', 'notincountry' => 'no_country',
'advanced_urls' => 'adv_url', 'not-advanced_urls' => 'no_adv_url',
'categories' => 'category', 'not-categories' => 'no_category',
'post_types' => 'posttype', 'not-post_types' => 'no_posttype',
'xprofile_value' => 'xprofile', 'not-xprofile_value' => 'no_xprofile',
'supporter' => 'no_prosite',
'searchengine' => 'searchengine',
'commented' => 'no_comment',
'internal' => 'no_internal',
'referrer' => 'referrer',
'count' => 'count',
'max_width' => 'width',
'wp_roles_rule' => 'role',
'membership_level' => 'membership',
//'on_exit' => 'on_exit',
//'on_click' => 'on_click',
);
// Translate style to new keys
$style_mapping = array(
'Default' => 'old-default',
'Default Fixed' => 'old-fixed',
'Dark Background Fixed' => 'old-fullbackground',
);
// Migrate data from build 5 to build 6!
foreach ( $res as $item ) {
// Confirm the item was not migrated, just to be sure...
// This is one-time code, we don't care for performance here.
$sql = "
SELECT 1 status
FROM {$tbl_popover}
WHERE id=%s AND migrated=0
";
$sql = $wpdb->prepare( $sql, $item->id );
$status = $wpdb->get_var( $sql );
if ( '1' != $status ) { continue; }
$raw = maybe_unserialize( $item->popover_settings );
$checks = explode( ',', @$raw['popover_check']['order'] );
foreach ( $checks as $ind => $key ) {
if ( isset( $mapping[$key] ) ) {
$checks[$ind] = $mapping[$key];
} else {
unset( $checks[$ind] );
}
}
if ( isset( $style_mapping[ @$raw['popover_style'] ] ) ) {
$style = $style_mapping[ @$raw['popover_style'] ];
} else {
$style = @$raw['popover_style'];
}
$colors = array(
'col1' => @$raw['popover_colour']['back'],
'col2' => @$raw['popover_colour']['fore'],
);
$display = 'delay';
if ( isset( $raw['on_exit'] ) ) { $display = 'leave'; }
if ( isset( $raw['on_click'] ) ) { $display = 'click'; }
$custom_colors = false;
if ( 'FFFFFF' != $colors['col1'] ) { $custom_colors = true; }
if ( '000000' != $colors['col2'] ) { $custom_colors = true; }
$custom_size = true;
if ( ! empty( $raw['popover_size']['usejs'] ) ) { $custom_size = false; }
if ( 'no' != @$raw['popover_usejs'] ) { $custom_size = false; }
$data = array(
'name' => $item->popover_title,
'content' => $item->popover_content,
'order' => $item->popover_order,
'active' => (true == $item->popover_active),
'size' => @$raw['popover_size'],
'color' => $colors,
'custom_colors' => $custom_colors,
'custom_size' => $custom_size,
'style' => $style,
'can_hide' => ('no' == @$raw['popoverhideforeverlink']),
'close_hides' => ('no' != @$raw['popover_close_hideforever']),
'hide_expire' => absint( @$raw['popover_hideforever_expiry'] ),
'display' => $display,
'display_data' => array(
'delay' => absint( @$raw['popoverdelay'] ),
'delay_type' => 's',
'click' => @$raw['on_click']['selector'],
'click_multi' => ! empty( $raw['on_click']['selector'] ),
),
'rule' => $checks,
'rule_data' => array(
'count' => @$raw['popover_count'],
'referrer' => @$raw['popover_ereg'],
'exit' => @$raw['on_exit'],
'url' => @$raw['onurl'],
'no_url' => @$raw['notonurl'],
'adv_url' => @$raw['advanced_urls']['urls'],
'no_adv_url' => @$raw['not-advanced_urls']['urls'],
'country' => @$raw['incountry'],
'no_country' => @$raw['notincountry'],
'category' => @$raw['categories'],
'no_category' => @$raw['not-categories'],
'posttype' => @$raw['post_types'],
'no_posttype' => @$raw['not-post_types'],
'xprofile' => @$raw['xprofile_value'],
'no_xprofile' => @$raw['not-xprofile_value'],
'width' => array(
'min' => @$raw['max_width']['width'],
),
)
);
// Save the popup as custom posttype.
$popup = new IncPopupItem( $data );
$popup->save( false );
// Mark Popup as migrated
$sql = "
UPDATE {$tbl_popover}
SET migrated=1
WHERE id=%s
";
$sql = $wpdb->prepare( $sql, $item->id );
$wpdb->query( $sql );
// Advance counter.
$count += 1;
}
}
self::refresh_order();
// Create or update the IP cache table.
$sql = "
CREATE TABLE {$tbl_ip_cache} (
IP varchar(12) NOT NULL DEFAULT '',
country varchar(2) DEFAULT NULL,
cached bigint(20) DEFAULT NULL,
PRIMARY KEY (IP),
KEY cached (cached)
) {$charset_collate};";
dbDelta( $sql );
if ( $count > 0 ) {
lib2()->ui->admin_message(
sprintf(
__(
'<strong>PopUp Pro</strong><br />' .
'Your installation was successfully updated to use the ' .
'latest version of the plugin!<br />' .
'<em>Note: Some PopUp options changed or were replaced. ' .
'You should have a look at your <a href="%s">PopUps</a> ' .
'to see if they still look as intended.</em>', PO_LANG
),
admin_url( 'edit.php?post_type=' . IncPopupItem::POST_TYPE )
)
);
}
// Migrate the Plugin Settings.
$old_settings = IncPopupDatabase::_get_option( 'popover-settings', array() );
$settings = array();
$cur_method = @$old_settings['loadingmethod'];
switch ( $cur_method ) {
case '':
case 'external': $cur_method = 'ajax'; break;
case 'frontloading': $cur_method = 'front'; break;
}
$settings['loadingmethod'] = $cur_method;
// Migrate Add-Ons to new settings.
// Add-Ons were always saved in the local Options-table by old version.
self::before_db();
$addons = get_option( 'popover_activated_addons', array() );
self::after_db();
$rules = array(
'class-popup-rule-browser.php',
'class-popup-rule-geo.php',
'class-popup-rule-popup.php',
'class-popup-rule-referrer.php',
'class-popup-rule-url.php',
'class-popup-rule-user.php',
'class-popup-rule-prosite.php',
);
foreach ( $addons as $addon ) {
switch ( $addon ) {
case 'anonymous_loading.php':
case 'testheadfooter.php':
/* Integrated; no option. */ break;
case 'localgeodatabase.php':
$settings['geo_db'] = true; break;
case 'rules-advanced_url.php':
$rules[] = 'class-popup-rule-advurl.php'; break;
case 'rules-categories.php':
$rules[] = 'class-popup-rule-category.php'; break;
case 'rules-max_width.php':
$rules[] = 'class-popup-rule-width.php'; break;
case 'rules-on_exit.php':
$rules[] = 'class-popup-rule-events.php'; break;
case 'rules-onclick.php':
$rules[] = 'class-popup-rule-events.php'; break;
case 'rules-post_types.php':
$rules[] = 'class-popup-rule-posttype.php'; break;
case 'rules-xprofile_value.php':
$rules[] = 'class-popup-rule-xprofile.php'; break;
case 'rules-membership.php':
$rules[] = 'class-popup-rule-membership.php'; break;
case 'rules-wp_roles.php':
$rules[] = 'class-popup-rule-role.php'; break;
}
}
$settings['rules'] = $rules;
self::set_settings( $settings );
// Save the new DB version to options table.
self::_set_option( 'popover_installed', PO_BUILD );
}
/**
* Returns a popup object.
*
* @since 4.6
* @param int $post_id ID of the PopUp
* @param bool $clear If TRUE then a new object will be fetched from DB and
* not from cache.
* @return IncPopupItem
*/
static public function get( $post_id, $clear = false ) {
$post_id = absint( $post_id );
if ( $clear ) {
$popup = false;
} else {
$popup = wp_cache_get( $post_id, IncPopupItem::POST_TYPE );
}
if ( false === $popup ) {
self::before_db();
$popup = new IncPopupItem( $post_id );
self::after_db();
wp_cache_set( $post_id, $popup, IncPopupItem::POST_TYPE );
}
return $popup;
}
/**
* Returns an array with all IDs of the active popups.
* The IDs are in the correct order (as defined in the admin list)
*
* @since 4.6
* @return array List of active popups.
*/
static public function get_active_ids() {
global $wpdb;
static $List = null;
if ( null === $List ) {
self::before_db();
// Using get_posts() adds support for WPML
$active_posts = get_posts(
array(
'post_type' => IncPopupItem::POST_TYPE,
'suppress_filters' => 0,
'posts_per_page' => -1,
)
);
foreach ( $active_posts as $post ) {
$List[] = $post->ID;
}
self::after_db();
}
return $List;
}
/**
* Returns the next available value for the popup position (order)
*
* @since 4.6
* @return int Next free order position; bottom of the list.
*/
static public function next_order() {
global $wpdb;
self::before_db();
$sql = "
SELECT menu_order
FROM {$wpdb->posts}
WHERE post_type=%s
ORDER BY menu_order DESC
LIMIT 1
";
$sql = $wpdb->prepare(
$sql,
IncPopupItem::POST_TYPE
);
//wp_die( $sql );
$pos = $wpdb->get_var( $sql );
self::after_db();
return absint( $pos ) + 1;
}
/**
* Updates the order of all popups that are not in trash.
*
* @since 4.6
*/
static public function refresh_order() {
global $wpdb;
self::before_db();
// 1. Set all trashed popups to order=999999.
$sql_fix = "
UPDATE {$wpdb->posts}
SET menu_order=999999
WHERE post_type=%s AND post_status=%s
";
$sql = $wpdb->prepare(
$sql_fix,
IncPopupItem::POST_TYPE,
'trash'
);
$wpdb->query( $sql );
// 2. Get all active/inactive popups in correct order.
$sql_get = "
SELECT ID, menu_order
FROM {$wpdb->posts}
WHERE post_type=%s
AND post_status IN (%s, %s)
ORDER BY menu_order
";
$sql = $wpdb->prepare(
$sql_get,
IncPopupItem::POST_TYPE,
'publish',
'draft'
);
$list = $wpdb->get_results( $sql );
// 3. Update the menu order of all active/inactive popups.
$sql_fix = "
UPDATE {$wpdb->posts}
SET menu_order=%d
WHERE post_type=%s AND ID=%d
";
foreach ( $list as $ind => $data ) {
$sql = $wpdb->prepare(
$sql_fix,
($ind + 1),
IncPopupItem::POST_TYPE,
$data->ID
);
$wpdb->query( $sql );
}
self::after_db();
}
/**
* Count active PopUps
*
* @since 4.6
* @param int $id Optional. Don't count this PopUp in the results.
* @return int Number of active PopUps
*/
static public function count_active( $id = '' ) {
global $wpdb;
if ( ! is_scalar( $id ) ) { $id = ''; }
$sql = "
SELECT COUNT(1)
FROM {$wpdb->posts}
WHERE post_type=%s AND post_status=%s AND ID!=%s
";
$sql = $wpdb->prepare( $sql, IncPopupItem::POST_TYPE, 'publish', $id );
$count = $wpdb->get_var( $sql );
return $count;
}
/**
* Deactivate all active PopUps
*
* @since 4.6
*/
static public function deactivate_all() {
global $wpdb;
$sql = "
UPDATE {$wpdb->posts}
SET post_status=%s
WHERE post_type=%s AND post_status=%s
";
$sql = $wpdb->prepare( $sql, 'draft', IncPopupItem::POST_TYPE, 'publish' );
$wpdb->query( $sql );
}
/*==============================*\
==================================
== ==
== SETTINGS ==
== ==
==================================
\*==============================*/
/**
* Returns the list of available loading methods.
*
* @since 4.6.1.1
* @return array Loading methods displayed in the Settings screen.
*/
static public function get_loading_methods() {
static $Loading_methods = null;
if ( null === $Loading_methods ) {
$Loading_methods = array();
$Loading_methods[] = (object) array(
'id' => 'footer',
'label' => __( 'Page Footer', PO_LANG ),
'info' => __(
'Include PopUp as part of your site\'s HTML (no AJAX call).',
PO_LANG
),
);
$Loading_methods[] = (object) array(
'id' => 'ajax',
'label' => __( 'WordPress AJAX', PO_LANG ),
'info' => __(
'Load PopUp separately from the page via a WordPress AJAX call. ' .
'This is the best option if you use caching.',
PO_LANG
),
);
$Loading_methods[] = (object) array(
'id' => 'front',
'label' => __( 'Custom AJAX', PO_LANG ),
'info' => __(
'Load PopUp separately from the page via a custom front-end AJAX call.',
PO_LANG
),
);
/**
* Allow addons to register additional loading methods.
*
* @var array
*/
$Loading_methods = apply_filters(
'popup-settings-loading-method',
$Loading_methods
);
}
return $Loading_methods;
}
/**
* Returns the plugin settings.
*
* @since 4.6
* @return array.
*/
static public function get_settings() {
$defaults = array(
'loadingmethod' => 'ajax',
'geo_lookup' => 'hostip',
'geo_db' => false,
'rules' => array(
'class-popup-rule-browser.php',
'class-popup-rule-geo.php',
'class-popup-rule-popup.php',
'class-popup-rule-referrer.php',
'class-popup-rule-url.php',
'class-popup-rule-user.php',
'class-popup-rule-prosite.php',
)
);
$data = (array) self::_get_option( 'inc_popup-config', array() );
if ( ! is_array( $data ) ) { $data = array(); }
foreach ( $defaults as $key => $def_value ) {
if ( ! isset( $data[$key] ) ) {
$data[$key] = $def_value;
}
}
return $data;
}
/**
* Saves the plugin settings.
*
* @since 4.6
* @param array $value The value to save.
*/
static public function set_settings( $value ) {
self::_set_option( 'inc_popup-config', $value );
}
/**
* Returns the value of a named flag of the current user.
* Table: User-Meta
*
* @since 4.6
* @param string $key
* @return mixed
*/
static public function get_flag( $key ) {
$data = get_user_meta( get_current_user_id(), 'po_data', true );
if ( is_object( $data ) ) { $data = (array) $data; }
if ( ! is_array( $data ) ) { $data = array(); }
return isset( $data[$key] ) ? $data[$key] : '';
}
/**
* Saves a flag for the current user.
* Table: User-Meta
*
* @since 4.6
* @param string $key
* @param mixed $value
*/
static public function set_flag( $key, $value ) {
$data = get_user_meta( get_current_user_id(), 'po_data', true );
if ( is_object( $data ) ) { $data = (array) $data; }
if ( ! is_array( $data ) ) { $data = array(); }
$data[$key] = $value;
update_user_meta( get_current_user_id(), 'po_data', $data );
}
/**
* Internal function to get a option value from correct options table.
* Table: Blog-Options
*
* @since 4.6
*/
static protected function _get_option( $key, $default ) {
$value = $default;
self::before_db();
if ( IncPopup::use_global() ) {
$value = get_site_option( $key, $default );
} else {
$value = get_option( $key, $default );
}
self::after_db();
return $value;
}
/**
* Internal function to save a value to the correct options table.
* Table: Blog-Options
*
* @since 4.6
*/
static protected function _set_option( $key, $value ) {
self::before_db();
if ( IncPopup::use_global() ) {
update_site_option( $key, $value );
} else {
update_option( $key, $value );
}
self::after_db();
}
/**
* Selects the correct database, in case the PO_GLOBAL flag is true.
*
* @since 4.6
*/
static public function before_db() {
if ( IncPopup::use_global() ) {
switch_to_blog( BLOG_ID_CURRENT_SITE );
}
}
/**
* Selects the correct database, in case the PO_GLOBAL flag is true.
*
* @since 4.6
*/
static public function after_db() {
if ( IncPopup::use_global() ) {
restore_current_blog();
}
}
/*==============================*\
==================================
== ==
== IP CACHE ==
== ==
==================================
\*==============================*/
/**
* Returns the country code that is associated with the IP Address from the
* local cache table.
*
* @since 4.6
* @param string $ip The IP Address.
* @return string Associated country code (or empty string).
*/
static public function get_country( $ip ) {
global $wpdb;
$Country = array();
if ( ! isset( $Country[$ip] ) ) {
$ip_table = self::db_prefix( self::IP_TABLE );
$sql = "
SELECT country
FROM {$ip_table}
WHERE IP = %s
";
$sql = $wpdb->prepare( $sql, $ip );
$Country[$ip] = $wpdb->get_var( $sql );
if ( null === $Country[$ip] ) { $Country[$ip] = ''; }
}
return $Country[$ip];
}
/**
* Adds information to the IP-Cache table.
*
* @since 4.6
* @param string $ip The IP Address.
* @param string $country Country code.
*/
static public function add_ip( $ip, $country ) {
global $wpdb;
$ip_table = self::db_prefix( self::IP_TABLE );
// Delete the cached data, if it already exists.
$sql = "
DELETE FROM $ip_table
WHERE IP = %s
";
$sql = $wpdb->prepare( $sql, $ip );
$wpdb->query( $sql );
// Insert the new dataset.
$sql = "
INSERT INTO $ip_table (IP, country, cached)
VALUES (%s, %s, %s)
";
$sql = $wpdb->prepare( $sql, $ip, $country, time() );
$wpdb->query( $sql );
}
/**
* Clears the IP-Country cache
*
* @since 4.6.1.1
*/
static public function clear_ip_cache() {
global $wpdb;
$ip_table = self::db_prefix( self::IP_TABLE );
// Delete the cached data, if it already exists.
$sql = "TRUNCATE TABLE $ip_table";
$wpdb->query( $sql );
}
/**
* Returns a list of available ip-resolution services.
*
* @since 4.6.1.1
* @return array List of available webservices.
*/
static public function get_geo_services() {
static $Geo_service = null;
if ( null === $Geo_service ) {
$Geo_service = array();
$Geo_service['hostip'] = (object) array(
'label' => 'Host IP',
'url' => 'http://api.hostip.info/country.php?ip=%ip%',
'type' => 'text',
);
$Geo_service['telize'] = (object) array(
'label' => 'Telize',
'url' => 'http://www.telize.com/geoip/%ip%',
'type' => 'json',
'field' => 'country_code',
);
$Geo_service['freegeo'] = (object) array(
'label' => 'Free Geo IP',
'url' => 'http://freegeoip.net/json/%ip%',
'type' => 'json',
'field' => 'country_code',
);
/**
* Allow other modules/plugins to register a geo service.
*/
$Geo_service = apply_filters( 'popup-geo-services', $Geo_service );
}
return $Geo_service;
}
}