<?php
/*
Plugin Name: Ad Overlay Anything
Plugin URI: http://www.superblogme.com/ad-overlay-anything/
Description: Overlay ads onto videos, images, text, anything!
Version: 1.9.3
Released: February 1st, 2022
Author: Super Blog Me
Author URI: http://www.superblogme.com
License: http://codecanyon.net/licenses/faq
Any attempt to redistribute or resell will be considered a breach of this license.
*/

defined( 'ABSPATH' ) or die( "Oops! This is a WordPress plugin and should not be called directly.\n" );

////////////////////////////////////////////////////////////////////////////////////////////

if(!class_exists('aoa_core'))
{

    class aoa_core
    {
	private $version = "1.9.3";
	private $db_version = "1.0";
	private $AOA_UpdateChecker = null;
	private $debug = false;
	private $whitelist = null;

//----- WORDPRESS functions ---------------------------------------------------------------------
        /**
         * Construct the plugin object
         */
        public function __construct()
        {
            	// register actions
		add_action( 'admin_init', array( $this, 'admin_init' ) );
		add_action( 'admin_menu', array( $this, 'add_menu' ) );
		add_action( 'plugins_loaded', array( $this, 'plugin_init' ) );
		add_action( 'wp_enqueue_scripts', array( $this, 'aoa_styles' ) );
		add_action( 'init', array( $this, 'aoa_cookie' ) );
		add_action( 'admin_enqueue_scripts', array( $this, 'aoa_admin_styles' ) );
		add_filter( 'the_content', array( $this, 'aoa_auto_overlay' ), 99 );
		add_shortcode( 'aoa', array( $this, 'aoa_shortcode' ) );
		add_filter( 'get_post_metadata', array( $this, 'aoa_custom_meta' ), 99, 4 );

        } // END public function __construct

	/**
	 * hook into WP's admin_init action hook
	 */
	public function admin_init()
	{
		add_action( 'mce_external_plugins', array( $this, 'aoa_add_button' ) );
		add_action( 'mce_buttons', array( $this, 'aoa_register_button' ) );
	} 

	public function aoa_cookie()
	{
		$cookie = get_option( 'aoa_cookie_hours', "0" );
		if ( is_numeric( $cookie ) && $cookie > 0 && ! isset( $_COOKIE['aoa'] ) )
		{
			setcookie( 'aoa', '1', time() + (3600 * $cookie) );
		}
	}

	public function aoa_styles() 
	{
		wp_enqueue_style( 'aoa', plugins_url('/css/style.css', __FILE__), array(), $this->version );
		$custom_css = get_option( 'aoa_custom_css' );
		if ( $custom_css )
		{
			wp_add_inline_style( 'aoa', $custom_css );
		}
		wp_enqueue_script( 'aoa', plugins_url('/js/aoa-functions.js', __FILE__), array( 'jquery' ), $this->version );
		$show = (int) get_option( 'aoa_show_ad', 0 );
		if ( $show > 0 )
		{
			wp_localize_script( 'aoa', 'AoaShowAfter', array( 0 => $show ) );
		}
		$repeat = (int) get_option( 'aoa_repeat_ad', 0 );
		if ( $repeat > 0 )
		{
			wp_localize_script( 'aoa', 'AoaRepeatAfter', array( 0 => $repeat ) );
		}
		$delay = (int) get_option( 'aoa_close_delay', 0 );
		if ( $delay > 0 )
		{
			wp_localize_script( 'aoa', 'AoaCloseTimer', array( 0 => ($delay + $show) ) );
		}
		$after = (int) get_option( 'aoa_close_after', 0 );
		if ( $after > 0 )
		{
			wp_localize_script( 'aoa', 'AoaCloseAfter', array( 0 => ($after + $show) ) );
		}
	}

	public function aoa_admin_styles( $hook ) 
	{
		if ( false === strpos( $hook, 'ad_overlay_anything' ) && false === strpos( $hook, 'ad-overlay-anything' ) ) return;
		wp_enqueue_style( 'aoa', plugins_url('/css/admin.css', __FILE__), array(), $this->version );
	}

	/**
	* add a menu
	*/     
	public function add_menu()
	{
		// create top level menu on dashboard sidebar
        	add_menu_page( 
			'AOA: Main Settings',				// page title
			'Ad Overlay Anything',				// menu title
			'manage_options',				// capability required
			'ad_overlay_anything',				// menu id
			array( $this, 'main_settings' ),		// function to call
			'dashicons-images-alt2'				// icon
		);

        	//create submenu items for our top level menu
        	add_submenu_page( 
			'ad_overlay_anything',
			'AOA: Main Settings', 
			'Main Settings', 
			'manage_options', 
			'ad_overlay_anything',
			array( $this, 'main_settings' ) 
		);
        	add_submenu_page( 
			'ad_overlay_anything',
			'AOA: Create Ad', 
			'Create Ad', 
			'manage_options', 
			'aoa_show_ad',
			array( $this, 'overlay_form' ) 
		);
        	add_submenu_page( 
			'ad_overlay_anything',
			'AOA: Show Ads', 
			'Show Ads', 
			'manage_options', 
			'aoa_show_ads',
			array( $this, 'show_ads' ) 
		);
	} 

	/**
	* Add button to MCE
	*/     
	public function aoa_add_button( $plugin_array )
	{
		$js = plugins_url( 'js/aoa-mce.js', __FILE__ );
		$plugin_array['aoa'] = $js;
		return $plugin_array;
	}

	public function aoa_register_button( $buttons )
	{
		array_push( $buttons, 'aoa' );
		return $buttons;
	}

	private function show_message( $str )
	{
		echo "<div id='message' class='updated'><p>" . $str . "</p></div>";
	}

	private function show_error( $str )
	{
		echo "<div id='message' class='error'><p>" . $str . "</p></div>";
	}

//----- MAIN SETTINGS page ---------------------------------------------------------------------

	/**
	* Save all options
	*/     
	public function save_settings()
	{
		$name = trim( stripslashes( (string) $_POST['aoa_envato_name'] ) );
		$name = preg_replace( '/\s+/', '', $name ); // remove all whitespace
		update_option( 'aoa_envato_name', $name );
		$code = trim( stripslashes( (string) $_POST['aoa_envato_code'] ) );
		$code = preg_replace( '/\s+/', '', $code ); // remove all whitespace
		update_option( 'aoa_envato_code', $code );
		update_option( 'aoa_auto_elements', stripslashes( (string) $_POST['aoa_auto_elements'] ) );
		update_option( 'aoa_auto_id', stripslashes( (string) $_POST['aoa_auto_id'] ) );
		update_option( 'aoa_custom_css', stripslashes( (string) $_POST['aoa_custom_css'] ) );
		update_option( 'aoa_cookie_hours', $_POST['aoa_cookie_hours'] );
		update_option( 'aoa_close_delay', (int) $_POST['aoa_close_delay'] );
		update_option( 'aoa_show_ad', (int) $_POST['aoa_show_ad'] );
		update_option( 'aoa_repeat_ad', (int) $_POST['aoa_repeat_ad'] );
		update_option( 'aoa_close_after', (int) $_POST['aoa_close_after'] );
		update_option( 'aoa_random_status', $_POST['aoa_random_status'] );
		update_option( 'aoa_mobile_ads', $_POST['aoa_mobile_ads'] );
		$whitelist = isset( $_POST['aoa_domain_whitelist'] ) ? trim( stripslashes( $_POST['aoa_domain_whitelist'] ) ) : '';
		$whitelist = str_replace( ",", "\n", $whitelist ); // in case user typed commas instead of newlines
		$whitelist = explode( PHP_EOL, $whitelist );
		update_option( 'aoa_domain_whitelist', $whitelist );
		update_option( 'aoa_admin_only', isset( $_POST['aoa_admin_only'] ) ? $_POST['aoa_admin_only'] : 0 );
		update_option( 'aoa_custom_fields', stripslashes( (string) $_POST['aoa_custom_fields'] ) );
	}

	/**
	* Menu Callback
	*/     
	public function main_settings()
	{
		if( ! current_user_can( 'manage_options' ) )
		{
			wp_die(__('You do not have sufficient permissions to access this page.'));
		}
		else if ( isset( $_POST['save_settings'] ) ) 
		{
			$this->save_settings();
			$this->show_message( esc_html__('Settings Saved.', 'ad-overlay-anything') );
		}

		$code = get_option( 'aoa_envato_code' );
		if ( ! empty( $code ) )
		{
			$name = get_option( 'aoa_envato_name' );
			$name = str_replace( '-beta', '', $name );
			$name = str_replace( '-debug', '', $name, $this->debug );
			$msg = aoa_envato_api::verifyPurchase( $code, $name );
			$support = get_option( 'aoa_support', null );
			if ( $this->support_expired( $support ) && ! empty( $msg ) )
			{
				$this->show_error( $msg );
			}
		}


    		// Render the main settings template
		include(sprintf("%s/templates/main_settings.php", dirname(__FILE__)));
	} 

	/**
	* Support expire check - let user know
	*/     
	public function support_expired( $support = null )
	{
		if ( empty( $support ) ) return 1;
		$now = new DateTime();
		try {
			$s = new DateTime( $support );
		} catch ( Exception $e ) {
			echo "<div id='message' class='error'><p>" . $e->getMessage() . "</p></div>";
			return 1;
		}
		if ( $now < $s ) return 0;
		return 1;
	}


//----- AD OVERLAY functions ---------------------------------------------------------------------

	private function get_form_data()
	{
		$args = array(
			'id'		=>      isset( $_POST['aoa_id'] ) ? $_POST['aoa_id'] : 0,
			'name'		=>      isset( $_POST['aoa_nickname'] ) ? trim( stripslashes( $_POST['aoa_nickname'] ) ) : '',
			'status'	=>      is_numeric( $_POST['aoa_status'] ) ? (int)$_POST['aoa_status'] : '1',
			'content'	=>      isset( $_POST['aoa_content'] ) ? trim( stripslashes( $_POST['aoa_content'] ) ) : '',
			'close'		=>      isset( $_POST['aoa_close'] ) ? trim( stripslashes( $_POST['aoa_close'] ) ) : 'Close',
			'percent'	=>      is_numeric( $_POST['aoa_percent'] ) ? (int)$_POST['aoa_percent'] : '100',
			'class'		=>      isset( $_POST['aoa_class'] ) ? trim( stripslashes( $_POST['aoa_class'] ) ) : '',
		);
		if ( $this->debug ) error_log( __FUNCTION__ . ": " . print_r($args,true) );
		return $args;
	}

	public function overlay_form()
	{
		$args = array();
		if( ! current_user_can( 'manage_options' ) )
		{
			wp_die(__('You do not have sufficient permissions to access this page.'));
		}
		else if ( isset( $_POST['save_ad'] ) ) 
		{
			$args = $this->get_form_data();
			if ( $this->debug ) error_log( __FUNCTION__ . ": " . print_r($args,true) );
			if ( empty( $args['id'] ) )
			{
				$this->db_create_ad( $args );
				$args = array();
			}
			else
			{
				$this->db_update_ad( $args );
			}
		}
		else if ( isset( $_GET['editID'] ) )
		{
			$args = $this->db_retrieve_ad( $_GET['editID'] );
		}

    		// Render the overlay form
		include(sprintf("%s/templates/overlay_ad.php", dirname(__FILE__)));
	}

	public function get_value( $args, $field, $default = '' )
	{
		if ( ! isset( $args ) ) return $default;
		if ( isset( $args[$field] ) ) return $args[$field];
		return $default;
	}

	public function show_ads()
	{
		if ( isset( $_GET['delID'] ) )
		{
			$this->db_delete_ad( $_GET['delID'] );
		}
		else if ( isset( $_POST['mass_submit'] ) && ! empty( $_POST['select'] ) ) {
			$function = isset( $_POST['aoa_function'] ) ? $_POST['aoa_function'] : 0;
			if ( $this->debug ) error_log( __FUNCTION__ . ": " . $function );
			foreach ( $_POST['select'] as $id )
			{
				if ( $this->debug) error_log( __FUNCTION__ . ": processing " . $function . " id " . $id );
				if ( $function == 'delete' )
				{
					$this->db_delete_ad( $id );
				}
				else if ( $function == 'active' )
				{
					$args = $this->db_retrieve_ad( $id );
					if ( $args['status'] ) continue;	// already active
					$args['status'] = 1;
					$this->db_update_ad( $args );
				}
				else if ( $function == 'inactive' )
				{
					$args = $this->db_retrieve_ad( $id );
					if ( ! $args['status'] ) continue;	// already inactive
					$args['status'] = 0;
					$this->db_update_ad( $args );
				}
			}
		}
		include(sprintf("%s/templates/show_ads.php", dirname(__FILE__)));
	}

//----- PUC functions ---------------------------------------------------------------------
	/*
	* Initialize the Plugin Update Checker
	* Load the i18n file for translations
	*/
	public function plugin_init()
	{
		// see if we should set debug mode:
		$name = get_option( 'aoa_envato_name' );
		$name = str_replace( '-debug', '', $name, $this->debug );

		// load i18n file
		$plugin_dir = basename( plugin_dir_path( __FILE__ ) ) . '/languages';
		load_plugin_textdomain( 'ad-overlay-anything', false, $plugin_dir );

		// see if new version requires db install/update
		if ( get_option( 'aoa_db_version' ) != $this->db_version )
		{
			$this->db_setup();
			update_option( 'aoa_db_version', $this->db_version );
		}

		// check the PUC if support
		$support = get_option( 'aoa_support', null );
		if ( empty( $support ) ) return;

		$url = "http://www.superblogme.com/wp-update-server/?action=get_metadata&slug=";
		$name = get_option( 'aoa_envato_name' );
		if ( stripos( $name, "-beta" ) !== FALSE ) 
		{
			$url = "http://www.superblogme.com/test-update-server/?action=get_metadata&slug=";
		}
		require_once plugin_dir_path( __FILE__ ) . 'plugin-updates/plugin-update-checker.php';
		$this->AOA_UpdateChecker = Puc_v4_Factory::buildUpdateChecker(
			$url . 'ad-overlay-anything',
			__FILE__,
			'ad-overlay-anything'
		);
		$this->AOA_UpdateChecker->addQueryArgFilter( array( $this, 'PUC_callback' ) );

	}

	/*
	* Add our own arguments onto the PUC
	*/
	public function PUC_callback( $query_args )
	{
		if ( empty( $query_args ) ) $query_args = array();
		$query_args['license'] = get_option( 'aoa_envato_name' );
		$query_args['code'] = get_option( 'aoa_envato_code' );
		return $query_args;
	}


//----- DATABASE functions ---------------------------------------------------------------------
	/*
	 * Will create custom tables or alter the existing tables if needed
	 */
	private function db_setup()
	{
		global $wpdb;
		include_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
		$charset_collate = '';  // Set default charset and collation
		if ( ! empty( $wpdb->charset ) ) {
			$charset_collate = "DEFAULT CHARACTER SET {$wpdb->charset}";
		}
		if ( ! empty( $wpdb->collate ) )  {
			$charset_collate .= " COLLATE {$wpdb->collate}";
		}
		$table_name = $wpdb->prefix . 'aoa';
		// use camelCode for sql variables
		$sql = "CREATE TABLE $table_name (
		id smallint unsigned NOT NULL AUTO_INCREMENT,
		time timestamp DEFAULT CURRENT_TIMESTAMP NOT NULL,
		name VARCHAR(128),
		status tinyint,
		content text,
		close VARCHAR(128),
		percent tinyint,
		class VARCHAR(128),
		UNIQUE KEY id (id )
		) $charset_collate;";

		if ( $this->debug ) error_log( __FUNCTION__ . ": {$sql}" );

		dbDelta( $sql );
	}

	private function db_create_ad( $args )
	{
		global $wpdb;
		$data = array(
			'name'		=> $args['name'],
			'status'	=> $args['status'],
			'content'	=> $args['content'],
			'close'		=> $args['close'],
			'percent'	=> $args['percent'],
			'class'		=> $args['class']
		);
		if ( $this->debug ) error_log( __FUNCTION__ . ": " . print_r($data,true) );
		$result = $wpdb->insert(
			$wpdb->prefix . 'aoa',
			$data,
			array(
				'%s',	// aoa_name
				'%d',	// aoa_status
				'%s',	// aoa_content
				'%s',	// aoa_close
				'%d',	// aoa_percent
				'%s'	// aoa_class
			)
		);
		if ( FALSE === $result )
		{
			$this->show_error( __FUNCTION__ . ": " . $wpdb->print_error() );
			return 0;
		}
		$id = $wpdb->insert_id;
		$this->show_message( sprintf( esc_html__('Ad Overlay #%s Created.', 'ad-overlay-anything' ), $id ) );
		return $id;
	}

	private function db_update_ad( $args )
	{
		global $wpdb;
		if ( empty( $args['id'] ) )
		{
			// this shouldn't happen
			$this->show_error( __FUNCTION__ . ": missing id!" );
			return 0;
		}
		$data = array(
			'name'		=> $args['name'],
			'status'	=> $args['status'],
			'content'	=> $args['content'],
			'close'		=> $args['close'],
			'percent'	=> $args['percent'],
			'class'		=> $args['class']
		);
		if ( $this->debug ) error_log( __FUNCTION__ . ": "  . print_r($data,true) );
		$result = $wpdb->update(
			$wpdb->prefix . 'aoa',
			$data,
			array( 'id'	=> $args['id'] ),
			array(
				'%s',	// aoa_name
				'%d',	// aoa_status
				'%s',	// aoa_content
				'%s',	// aoa_close
				'%d',	// aoa_percent
				'%s'	// aoa_class
			),
			array( '%d' )
		);
		if ( FALSE === $result )
		{
			$this->show_error( __FUNCTION__ . ": " . $wpdb->print_error() );
			return 0;
		}
		$id = $args['id'];
		$this->show_message( sprintf( esc_html__('Ad Overlay #%s Updated.', 'ad-overlay-anything' ), $id ) );
		return $id;
	}

	private function db_delete_ad( $id = 0 )
	{
		global $wpdb;
		if ( $this->debug ) error_log( __FUNCTION__ . ": id "  . $id );
		if ( ! $id ) return 0;  // should never happen
		$result = $wpdb->delete(
			$wpdb->prefix . 'aoa',
			array( 'id'	=> $id ),
			array( '%d' )
		);
		if ( FALSE === $result )
		{
			$this->show_error( __FUNCTION__ . ": " . $wpdb->print_error() );
			return 0;
		}
		$this->show_message( sprintf( esc_html__('Ad Overlay #%s Deleted.', 'ad-overlay-anything' ), $id ) );
		return $id;
	}

        /*
        * Retreive ad(s) from the database
        * id -1 = fetch all (show ads page)
        * id 0 = randomly fetch 1 ad
        * id X = fetch ad X
        * id X,Y,Z = randomly fetch ad X or Y or Z
        */
	private function db_retrieve_ad( $id = -1, $checkstatus = 0 )
	{
		global $wpdb;
		if ( $id === '' ) return array();  // should never happen

		$select = 'SELECT * FROM ' . $wpdb->prefix . 'aoa';
		$where = $order = '';

		// active ads only?
		if ( $checkstatus ) {
			$where .= 'status = 1';
		}

		// get all ads for 'Show Ads' page
		if ( $id < 0 ) { }
		// choose a random ad
		else if ( $id == 0 ) {
			$order .= ' RAND() LIMIT 1';
		}
		// get a specific ad 
		else if ( is_numeric( $id ) ) {
			if ( $where ) $where .= ' AND ';
			$where .= ' id = ' . $id;
		}
		// choose a random ad from amoung a group of ads  e.g.: 1,3,7,8
		else
		{
			$id = preg_replace( '/\s+/', '', $id ); // remove all whitespace
			if ( $where ) $where .= ' AND ';
			$where .= ' id IN (' . $id . ')';
			$order .= ' RAND() LIMIT 1';
		}

		$sql = $select;
		if ( $where ) $sql .= ' WHERE ' . $where;
		if ( $order ) $sql .= ' ORDER BY ' . $order;


		if ( $this->debug ) error_log( __FUNCTION__ . ": " . $sql );
		$results = $wpdb->get_results( $sql );
		if ( $this->debug ) error_log( __FUNCTION__ . ": " . print_r($results,true) );

		if ( ! $results ) 
		{
			error_log( 'Ad Overlay Anything plugin, ' . __FUNCTION__ . " ERROR: id " . $id . " returned no results." );
			return array();
		}

                if ( $id < 0 ) return $results;	// return list of objects for show ads page
                return (array)$results[0];	// return single array object for everything else
	}

//----- SHORTCODE functions ---------------------------------------------------------------------
	/*
	* Parse the AOA shortcode
	*/
	public function aoa_shortcode( $atts, $content = null )
	{
		if ( $this->debug ) echo "<!-- AOA shortcode start -->\n";
		if ( true == get_option( 'aoa_admin_only', false ) && ! current_user_can( 'manage_options' ) ) return do_shortcode( $content );
		if ( $this->debug ) echo "<!-- AOA admin only passed -->\n";

		if ( wp_is_mobile() && get_option( 'aoa_mobile_ads' ) == 'Inactive' ) return do_shortcode( $content );
		if ( $this->debug ) echo "<!-- AOA wp_is_mobile passed -->\n";

		if ( $this->aoa_on_whitelist() ) return do_shortcode( $content );

		if ( $this->debug ) echo "<!-- AOA on_whitelist passed -->\n";

		$support = get_option( 'aoa_support', null );
		if ( empty( $support ) ) {
			echo "<!-- AoA not licensed. -->\n";
			return do_shortcode( $content );
		}

		if ( $this->debug ) echo "<!-- AOA license passed -->\n";

		$atts = shortcode_atts( array (
			'id'		=> '',
			'idcookie'	=> '',
			'status'	=> '1',
			'content'	=> '',
			'close'		=> '',
			'percent'	=> '',
			'class'		=> ''
		), $atts, 'aoa' );

		// is cookie set?
		$cookie = get_option( 'aoa_cookie_hours', "0" );
		if ( is_numeric( $cookie ) && $cookie > 0 && isset( $_COOKIE['aoa'] ) ) 
		{
			if ( empty( $atts['idcookie'] ) ) return do_shortcode( $content );
			$atts['id'] = $atts['idcookie'];
		}

		if ( $this->debug ) echo "<!-- AOA cookie passed -->\n";

		// check for meta field id override
		$post_id = get_the_ID();
		if ( $post_id ) 
		{
			$idcheck = (int) get_post_meta( $post_id, 'aoa_id', true );
			if ( $this->debug && ! empty( $idcheck ) ) error_log( __FUNCTION__ . " meta field 'aoa_id' override: [" . print_r($idcheck,true) . "]" );
			if ( $idcheck < 0 ) return do_shortcode( $content );
			else if ( ! empty( $idcheck ) ) {
				$atts['id'] = $idcheck;
			}
		}

		if ( $this->debug ) echo "<!-- AOA custom meta field aoa_id passed -->\n";

		$atts = apply_filters( 'aoa_shortcode_atts', $atts );

		if ( $this->debug ) error_log( __FUNCTION__ . " atts: " . print_r($atts,true));

		if ( empty( $atts ) ) return do_shortcode( $content );

		if ( $atts['id'] == 0 && get_option( 'aoa_random_status' ) == 'Inactive' ) return do_shortcode( $content );

		if ( $atts['id'] != '' )
		{
			$db = $this->db_retrieve_ad( $atts['id'], $atts['status'] );
		}
		else 
		{
			$db = array();
		}

		if ( $this->debug ) error_log( __FUNCTION__ . " db: " . print_r($db,true));

		if ( empty( $db ) && empty( $atts ) ) return do_shortcode( $content );

		// shortcode params override any db params
		$ad = array(
			'id'		=> isset( $db['id'] ) ? $db['id'] : $atts['id'],
			'content'	=> ! empty( $atts['content'] ) ? $atts['content'] : ( ! empty( $db['content'] ) ? $db['content'] : '' ),
			'close'		=> ! empty( $atts['close'] ) ? $atts['close'] : ( ! empty( $db['close'] ) ? $db['close'] : '' ),
			'percent'	=> ! empty( $atts['percent'] ) ? $atts['percent'] : ( ! empty( $db['percent'] ) ? $db['percent'] : '' ),
			'class'		=> ! empty( $atts['class'] ) ? $atts['class'] : ( ! empty( $db['class'] ) ? $db['class'] : '' )
		);

		$ad = apply_filters( 'aoa_shortcode_ad', $ad );

		if ( $this->debug ) error_log( __FUNCTION__ . " ad: " . print_r($ad,true));

		if ( empty( $ad ) ) return do_shortcode( $content );

		if ( $ad['percent'] && $ad['percent'] < 100 && mt_rand( 1, 100 ) > $ad['percent'] )
		{
			if ( $this->debug ) error_log( __FUNCTION__ . " random num > " . $ad['percent'] );
			return do_shortcode( $content );
		}

		$m = microtime(true);
		$unique = sprintf( "aoa%05x", ($m-floor($m))*1000000 );

		$str = "\n";

		$str .= '<div id="wrap_' . $unique . '" class="aoa_wrap ' . $ad['class'] . '">' . "\n";
		$str .= '  ' . do_shortcode( $content ) . "\n";
		$str .= '    <div id="' . $unique . '" class="aoa_overlay">' . "\n";
		$str .= '        <div class="aoa_content">' . $ad['content'] . '</div>' . "\n";
		$str .= '        <span id="close_' . $unique . '" class="aoa_close">' . $ad['close'] . '</span>' . "\n";
		$str .= '        <a id="close_btn_' . $unique . '" class="aoa_close_btn" onclick="aoaSetVisibility(\'' . $unique . '\', \'none\');">&times;</a>' . "\n";	
		$str .= '    </div>' . "\n";
		$str .= '</div>' . "\n";
		if ( $this->debug ) error_log( __FUNCTION__ . " final ad: " . print_r($str,true));
		return $str;
	}

//----- public HOOK functions ---------------------------------------------------------------------
	/*
	* Insert beginning AOA code directly before the content to overlay
	* id - the id number(s) of the ads to show. 0 means randomly pick one.
	* atts - an array of fields that override those in the database
	*/
	public function aoa_code_begin( $atts = array() )
	{
		$support = get_option( 'aoa_support', null );
		if ( empty( $support ) ) return null;

		$id = $atts['id'];

		if ( $id < 0 ) return;

		$db = $this->db_retrieve_ad( $id, 1 );

		// ad params override any db params
		$ad = array(
			'id'		=> isset( $db['id'] ) ? $db['id'] : $atts['id'],
			'status'	=> ! empty( $atts['status'] ) ? $atts['status'] : $db['status'],
			'content'	=> ! empty( $atts['content'] ) ? $atts['content'] : $db['content'],
			'close'		=> ! empty( $atts['close'] ) ? $atts['close'] : $db['close'],
			'percent'	=> ! empty( $atts['percent'] ) ? $atts['percent'] : $db['percent'],
			'class'		=> ! empty( $atts['class'] ) ? $atts['class'] : $db['class']
		);

		if ( $this->debug ) error_log( __FUNCTION__ . ": " . print_r($ad,true));

		if ( empty( $ad['status'] ) )
		{
			if ( $this->debug ) error_log( __FUNCTION__ . " status inactive...");
			return null;
		}
		if ( $ad['percent'] && $ad['percent'] < 100 && mt_rand( 1, 100 ) > $ad['percent'] )
		{
			if ( $this->debug ) error_log( __FUNCTION__ . " random num > " . $ad['percent'] );
			return null;
		}

		$m = microtime(true);
		$ad['unique'] = $unique = sprintf( "aoa%05x", ($m-floor($m))*1000000 );

		$str = "\n";
		$str .= '<div id="wrap_' . $unique . '" class="aoa_wrap ' . $ad['class'] . '">' . "\n";
		echo $str;

		return $ad;
	}

	/*
	* Insert ending AOA code directly after the content to overlay
	*/
	public function aoa_code_end( $ad = null )
	{
		if ( ! $ad )
		{
			error_log( __FUNCTION__ . ": MUST be called with a matching ad variable!" );
			return;
		}

		if ( $this->debug ) error_log( __FUNCTION__ . ": " . print_r($ad,true));

		$unique = $ad['unique'];

		$str = "\n";
		$str .= '    <div id="' . $unique . '" class="aoa_overlay">' . "\n";
		$str .= '        <div class="aoa_content">' . $ad['content'] . '</div>' . "\n";
		$str .= '        <span class="aoa_close">' . $ad['close'] . '</span>' . "\n";
		$str .= '        <a class="aoa_close_btn" onclick="aoaSetVisibility(\'' . $unique . '\', \'none\');">&times;</a>' . "\n";	
		$str .= '    </div>' . "\n";
		$str .= '</div>' . "\n";
		echo $str;
	}

	/*
	* Don't show ads if referer is on whitelist
	*/
	public function aoa_on_whitelist()
	{
		if ( null == $this->whitelist ) $this->whitelist = get_option( 'aoa_domain_whitelist', array() );
		$ref = wp_get_referer();
		foreach ( $this->whitelist as $wl )
		{
			$wl = trim( $wl );
			if ( empty( $wl ) ) continue; // empty line
			if ( false !== stripos( $ref, $wl ) )
			{
				return 1;
			}
		}
		return 0;
	}

//----- AUTO OVERLAY functions ---------------------------------------------------------------------
	/*
	* Filter the content
	* Check for automatic overlay elements
	*/
	public function aoa_auto_overlay( $content )
	{
		if ( $this->debug ) echo "\n<!-- AOA auto overlay start -->\n";
		if ( true == get_option( 'aoa_admin_only', false ) && ! current_user_can( 'manage_options' ) ) return do_shortcode( $content );
		if ( $this->debug ) echo "<!-- AOA admin check pass -->\n";

		if ( wp_is_mobile() && get_option( 'aoa_mobile_ads' ) == 'Inactive' ) return do_shortcode( $content );
		if ( $this->debug ) echo "<!-- AOA mobile ad check pass -->\n";

		if ( $this->aoa_on_whitelist() ) return do_shortcode( $content );

		if ( $this->debug ) echo "<!-- AOA whitelist pass-->\n";

		$id = get_option( 'aoa_auto_id', null );
		if ( $id == '' ) return do_shortcode( $content );
		if ( $this->debug ) echo "<!-- AOA auto id is {$id} -->\n";

		$aae = get_option( 'aoa_auto_elements', null );
		if ( empty( $aae ) ) return do_shortcode( $content );
		if ( $this->debug ) echo "<!-- AOA auto elements are {$aae} -->\n";

		// only proceed if singular display
		if ( ! is_single() && ! is_page() ) return do_shortcode( $content );
		if ( $this->debug ) echo "<!-- AOA single page pass -->\n";

		if ( ! $content ) return $content;
		if ( $this->debug ) echo "<!-- AOA empty content pass -->\n";

		// is cookie set?
		$cookie = get_option( 'aoa_cookie_hours', "0" );
		if ( is_numeric( $cookie ) && $cookie > 0 && isset( $_COOKIE['aoa'] ) ) 
		{
			return do_shortcode( $content );
		}
		if ( $this->debug ) echo "<!-- AOA cookie check pass -->\n";

		// check for meta field id override
		$post_id = get_the_ID();
		if ( $this->debug ) echo "<!-- AOA post id is {$post_id} -->\n";
		if ( $post_id ) {	
			$idcheck = (int) get_post_meta( $post_id, 'aoa_id', true );
			if ( $this->debug && ! empty( $idcheck ) ) error_log( __FUNCTION__ . " meta field 'aoa_id' override: [" . print_r($idcheck,true) . "]" );

			if ( $this->debug ) echo "<!-- AOA custom meta field aoa_id is {$idcheck} -->\n";
			if ( $idcheck < 0 ) return do_shortcode( $content );
			else if ( ! empty( $idcheck ) ) {
				$id = $idcheck;
			}
		}
		if ( $this->debug ) echo "<!-- AOA meta field check pass -->\n";

		if ( $id == 0 && get_option( 'aoa_random_status' ) == 'Inactive' ) return do_shortcode( $content );
		if ( $this->debug ) echo "<!-- AOA random Inactive check pass -->\n";

		// does the content already use aoa? then skip auto overlay
		if ( FALSE !== stripos( $content, 'aoa_wrap' ) ) return do_shortcode( $content );
		if ( FALSE !== stripos( $content, '[/aoa]' ) ) return do_shortcode( $content );
		if ( $this->debug ) echo "<!-- AOA content keyword pass -->\n";

		if ( $this->debug ) error_log( __FUNCTION__ . " content: " . $content );

		// convert from comma-delimited string to array:
		$elements = explode( ',', $aae );
		if ( $this->debug ) error_log( __FUNCTION__ . " for elements [" . $aae . "] with Ad Id " . $id );

		// check elements and see if we need to wrap them in our class:
		foreach ( $elements as $ele )
		{
			if ( $this->debug ) echo "<!-- AOA checking for element {$ele} -->\n";
			$ele = trim( $ele );
			$pattern = sprintf( "~<%s\b[^>]*>(?:(.*?)?</%s>)?(?!\[\/aoa\])~", $ele, $ele );
			if ( ! preg_match( $pattern, $content, $matches ) ) continue;
			if ( $this->debug ) echo "<!-- AOA element {$ele} found, inserting shortcode -->\n";
			$replace = '[aoa id=' . $id . ']${0}[/aoa]';
			$content = preg_replace( $pattern, $replace, $content );
		}

		if ( $this->debug ) error_log( __FUNCTION__ . " insert finished: " . $content );

		// now expand any aoa shortcodes we inserted:
		$content = do_shortcode( $content );

		// did aoa shortcode insert another shortcode? (nested shortcode)
		$content = do_shortcode( $content );

		if ( $this->debug ) echo "<!-- AOA auto overlay finished -->\n";

		return $content;
	}

//----- CUSTOM META FIELD functions ---------------------------------------------------------------------
	/*
	* Replace custom meta field video with AoA shortcode and process into code
	*/
	public function aoa_custom_meta( $value, $postID, $meta_key, $single ) {
  
	$custom_meta_fields = get_option( 'aoa_custom_fields', '' );
	$custom_meta_key = explode( ',', $custom_meta_fields );

  	// are we on a single post page and trying to get video code meta data and AoA is being used?
  	if ( is_single() && in_array( $meta_key, $custom_meta_key ) ) {

		// Note $value is not passed in, so
		// use direct wpdb call to get the meta_key value
		global $wpdb;
		$meta_data = $wpdb->get_var( "SELECT meta_value FROM $wpdb->postmeta WHERE post_id = $postID AND  meta_key = '".$meta_key."'" );

		if ( ! $meta_data  ) {
			return $value;
		}
	  
	  	// wrap the meta_data value with aoa shortcode for a random ad
		$id = get_option( 'aoa_auto_id', 0 );
		$meta_data = sprintf( '[aoa id="%s"]%s[/aoa]',
				$id,
				$meta_data
		);

	  	// resolve the shortcode
	  	$aoa_meta = $this->aoa_auto_overlay( $meta_data ); // auto overlay elements defined in Main Settings
	  	// return the video wrapped with ad code
	  	return $aoa_meta;
	}
  	// otherwise return default empty meta value
  	return $value;
	}

    } // END class aoa_core
} // END if(!class_exists('aoa_core'))

////////////////////////////////////////////////////////////////////////////////////////////

if(!class_exists('aoa_envato_api'))
{

    class aoa_envato_api {

	// Bearer, no need for OAUTH token, change this to your bearer string
	// https://build.envato.com/my-apps/#tokens
	private static $bearer = "JPk0M1gUHXFr9cw60bIvqht2SXRsiXbZ";

	static function getPurchaseData( $code ) {
    
		//setting the header for the rest of the api
		$bearer   = 'Bearer ' . self::$bearer;
		$header   = array( 'Authorization' => $bearer );
    
		$verify_url = 'https://api.envato.com/v2/market/author/sale?code=' . $code;

		$response = wp_remote_get( $verify_url, array( 'headers' => $header, 'decompress' => FALSE, 'sslverify' => FALSE, 'user-agent'  => 'Ad Overlay Anything' ) );

		return $response;
	}
  
	static function verifyPurchase( $code, $username ) {

		$response = self::getPurchaseData( $code ); 

		if ( is_wp_error( $response ) ) {
			return sprintf( esc_html__( 'WP error %s in %s - %s ', 'ad-overlay-anything' ), $response->get_error_code(), __FUNCTION__, $response->get_error_message() );
		}

		$verify_obj = json_decode( wp_remote_retrieve_body( $response ) );

		$verify_obj = apply_filters( 'aoa_verify', $verify_obj );

		$msg = null;

		// Check for correct verify code
		if ( 
			(false === $verify_obj) || 
			!is_object($verify_obj)
		)
			$msg = esc_html__( "Ad Overlay Anything: Could not connect to Envato API server.", 'ad-overlay-anything' );
		else if (
			isset( $verify_obj->error ) &&
			isset( $verify_obj->description )
		)
			$msg = sprintf( esc_html__('Ad Overlay Anything: Envato error: %s', 'ad-overlay-anything' ), $verify_obj->description );
		else if (
			!isset($verify_obj->item) ||
			!isset($verify_obj->item->name)
		)
			$msg = esc_html__( "Ad Overlay Anything: Envato API did not return item information.", 'ad-overlay-anything' );

		// Check for proper item name
		else if (
			FALSE === stripos( $verify_obj->item->name, 'Ad Overlay Anything' )
		)
			$msg = sprintf( esc_html__('Envato API states the Ad Overlay Anything purchase code is for: %s', 'ad-overlay-anything' ), $verify_obj->item->name );

		// Check for proper item id
		else if (
			$verify_obj->item->id != 13892181
		)
			$msg = esc_html__( "Envato API states the Ad Overlay Anything purchase code is for another product id.", 'ad-overlay-anything' );
			
		// Check for username match
		else if (
			! empty( $verify_obj->buyer ) && 
			strcmp( $verify_obj->buyer, $username )
		)
			$msg = esc_html__( "Envato states the Ad Overlay Anything purchase code is for another username.", 'ad-overlay-anything' );

		else if ( isset( $verify_obj->supported_until ) && ! empty( $verify_obj->supported_until ) )
			update_option( 'aoa_support', $verify_obj->supported_until );
		else 
			$msg = esc_html__( "Ad Overlay Anything: Strange. Envato API did not return a support field.", 'ad-overlay-anything' );
		return $msg;
	}

    }
}


if(class_exists('aoa_core'))
{
	// instantiate the plugin class
	$ad_overlay_anything = new aoa_core();

	// Add a link to the settings page onto the plugin page
	if ( isset( $ad_overlay_anything ) )
	{
		// Add the settings link to the plugins page
		function aoa_plugin_settings_link($links)
    		{
			$settings_link = '<a href="admin.php?page=ad_overlay_anything">Settings</a>'; 
			array_unshift($links, $settings_link); 
			return $links; 
    		}
    		$plugin = plugin_basename(__FILE__); 
    		add_filter("plugin_action_links_$plugin", 'aoa_plugin_settings_link');
	}
}

////////////////////////////////////////////////////////////////////////////////////////////
