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,713 @@
<?php
if ( ! class_exists( 'BWF_AS_Action_Store' ) ) {
#[AllowDynamicProperties]
class BWF_AS_Action_Store extends ActionScheduler_Store {
public $bwf_action_data = [];
public $action_table = '';
public $claim_table = '';
public $p_key = '';
public function init() {
global $wpdb;
$this->action_table = BWF_AS_Actions_Crud::_table();
$this->claim_table = $wpdb->bwf_action_claim;
$this->p_key = BWF_AS_Actions_Crud::$primary_key;
}
public function save_action( ActionScheduler_Action $action, ?DateTime $date = null ) {
/** Not scheduling any new action while processing our requests */
}
public function fetch_action( $action_id ) {
global $wpdb;
if ( empty( $action_id ) ) {
return $this->get_null_action();
}
$this->log( 'fetch running action id: ' . $action_id );
if ( class_exists( 'BWFAN_Merge_Tag_Loader' ) ) {
BWFAN_Merge_Tag_Loader::reset_data();
}
/**
* Below code will run between these 2 hooks action_scheduler_begin_execute and action_scheduler_after_execute
*/
if ( true === BWF_AS::is_execution_started() ) {
/** Changing status to running i.e. 1 on action */
$wpdb->update( $this->action_table, [ 'status' => 1 ], [ $this->p_key => $action_id ], [ '%s' ], [ '%d' ] ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
}
$data = $this->get_action_data( $action_id );
if ( empty( $data ) || ! ( $data instanceof StdClass ) ) {
return $this->get_null_action();
}
if ( true === BWF_AS::is_execution_started() ) {
/** Scheduling recurring action if possible */
$this->schedule_recurring_action( $action_id );
}
/** Fetching action data again as status may be altered */
$data = $this->get_action_data( $action_id );
/** If hook not present, return null action */
if ( empty( $data->hook ) || ! ( $data instanceof StdClass ) ) {
return $this->get_null_action();
}
return $this->make_action_from_db_record( $data );
}
protected function get_null_action() {
return new ActionScheduler_NullAction();
}
public function log( $msg ) {
BWF_Logger::get_instance()->log( WooFunnels_AS_DS::$unique . ' - ' . $msg, 'woofunnel-as' );
}
protected function get_action_data( $action_id ) {
$cache_key = 'bwf_fetch_action_' . $action_id;
if ( isset( $this->bwf_action_data[ $action_id ] ) ) {
return $this->bwf_action_data[ $action_id ];
}
$data = wp_cache_get( $cache_key, __CLASS__ );
if ( false === $data ) {
$data = BWF_AS_Actions_Crud::get_single_action( $action_id );
/** Saving data to local scope and cache */
if ( is_object( $data ) ) {
$this->bwf_action_data[ $action_id ] = $data;
wp_cache_set( $cache_key, $data, __CLASS__, ( 60 ) );
}
}
return $data;
}
/**
* Helper method to schedule recurring action before execution itself.
* This make sure recurring action should be scheduled.
*
* @param $action_id
*/
protected function schedule_recurring_action( $action_id ) {
global $wpdb;
$data = $this->get_action_data( $action_id );
/** Checking if recurring action */
if ( ! ( $data instanceof StdClass ) || false === $this->action_is_recurring( $data ) ) {
return;
}
$args = ( is_array( $data->args ) && count( $data->args ) > 0 ) ? $data->args : array();
$group = ( ! empty( $data->group_slug ) ) ? $data->group_slug : '';
/** Checking if already running then change the status to failed and schedule new action */
$count = bwf_scheduled_action_count( $data->hook, $args, $group, '1', 'recurring' );
if ( false === $count || 1 < $count ) {
$this->log( __FUNCTION__ . ' id ' . $action_id . ', recurring action already running count: ' . $count );
/** Changing status to failed i.e. 2 on action */
$wpdb->update( $this->action_table, [ 'status' => 2 ], [ $this->p_key => $action_id ], [ '%s' ], [ '%d' ] ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
/** Modify action object cache data status */
if ( isset( $this->bwf_action_data[ $action_id ] ) ) {
$this->bwf_action_data[ $action_id ]->status = '2';
}
}
/** Validate non-running actions */
$count = bwf_scheduled_action_count( $data->hook, $args, $group, '0', 'recurring' );
if ( 1 === $count ) {
/** if one current and one more action non-running found then no need to schedule */
return;
}
if ( 1 < $count ) {
/** delete all non running actions i.e. 0 except current action */
bwf_delete_scheduled_recurring_action( $data->hook, 0, $action_id );
}
/** Scheduling new action */
$curr_time = current_time( 'mysql', 1 );
$exec_time = time() + (int) $data->recurring_interval;
$exec_time = apply_filters( 'bwf_recurring_action_' . $data->hook . '_execution_time', $exec_time, $data );
$new_data = array(
'c_date' => $curr_time,
'e_time' => $exec_time,
'hook' => $data->hook,
'recurring_interval' => (int) $data->recurring_interval,
'claim_id' => 0
);
if ( is_array( $data->args ) && count( $data->args ) > 0 ) {
$new_data['args'] = wp_json_encode( $data->args );
}
if ( ! empty( $data->group_slug ) ) {
$new_data['group_slug'] = $data->group_slug;
}
BWF_AS_Actions_Crud::insert( $new_data );
}
/**
* Helper method that checks if an action is recurring.
*
* @param $data
*
* @return bool
*/
protected function action_is_recurring( $data ) {
if ( ! is_object( $data ) ) {
return false;
}
if ( (int) $data->recurring_interval < 1 ) {
return false;
}
return true;
}
/**
* Initiate action class object with needful data
*
* @param $data
*
* @return ActionScheduler_Action|ActionScheduler_FinishedAction
*/
protected function make_action_from_db_record( $data ) {
$hook = $data->hook;
$args = ( is_array( $data->args ) && count( $data->args ) > 0 ) ? $data->args : [];
/** creating fresh schedule */
$schedule = new ActionScheduler_NullSchedule();
$group = ( ! empty( $data->group_slug ) ) ? $data->group_slug : '';
if ( $this->verify_status( $data->status ) ) {
$action = new ActionScheduler_Action( $hook, $args, $schedule, $group );
} else {
/** status not 0 - finishing AS action (status won't occur as we are fetching 0 status actions only) */
$action = new ActionScheduler_FinishedAction( $hook, $args, $schedule, $group );
}
return $action;
}
/**
* Helper method: If pending action then bool true otherwise false
*
* @param $status
*
* @return bool
*/
protected function verify_status( $status ) {
return ( 0 == $status || 1 == $status ) ? true : false;
}
/**
* @param string $hook
* @param array $params
*
* @return string
*/
public function find_action( $hook, $params = [] ) {
/** This is invoked during unscheduled or next schedule, we are not doing anything, so blank */
return '';
}
/**
* @param array $query
* @param string $query_type
*
* @return array|string ids array or count
*/
public function query_actions( $query = [], $query_type = 'select' ) {
global $wpdb;
/** cleanup call handling */
if ( ! isset( $query['status'] ) || in_array( $query['status'], array( 'complete', 'canceled', 'failed' ), true ) || is_array( $query['status'] ) ) {
return array();
}
if ( 'pending' === $query['status'] ) {
$query['status'] = '0';
} elseif ( 'in-progress' === $query['status'] ) {
$query['status'] = '1';
}
/** Code will through in case of pending status i.e. 0 */
$sql = $this->get_query_actions_sql( $query, $query_type );
$value = ( 'count' === $query_type ) ? $wpdb->get_var( $sql ) : $wpdb->get_col( $sql ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
if ( empty( $value ) ) {
return array();
}
$this->log( __FUNCTION__ . ': status ' . $query['status'] . ' - (' . $this->get_as_defined_status_val( $query['status'] ) . ')' . ' query result: ' . implode( ',', $value ) );
return $value;
}
/**
* Returns the SQL statement to query (or count) actions.
*
* @param array $query Filtering options
* @param string $select_or_count Whether the SQL should select and return the IDs or just the row count
*
* @return string SQL statement. The returned SQL is already properly escaped.
* 'status' => ActionScheduler_Store::STATUS_PENDING,
* 'modified' => $cutoff,
* 'modified_compare' => '<=',
* 'claimed' => true,
* 'per_page' => $this->get_batch_size(),
*/
protected function get_query_actions_sql( array $query, $select_or_count = 'select' ) {
if ( ! in_array( $select_or_count, array( 'select', 'count' ), true ) ) {
throw new InvalidArgumentException( esc_html__( 'Invalid value for select or count parameter. Cannot query actions.', 'action-scheduler' ) ); // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
}
$query = wp_parse_args( $query, [
'hook' => '',
'args' => null,
'date' => null,
'date_compare' => '<=',
'modified' => null,
'modified_compare' => '<=',
'group' => '',
'status' => '0',
'claimed' => null,
'per_page' => 5,
'offset' => 0,
'orderby' => 'date',
'order' => 'ASC',
] );
global $wpdb;
$sql = 'SELECT ';
$sql .= ( 'count' === $select_or_count ) ? "count({$this->p_key})" : "{$this->p_key} ";
$sql .= "FROM {$this->action_table}";
$sql_params = [];
$sql .= ' WHERE 1=1';
if ( ! empty( $query['group'] ) ) {
$sql .= ' AND group_slug=%s';
$sql_params[] = $query['group'];
}
if ( $query['hook'] ) {
$sql .= ' AND hook=%s';
$sql_params[] = $query['hook'];
}
if ( ! is_null( $query['args'] ) ) {
$sql .= ' AND args=%s';
$sql_params[] = wp_json_encode( $query['args'] );
}
/** 0 or 1 in our case */
if ( '' !== $query['status'] ) {
$sql .= ' AND status=%s';
$sql_params[] = $query['status'];
}
if ( $query['date'] instanceof DateTime ) {
$date = clone $query['date'];
$date->setTimezone( new DateTimeZone( 'UTC' ) );
$date_string = $date->format( 'Y-m-d H:i:s' );
$comparator = $this->validate_sql_comparator( $query['date_compare'] );
$sql .= " AND e_time $comparator %s";
$sql_params[] = $date_string;
}
if ( $query['claimed'] === true ) {
$sql .= ' AND claim_id != 0';
} elseif ( $query['claimed'] === false ) {
$sql .= ' AND claim_id = 0';
} elseif ( ! is_null( $query['claimed'] ) ) {
$sql .= ' AND claim_id = %d';
$sql_params[] = $query['claimed'];
}
if ( $query['modified'] instanceof DateTime ) {
$modified = clone $query['modified'];
$modified->setTimezone( new DateTimeZone( 'UTC' ) );
$date_string = $modified->getTimestamp();
$comparator = $this->validate_sql_comparator( $query['modified_compare'] );
$sql .= " AND e_time $comparator %s";
$sql_params[] = $date_string;
}
if ( 'select' === $select_or_count ) {
switch ( $query['orderby'] ) {
case 'date':
default:
$orderby = 'e_time';
break;
}
$order = ( strtoupper( $query['order'] ) === 'ASC' ) ? 'ASC' : 'DESC';
$sql .= " ORDER BY $orderby $order";
if ( $query['per_page'] > 0 ) {
$sql .= ' LIMIT %d, %d';
$sql_params[] = $query['offset'];
$sql_params[] = $query['per_page'];
}
}
if ( ! empty( $sql_params ) ) {
$sql = $wpdb->prepare( $sql, $sql_params ); //phpcs:ignore WordPress.DB.PreparedSQL
}
return $sql;
}
protected function get_as_defined_status_val( $status ) {
switch ( $status ) {
case '0':
return 'pending';
case '1':
return 'in-progress';
case '2':
return 'canceled';
}
return $status;
}
/**
* Get a count of all actions in the store, grouped by status; used in native actions listing. Not used in our scope.
*/
public function action_counts() {
return [];
}
/**
* @param string $action_id
*
* @return void
* @throws InvalidArgumentException
*/
public function cancel_action( $action_id ) {
$this->log( __FUNCTION__ . ' id ' . $action_id );
return;
}
/**
* @param string $action_id
*/
public function delete_action( $action_id ) {
$this->log( __FUNCTION__ . ' id ' . $action_id );
return;
}
/**
* don't know where using
*
* @param string $action_id
*
* @return DateTime The local date the action is scheduled to run, or the date that it ran.
* @throws InvalidArgumentException
*/
public function get_date( $action_id ) {
$date = $this->get_date_gmt( $action_id );
ActionScheduler_TimezoneHelper::set_local_timezone( $date );
return $date;
}
/**
* @param string $action_id
*
* @return DateTime The GMT date the action is scheduled to run, or the date that it ran.
* @throws InvalidArgumentException
*/
protected function get_date_gmt( $action_id ) {
$record = BWF_AS_Actions_Crud::get_single_action( $action_id );
if ( empty( $record ) ) {
throw new InvalidArgumentException( esc_html( sprintf( __( 'Unidentified action %s', 'action-scheduler' ), $action_id ) ) ); // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch, WordPress.WP.I18n.MissingTranslatorsComment
}
if ( $this->verify_status( $record->status ) ) {
return as_get_datetime_object( $record->e_time );
}
}
/**
* @param int $max_actions
* @param DateTime $before_date Jobs must be schedule before this date. Defaults to now.
*
* @return ActionScheduler_ActionClaim
*/
public function stake_claim( $max_actions = 10, ?DateTime $before_date = null, $hooks = array(), $group = '' ) {
$claim_id = $this->generate_claim_id();
$this->log( __FUNCTION__ . ' claim id: ' . $claim_id );
$this->claim_actions( $claim_id, $max_actions, $before_date, $hooks, $group );
$action_ids = $this->find_actions_by_claim_id( $claim_id );
return new ActionScheduler_ActionClaim( $claim_id, $action_ids );
}
/**
* Generate claim id of current date time
*
* @return int
*/
protected function generate_claim_id() {
global $wpdb;
$now = as_get_datetime_object();
//phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
$wpdb->insert( $this->claim_table, [
'date' => $now->format( 'Y-m-d H:i:s' ),
] );
return $wpdb->insert_id;
}
/**
* Claim actions which are executable based on given inputs
*
* @param string $claim_id
* @param int $limit
* @param DateTime $before_date Should use UTC timezone.
*
* @return int The number of actions that were claimed
* @throws RuntimeException
*
*/
protected function claim_actions( $claim_id, $limit, ?DateTime $before_date = null, $hooks = array(), $group = '' ) {
global $wpdb;
/** can't use $wpdb->update() because of the <= condition */
$update = "SELECT {$this->p_key} FROM {$this->action_table}";
$params = [];
$where = 'WHERE `claim_id` = 0 AND `e_time` <= %s AND `status` = 0';
$params[] = time();
if ( ! empty( $group ) ) {
$where .= ' AND `group` = %s';
$params[] = $group;
}
$order = 'ORDER BY `e_time` ASC LIMIT %d';
$params[] = $limit;
$sql = $wpdb->prepare( "{$update} {$where} {$order}", $params ); //phpcs:ignore WordPress.DB.PreparedSQL
$action_ids = $wpdb->get_results( $sql, ARRAY_A ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
if ( ! is_array( $action_ids ) || count( $action_ids ) == 0 ) {
return 0;
}
$action_ids = array_column( $action_ids, $this->p_key );
/** Update call */
$type = array_fill( 0, count( $action_ids ), '%d' );
$format = implode( ', ', $type );
$query = "UPDATE {$this->action_table} SET `claim_id` = %d WHERE {$this->p_key} IN ({$format})";
$params = array( $claim_id );
$params = array_merge( $params, $action_ids );
$sql = $wpdb->prepare( $query, $params ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
$rows_affected = $wpdb->query( $sql ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
if ( $rows_affected === false ) {
throw new RuntimeException( esc_html__( 'Unable to claim actions. Database error.', 'action-scheduler' ) ); // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
}
return (int) $rows_affected;
}
/**
* Get Actions against a claim_id
*
* @param string $claim_id
*
* @return $array
*/
public function find_actions_by_claim_id( $claim_id ) {
global $wpdb;
$cache_key = 'bwf_action_ids_for_claim_id_' . $claim_id;
$cache_available = wp_cache_get( $cache_key, __CLASS__ );
if ( false !== $cache_available ) {
return $cache_available;
}
$sql = "SELECT `{$this->p_key}` FROM {$this->action_table} WHERE claim_id=%d ORDER BY e_time ASC";
$sql = $wpdb->prepare( $sql, $claim_id ); //phpcs:ignore WordPress.DB.PreparedSQL
$action_ids = $wpdb->get_col( $sql ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
$return = array_map( 'intval', $action_ids );
wp_cache_set( $cache_key, $return, __CLASS__, ( HOUR_IN_SECONDS / 4 ) );
$this->log( 'Found ids: ' . implode( ', ', $return ) );
return $return;
}
/**
* Return unique claim id counts
*
* @return int
*/
public function get_claim_count() {
global $wpdb;
/** status 0 have actions which are executable */
$sql = "SELECT COUNT(DISTINCT claim_id) FROM {$this->action_table} WHERE claim_id != 0 AND status = 0";
return (int) $wpdb->get_var( $sql ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
}
/**
* Return an action's claim ID, as stored in the claim_id column
*
* @param string $action_id
*
* @return mixed
*/
public function get_claim_id( $action_id ) {
$this->log( __FUNCTION__ . ' ' . $action_id );
$claim_id = BWF_AS_Actions_Crud::get_single_action( $action_id, 'claim_id' );
return (int) $claim_id;
}
/**
* Releasing the claim
*
* @param ActionScheduler_ActionClaim $claim
*/
public function release_claim( ActionScheduler_ActionClaim $claim ) {
$this->log( __FUNCTION__ . ' id ' . $claim->get_id() );
global $wpdb;
$wpdb->update( $this->action_table, [ 'claim_id' => 0 ], [ 'claim_id' => $claim->get_id() ], [ '%d' ], [ '%d' ] ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
$wpdb->delete( $this->claim_table, [ 'id' => $claim->get_id() ], [ '%d' ] ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
}
/**
* Unclaim pending actions that have not been run within a given time limit.
* Default 300
* Called inside reset_timeouts method
*
* @param string $action_id
*
* @return void
*/
public function unclaim_action( $action_id ) {
$this->log( __FUNCTION__ . ' id ' . $action_id );
global $wpdb;
$wpdb->update( $this->action_table, [ 'claim_id' => 0 ], [ $this->p_key => $action_id ], [ '%s' ], [ '%d' ] ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
}
/**
* @param string $action_id
* @param null $e
*/
public function mark_failure( $action_id, $e = null ) {
$this->log( __FUNCTION__ . ' for action id ' . $action_id );
/** Log failure data */
$this->log_failure_data( $action_id );
/** Deleting existing action */
BWF_AS_Actions_Crud::delete( $action_id );
}
/**
* Helper method
* Log failure action data in bwf logs
*
* @param $action_id
*/
protected function log_failure_data( $action_id ) {
$data = $this->get_action_data( $action_id );
if ( $data instanceof StdClass ) {
$log_arr = array(
'action_id' => $action_id,
'creation_date' => $data->c_date,
'execution_time' => $data->e_time,
'hook' => $data->hook,
'arguments' => $data->args,
'group' => $data->group_slug,
'recurring' => $data->recurring_interval,
'error' => error_get_last(),
);
/** updating logs force */
add_filter( 'bwf_logs_allowed', array( $this, 'overriding_bwf_logging' ), 99999, 2 );
BWF_Logger::get_instance()->log( print_r( $log_arr, true ), 'woofunnel-failed-actions' );
remove_filter( 'bwf_logs_allowed', array( $this, 'overriding_bwf_logging' ), 99999, 2 );
}
}
/**
* @param string $action_id
*
* @return void
*/
public function log_execution( $action_id ) {
/** no need to log as we are managing logs differently, even attempts */
}
/**
* @param string $action_id
*/
public function mark_complete( $action_id ) {
$this->log( __FUNCTION__ . ' for action id ' . $action_id );
/** Deleting existing action */
BWF_AS_Actions_Crud::delete( $action_id );
}
public function get_status( $action_id ) {
$this->log( __FUNCTION__ . ' of action id ' . $action_id );
$status = BWF_AS_Actions_Crud::get_action_status( $action_id );
if ( null === $status ) {
throw new InvalidArgumentException( esc_html__( 'Invalid action ID. No status found.', 'action-scheduler' ) ); // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
} else {
return $this->get_as_defined_status_val( $status );
}
}
public function overriding_bwf_logging( $value, $filename ) {
return true;
}
/**
* Cancel pending actions by hook.
*
* @param string $hook
*
* @since 3.0.0 Action Scheduler and 1.9.15 Core
*/
public function cancel_actions_by_hook( $hook ) {
return;
}
/**
* Cancel pending actions by group.
*
* @param string $group
*
* @since 3.0.0 Action Scheduler and 1.9.15 Core
*/
public function cancel_actions_by_group( $group ) {
return;
}
}
}

View File

@@ -0,0 +1,107 @@
<?php
use WP_CLI\ExitException;
use function WP_CLI\Utils\get_flag_value;
if ( ! class_exists( 'BWF_AS_CLI' ) ) {
/**
* Commands for the Custom Action Scheduler
*/
#[AllowDynamicProperties]
class BWF_AS_CLI extends WP_CLI_Command {
/**
* Run the Autonami tasks
*
* ## OPTIONS
*
* [--size=<size>]
* : The maximum number of tasks to run. Defaults to 50.
*
* @param array $args Positional arguments.
* @param array $assoc_args Keyed arguments.
*
* @throws ExitException When an error occurs.
*/
public function run( $args, $assoc_args ) {
// Handle passed arguments.
$size = absint( get_flag_value( $assoc_args, 'size', 50 ) );
$tasks_completed = 0;
try {
if ( ! class_exists( 'ActionScheduler_QueueRunner' ) ) {
$this->print_custom_error( '1' );
}
$global_settings = BWFAN_Common::get_global_settings();
if ( 1 == $global_settings['bwfan_sandbox_mode'] || ( defined( 'BWFAN_SANDBOX_MODE' ) && true === BWFAN_SANDBOX_MODE ) ) {
$this->print_custom_error( '2' );
}
/** Custom queue cleaner instance */
$cleaner = new ActionScheduler_QueueCleaner( null, $size );
/** Queue runner instance */
$runner = new ActionScheduler_WPCLI_QueueRunner( null, null, $cleaner );
/** Run Action Scheduler worker */
// Determine how many tasks will be run in the first batch.
$total = $runner->setup( $size );
WP_CLI::log( "Current batch size is: " . $size );
$this->print_total_tasks( $total );
$tasks_completed = $runner->run();
} catch ( Exception $e ) {
$this->print_error( $e );
}
$this->print_success( $tasks_completed );
}
protected function print_custom_error( $type ) {
switch ( $type ) {
case '1':
$msg = 'ActionScheduler_QueueRunner class not found.';
break;
case '2':
$msg = 'FunnelKit Automations Sandbox mode is ON.';
break;
default:
$msg = 'Some error occurred';
}
WP_CLI::error( sprintf( /* translators: %s refers to the exception error message. */ $msg ) );
}
/**
* Print WP CLI message about how many tasks are about to be processed.
*
* @param int $total
*/
protected function print_total_tasks( $total ) {
WP_CLI::log( sprintf( /* translators: %d refers to how many scheduled tasks were found to run */ _n( 'Found %d scheduled task', 'Found %d scheduled tasks', $total, 'action-scheduler' ), number_format_i18n( $total ) ) ); // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch, WordPress.WP.I18n.MissingTranslatorsComment
}
/**
* Convert an exception into a WP CLI error.
*
* @param Exception $e The error object.
*
* @throws ExitException
*/
protected function print_error( Exception $e ) {
WP_CLI::error( sprintf( /* translators: %s refers to the exception error message. */ __( 'There was an error running the action scheduler: %s', 'action-scheduler' ), $e->getMessage() ) ); // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch, WordPress.WP.I18n.MissingTranslatorsComment
}
/**
* Print a success message with the number of completed tasks.
*
* @param int $tasks_completed
*/
protected function print_success( $tasks_completed ) {
WP_CLI::success( sprintf( /* translators: %d refers to the total number of tasks completed */ _n( '%d scheduled task completed.', '%d scheduled tasks completed.', $tasks_completed, 'action-scheduler' ), number_format_i18n( $tasks_completed ) ) ); // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch, WordPress.WP.I18n.MissingTranslatorsComment
}
}
}

View File

@@ -0,0 +1,30 @@
<?php
if ( ! class_exists( 'BWF_AS_Log_Store' ) ) {
/**
* Not saving any log as no do_action left in action data store
*
* Class BWFAN_AS_CT_Log_Store
*/
#[AllowDynamicProperties]
class BWF_AS_Log_Store extends ActionScheduler_Logger {
public function log( $action_id, $message, ?DateTime $date = null ) {
return;
}
public function get_entry( $entry_id ) {
return new ActionScheduler_NullLogEntry();
}
public function get_logs( $action_id ) {
return array();
}
public function init() {
}
public function clear_deleted_action_logs( $action_id ) {
}
}
}

View File

@@ -0,0 +1,192 @@
<?php
if ( ! class_exists( 'BWF_AS' ) ) {
#[AllowDynamicProperties]
class BWF_AS {
private static $instance;
protected $start_time = 0;
public static $execution_started = 0;
public function __construct() {
global $wpdb;
$wpdb->bwf_actions = $wpdb->prefix . 'bwf_actions';
$wpdb->bwf_action_claim = $wpdb->prefix . 'bwf_action_claim';
$this->start_time = time();
}
public static function instance() {
if ( ! isset( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Change the data store
*/
public function change_data_store() {
/** Hook late so that functionalities can be hooked in */
add_action( 'plugins_loaded', [ $this, 'bwf_data_store_set' ], 1000 );
/** Removing all action data store change filter and then assign ours */
remove_all_filters( 'action_scheduler_store_class' );
add_filter( 'action_scheduler_store_class', [ $this, 'set_store_class' ], 1000000, 1 );
/** Removing all log data store change filter and then assign ours */
remove_all_filters( 'action_scheduler_logger_class' );
add_filter( 'action_scheduler_logger_class', [ $this, 'set_logger_class' ], 1000000, 1 );
/** Removing all AS memory exceeds filter */
remove_all_filters( 'action_scheduler_memory_exceeded' );
add_filter( 'action_scheduler_memory_exceeded', [ $this, 'check_memory_exceeded' ], 1000000, 1 );
add_action( 'action_scheduler_begin_execute', [ $this, 'attach_flag' ] );
add_action( 'action_scheduler_after_execute', [ $this, 'detach_flag' ] );
add_action( 'action_scheduler_failed_execution', [ $this, 'detach_flag' ] );
add_action( 'action_scheduler_failed_validation', [ $this, 'detach_flag' ] );
}
public function bwf_data_store_set() {
do_action( 'bwf_as_data_store_set' );
}
/**
* Override the action store with our own
*
* @param string $class
*
* @return string
*/
public function set_store_class( $class ) {
return BWF_AS_Action_Store::class;
}
/**
* Override the logger with our own
*
* @param string $class
*
* @return string
*/
public function set_logger_class( $class ) {
return BWF_AS_Log_Store::class;
}
/**
* Override memory exceeded filter value
*
* @param $memory_exceeded
*
* @return bool
*/
public function check_memory_exceeded( $memory_exceeded ) {
if ( true === $memory_exceeded ) {
return $memory_exceeded;
}
return $this->validate_time_breach();
}
/**
* Validate if call input time reached
*
* @return bool
*/
public function validate_time_breach() {
$per_call_time = apply_filters( 'bwfan_as_per_call_time', 30 );
if ( ( time() - $this->start_time ) >= $per_call_time || $this->memory_exceeded() ) {
return true;
}
return false;
}
/**
* Check server memory limit.
* Using 75% max
*
* @return bool
*/
public function memory_exceeded() {
$memory_limit = $this->get_memory_limit() * 0.9;
$current_memory = memory_get_usage( true );
return ( $current_memory >= $memory_limit );
}
/**
* Get Server memory limit value
*
* @return int|mixed
*/
public function get_memory_limit() {
if ( function_exists( 'ini_get' ) ) {
$memory_limit = ini_get( 'memory_limit' );
} else {
$memory_limit = '128M'; // Sensible default, and minimum required by WooCommerce
}
if ( ! $memory_limit || - 1 === $memory_limit || '-1' === $memory_limit ) {
// Unlimited, set to 32GB.
$memory_limit = '32G';
}
return $this->convert_hr_to_bytes( $memory_limit );
}
/**
* Convert memory to bytes
*
* @param $value
*
* @return int|mixed
*/
public function convert_hr_to_bytes( $value ) {
if ( function_exists( 'wp_convert_hr_to_bytes' ) ) {
return wp_convert_hr_to_bytes( $value );
}
$value = strtolower( trim( $value ) );
$bytes = (int) $value;
if ( false !== strpos( $value, 'g' ) ) {
$bytes *= GB_IN_BYTES;
} elseif ( false !== strpos( $value, 'm' ) ) {
$bytes *= MB_IN_BYTES;
} elseif ( false !== strpos( $value, 'k' ) ) {
$bytes *= KB_IN_BYTES;
}
// Deal with large (float) values which run into the maximum integer size.
return min( $bytes, PHP_INT_MAX );
}
/**
* Attach flag before starting execution of the action
*
* @return void
*/
public function attach_flag() {
self::$execution_started = 1;
}
/**
* Detach flag after finishing the execution of the action
*
* @return void
*/
public function detach_flag() {
self::$execution_started = 0;
}
/**
* Check if action execution started
*
* @return bool
*/
public static function is_execution_started() {
return ( self::$execution_started === 1 );
}
}
}

View File

@@ -0,0 +1,2 @@
<?php
// Silence is golden.

View File

@@ -0,0 +1,685 @@
<?php
/**
* @todo things to do
* AS data store cli
*/
if ( ! class_exists( 'WooFunnels_AS_DS' ) ) {
#[AllowDynamicProperties]
final class WooFunnels_AS_DS {
public static $unique = '';
private static $ins = null;
public $dir = __DIR__;
/**
* WooFunnels_Actions constructor.
*/
public function __construct() {
$enable_as_ds = apply_filters( 'enable_woofunnels_as_ds', false );
if ( true !== $enable_as_ds && ! class_exists( 'BWFAN_Core' ) ) {
return;
}
add_action( 'action_scheduler_pre_init', array( $this, 'load_files' ) );
/** Rest API endpoint */
add_action( 'rest_api_init', array( $this, 'register_endpoints' ) );
/** BWF Action Scheduler custom table worker callback */
add_action( 'bwf_as_run_queue', array( $this, 'run_as_ct_worker' ) );
add_action( 'action_scheduler_pre_init', array( $this, 'as_pre_init_cb' ) );
/** Needs to code */
add_action( 'action_scheduler_pre_init', array( $this, 'as_pre_init_cli_cb' ) );
/** Creating tables */
add_action( 'bwf_after_action_scheduler_load', [ $this, 'bwf_after_action_scheduler_load' ] );
}
/**
* @return WooFunnels_AS_DS instance
*/
public static function get_instance() {
if ( null === self::$ins ) {
self::$ins = new self();
}
return self::$ins;
}
/**
* Load files
*/
public function load_files() {
foreach ( glob( $this->dir . '/db/class-*.php' ) as $file_name ) {
require_once( $file_name );
}
foreach ( glob( $this->dir . '/asct/class-*.php' ) as $file_name ) {
if ( false !== strpos( $file_name, '-cli.php' ) ) {
/** Will load CLI when need to run */
continue;
}
require_once( $file_name );
}
/** Loading WooFunnels Actions CLI */
if ( version_compare( PHP_VERSION, '5.3', '>' ) ) {
$this->load_cli();
}
do_action( 'bwf_after_action_scheduler_load' );
}
/**
* Load CLI file
*/
public function load_cli() {
/** Not including files if Action Scheduler doesn't exist */
if ( ! class_exists( 'ActionScheduler' ) ) {
return;
}
if ( defined( 'WP_CLI' ) && WP_CLI ) {
require_once $this->dir . '/asct/class-bwf-as-cli.php';
WP_CLI::add_command( 'woofunnels-actions', 'BWF_AS_CLI' );
}
}
/**
* Load Hooks after Action Scheduler is loaded
*/
public function bwf_after_action_scheduler_load() {
/** Create action scheduler custom tables */
add_filter( 'bwf_add_db_table_schema', [ $this, 'create_db_tables' ], 10, 2 );
/** Un-schedule older WP cron event */
add_action( 'admin_init', [ $this, 'maybe_set_bwf_ct_worker' ], 9 );
/** Registering custom schedule */
add_filter( 'cron_schedules', [ $this, 'add_cron_schedule' ] );
}
/**
* Create DB tables
* Actions and Action_Claim
*/
public function create_db_tables( $args, $tables ) {
$max_index_length = 191;
if ( $tables['version'] !== BWF_DB_VERSION || ! in_array( 'bwf_actions', $tables['tables'], true ) ) {
$args[] = [
'name' => 'bwf_actions',
'schema' => "CREATE TABLE `{table_prefix}bwf_actions` (
id bigint(20) unsigned NOT NULL auto_increment,
c_date datetime NOT NULL default '0000-00-00 00:00:00',
e_time int(12) NOT NULL default 0,
hook varchar(255) not null,
args longtext null,
status int(1) not null default 0 COMMENT '0 - Pending | 1 - Running',
recurring_interval int(10) not null default 0,
group_slug varchar(255) not null default 'woofunnels',
claim_id bigint(20) unsigned NOT NULL default 0,
PRIMARY KEY (id),
KEY id (id),
KEY e_time (e_time),
KEY hook (hook($max_index_length)),
KEY status (status),
KEY group_slug (group_slug($max_index_length)),
KEY claim_id (claim_id)
) {table_collate};",
];
}
if ( $tables['version'] !== BWF_DB_VERSION || ! in_array( 'bwf_action_claim', $tables['tables'], true ) ) {
$args[] = [
'name' => 'bwf_action_claim',
'schema' => "CREATE TABLE `{table_prefix}bwf_action_claim` (
id bigint(20) unsigned NOT NULL auto_increment,
date datetime NOT NULL default '0000-00-00 00:00:00',
PRIMARY KEY (id),
KEY date (date)
) {table_collate};",
];
}
return $args;
}
public function maybe_set_bwf_ct_worker() {
$hook = 'bwf_as_ct_1min_worker';
if ( wp_next_scheduled( $hook ) ) {
$timestamp = wp_next_scheduled( $hook );
wp_unschedule_event( $timestamp, $hook );
}
}
public function add_cron_schedule( $schedules ) {
$schedules['bwf_every_minute'] = apply_filters( 'bwf_every_minute_cron', array(
'interval' => MINUTE_IN_SECONDS,
'display' => __( 'Every minute', 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
) );
return $schedules;
}
/**
* 1 min worker callback
*/
public function run_as_ct_worker() {
$url = rest_url( '/woofunnels/v1/worker' ) . '?' . time();
$args = bwf_get_remote_rest_args( [], 'GET' );
wp_remote_post( $url, $args );
}
/**
* Register WooFunnels Core WP endpoints
*/
public function register_endpoints() {
register_rest_route( 'woofunnels/v1', '/worker', array(
'methods' => WP_REST_Server::READABLE,
'callback' => array( $this, 'rest_worker_callback' ),
'permission_callback' => '__return_true',
) );
}
/**
* action_scheduler_pre_init action hook
*/
public function as_pre_init_cb() {
$is_worker_request = false;
if ( isset( $_GET['rest_route'] ) && false !== strpos( bwf_clean( $_GET['rest_route'] ), '/woofunnels/v1/worker' ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
$is_worker_request = true;
} else if ( isset( $_SERVER['REQUEST_URI'] ) && false !== strpos( bwf_clean( $_SERVER['REQUEST_URI'] ), '/woofunnels/v1/worker' ) ) {
$is_worker_request = true;
}
if ( false === $is_worker_request ) {
return;
}
if ( ! class_exists( 'BWF_AS' ) ) {
return;
}
/** BWF_AS instance */
$as_ct_ins = BWF_AS::instance();
/** Set new AS CT data store */
$as_ct_ins->change_data_store();
/** Set unique key */
self::$unique = time();
}
/**
* action_scheduler_pre_init action hook for autonami cli
*/
public function as_pre_init_cli_cb() {
global $argv;
if ( ! defined( 'WP_CLI' ) || ! WP_CLI ) {
return;
}
/**
* $argv holds arguments passed to script
* https://www.php.net/manual/en/reserved.variables.argv.php
*/
if ( ! is_array( $argv ) || 0 === count( $argv ) ) {
WP_CLI::log( 'WooFunnels WP CLI arguments not found.' );
return;
}
if ( ! isset( $argv[1] ) || 'woofunnels-actions' !== $argv[1] ) {
return;
}
if ( ! isset( $argv[2] ) || 'run' !== $argv[2] ) {
return;
}
if ( ! class_exists( 'BWF_AS' ) ) {
WP_CLI::log( "BWF_AS class not found." );
}
/** BWF_AS instance */
$as_ct_ins = BWF_AS::instance();
/** Set new AS CT data store */
$as_ct_ins->change_data_store();
}
/**
* Callback function for running WooFunnels actions
*
* @param WP_REST_Request $request
*/
public function rest_worker_callback( WP_REST_Request $request ) {
/** Update execution time */
if ( function_exists( 'bwf_options_update' ) ) {
bwf_options_update( 'fk_core_worker_let', time() );
}
$this->worker_as_run();
$resp['msg'] = 'success';
$resp['time'] = date_i18n( 'Y-m-d H:i:s' );
$resp['datastore'] = get_class( ActionScheduler_Store::instance() );
$path = filter_input( INPUT_GET, 'path' );
if ( ! empty( $path ) && 1 === intval( $path ) ) {
$obj = new ReflectionClass( 'ActionScheduler_QueueRunner' );
$resp['as-path'] = $obj->getFileName();
$obj = new ReflectionClass( 'BWF_Logger' );
$resp['core-path'] = $obj->getFileName();
}
/** Logs */
if ( ( defined( 'BWF_CHECK_CRON_SCHEDULE' ) && true === BWF_CHECK_CRON_SCHEDULE ) || true === apply_filters( 'bwf_check_cron_schedule_logging', false ) ) {
add_filter( 'bwf_logs_allowed', '__return_true', PHP_INT_MAX );
$logger_obj = BWF_Logger::get_instance();
$logger_obj->log( $resp['time'], 'fka-cron-check', 'autonami' );
}
wp_send_json( $resp );
}
/**
* Helper method to run action scheduler
*/
public function worker_as_run() {
if ( ! class_exists( 'ActionScheduler_QueueRunner' ) ) {
return;
}
/** Modify Action Scheduler filters */
$this->modify_as_filters();;
$as_ins = ActionScheduler_QueueRunner::instance();
/** Run Action Scheduler worker */
$as_ins->run();
}
public function modify_as_filters() {
/** Remove all existing filters */
remove_all_filters( 'action_scheduler_queue_runner_time_limit' );
remove_all_filters( 'action_scheduler_queue_runner_batch_size' );
remove_all_filters( 'action_scheduler_queue_runner_concurrent_batches' );
remove_all_filters( 'action_scheduler_timeout_period' );
remove_all_filters( 'action_scheduler_cleanup_batch_size' );
remove_all_filters( 'action_scheduler_maximum_execution_time_likely_to_be_exceeded' );
remove_all_filters( 'action_scheduler_failure_period' );
/** Adding all filters for Autonami Action Scheduler only */
add_filter( 'action_scheduler_queue_runner_time_limit', function () {
return 20;
}, 998 );
add_filter( 'action_scheduler_queue_runner_batch_size', function () {
return 20;
}, 998 );
add_filter( 'action_scheduler_queue_runner_concurrent_batches', function () {
return 5;
}, 998 );
add_filter( 'action_scheduler_timeout_period', function () {
return 300;
}, 998 );
add_filter( 'action_scheduler_cleanup_batch_size', function () {
return 20;
}, 998 );
add_filter( 'action_scheduler_maximum_execution_time_likely_to_be_exceeded', function ( $val, $ins, $processed_actions, $execution_time, $max_execution_time ) {
return ( $execution_time > $max_execution_time );
}, 998, 5 );
add_filter( 'action_scheduler_failure_period', function () {
return 180;
}, 999 );
}
/**
* Deprecated
* Since v1.9.82
*/
public function fallback_execution_on_heartbeat() {
/**
* Added the filter so that we can keep this heartbeat off by default and any plugin from our family can hook into it
*/
if ( ( true === apply_filters( 'bwf_as_ds_should_register_heartbeat', false ) ) || class_exists( 'BWFAN_Core' ) ) {
add_action( 'heartbeat_tick', [ $this, 'heartbeat_callback' ] );
}
}
public function heartbeat_callback() {
$save_time = get_option( 'bwf_heartbeat_run', time() );
if ( time() < $save_time ) {
return;
}
$url = rest_url( '/woofunnels/v1/worker' ) . '?' . time();
$args = bwf_get_remote_rest_args( [], 'GET' );
wp_remote_post( $url, $args );
update_option( 'bwf_heartbeat_run', ( time() + 60 ) );
}
}
WooFunnels_AS_DS::get_instance();
}
/**
* Schedule single action
*
* @param $timestamp
* @param $hook
* @param array $args
* @param string $group
*
* @return bool|int
*/
function bwf_schedule_single_action( $timestamp, $hook, $args = array(), $group = '' ) {
if ( ! class_exists( 'BWF_AS_Actions_Crud' ) ) {
_doing_it_wrong( __FUNCTION__, __( 'Method is called before plugins_loaded hook.', 'woofunnels' ), BWF_VERSION ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.I18n.TextDomainMismatch
return false;
}
if ( ! class_exists( 'ActionScheduler' ) ) {
_doing_it_wrong( __FUNCTION__, __( 'Action Scheduler class not found.', 'woofunnels' ), BWF_VERSION ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.I18n.TextDomainMismatch
return false;
}
if ( empty( $hook ) ) {
_doing_it_wrong( __FUNCTION__, __( 'Hook is a required entity.', 'woofunnels' ), BWF_VERSION ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.I18n.TextDomainMismatch
return false;
}
$data = array(
'c_date' => current_time( 'mysql', 1 ),
'e_time' => (int) $timestamp,
'hook' => $hook,
'claim_id' => 0
);
if ( is_array( $args ) && count( $args ) > 0 ) {
$data['args'] = wp_json_encode( $args );
}
if ( ! empty( $group ) ) {
$data['group_slug'] = $group;
}
BWF_AS_Actions_Crud::insert( $data );
$inserted_id = BWF_AS_Actions_Crud::insert_id();
return $inserted_id;
}
/**
* Schedule recurring action
*
* @param $timestamp
* @param int $interval_in_seconds - should be min 1 otherwise not recurring
* @param $hook
* @param array $args
* @param string $group
*
* @return bool|int
*/
function bwf_schedule_recurring_action( $timestamp, $interval_in_seconds, $hook, $args = array(), $group = '' ) {
if ( ! class_exists( 'BWF_AS_Actions_Crud' ) ) {
_doing_it_wrong( __FUNCTION__, __( 'Method is called before plugins_loaded hook.', 'woofunnels' ), BWF_VERSION ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.I18n.TextDomainMismatch
return false;
}
if ( ! class_exists( 'ActionScheduler' ) ) {
_doing_it_wrong( __FUNCTION__, __( 'Action Scheduler class not found.', 'woofunnels' ), BWF_VERSION ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.I18n.TextDomainMismatch
return false;
}
if ( empty( $hook ) ) {
_doing_it_wrong( __FUNCTION__, __( 'Hook is a required entity.', 'woofunnels' ), BWF_VERSION ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.I18n.TextDomainMismatch
return false;
}
$recurring_interval = ( (int) $interval_in_seconds > 0 ) ? (int) $interval_in_seconds : 0;
$data = array(
'c_date' => current_time( 'mysql', 1 ),
'e_time' => (int) $timestamp,
'hook' => $hook,
'recurring_interval' => $recurring_interval,
'claim_id' => 0
);
if ( is_array( $args ) && count( $args ) > 0 ) {
$data['args'] = wp_json_encode( $args );
}
if ( ! empty( $group ) ) {
$data['group_slug'] = $group;
}
BWF_AS_Actions_Crud::insert( $data );
$inserted_id = BWF_AS_Actions_Crud::insert_id();
return $inserted_id;
}
/**
* Unschedule actions based on given hook or args or group
*
* @param $hook
* @param array $args
* @param string $group
*
* @return bool
*/
function bwf_unschedule_actions( $hook, $args = array(), $group = '' ) {
if ( ! class_exists( 'BWF_AS_Actions_Crud' ) ) {
_doing_it_wrong( __FUNCTION__, __( 'Method is called before plugins_loaded hook.', 'woofunnels' ), BWF_VERSION ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.I18n.TextDomainMismatch
return false;
}
if ( empty( $hook ) ) {
_doing_it_wrong( __FUNCTION__, __( 'Hook is a required entity.', 'woofunnels' ), BWF_VERSION ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.I18n.TextDomainMismatch
return false;
}
$arr = array(
'hook' => $hook,
);
if ( is_array( $args ) && count( $args ) > 0 ) {
$arr['args'] = $args;
}
if ( ! empty( $group ) ) {
$arr['group_slug'] = $group;
}
$action_ids = BWF_AS_Actions_Crud::find_actions( $arr );
if ( false === $action_ids ) {
_doing_it_wrong( __FUNCTION__, __( 'No actions found for data: ', 'woofunnels' ) . print_r( $arr, true ), BWF_VERSION ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.I18n.TextDomainMismatch
}
BWF_AS_Actions_Crud::delete_actions( $action_ids );
return true;
}
/**
* Check if action is already scheduled based on given hook or args or group
*
* @param $hook
* @param array $args
* @param string $group
*
* @return bool
*/
function bwf_has_action_scheduled( $hook, $args = array(), $group = '' ) {
if ( empty( $hook ) ) {
_doing_it_wrong( __FUNCTION__, __( 'Hook is a required entity.', 'woofunnels' ), BWF_VERSION ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.I18n.TextDomainMismatch
return false;
}
global $wpdb;
$table = $wpdb->prefix . 'bwf_actions';
$sql = "SELECT `id` FROM $table WHERE `hook` LIKE %s";
$sql_params = [];
$sql_params[] = trim( $hook );
if ( is_array( $args ) && count( $args ) > 0 ) {
$sql .= ' AND `args` LIKE %s';
$sql_params[] = wp_json_encode( $args );
}
if ( ! empty( trim( $group ) ) ) {
$sql .= ' AND `group_slug` LIKE %s';
$sql_params[] = trim( $group );
}
$sql .= ' LIMIT 0,1';
$sql = $wpdb->prepare( $sql, $sql_params ); //phpcs:ignore WordPress.DB.PreparedSQL
$action_ids = $wpdb->get_var( $sql ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
return ( intval( $action_ids ) > 0 );
}
/**
* Check if action is running based on given hook or args or group
*
* @param $hook
* @param array $args
* @param string $group
*
* @return bool
*/
function bwf_is_action_running( $hook, $args = array(), $group = '' ) {
if ( ! class_exists( 'BWF_AS_Actions_Crud' ) ) {
_doing_it_wrong( __FUNCTION__, __( 'Method is called before plugins_loaded hook.', 'woofunnels' ), BWF_VERSION ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.I18n.TextDomainMismatch
return false;
}
if ( empty( $hook ) ) {
_doing_it_wrong( __FUNCTION__, __( 'Hook is a required entity.', 'woofunnels' ), BWF_VERSION ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.I18n.TextDomainMismatch
return false;
}
$arr = array(
'hook' => $hook,
);
if ( is_array( $args ) && count( $args ) > 0 ) {
$arr['args'] = $args;
}
if ( ! empty( $group ) ) {
$arr['group_slug'] = $group;
}
$arr['status'] = 1;
$action_ids = BWF_AS_Actions_Crud::find_actions( $arr );
if ( false === $action_ids ) {
return false;
}
return $action_ids;
}
/**
* Delete action by action id
*
* @param array $action_ids
*
* @return bool|int
*/
function bwf_delete_action( $action_ids = [] ) {
if ( ! class_exists( 'BWF_AS_Actions_Crud' ) ) {
_doing_it_wrong( __FUNCTION__, __( 'Method is called before plugins_loaded hook.', 'woofunnels' ), BWF_VERSION ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.I18n.TextDomainMismatch
return false;
}
if ( empty( $action_ids ) ) {
_doing_it_wrong( __FUNCTION__, __( 'Action ID is required.', 'woofunnels' ), BWF_VERSION ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.I18n.TextDomainMismatch
return false;
}
$delete_count = BWF_AS_Actions_Crud::delete_actions( $action_ids );
if ( false === $action_ids ) {
return false;
}
return $delete_count;
}
/**
* Get scheduled actions count based on given hook or args or group
*
* @param $hook
* @param array $args
* @param string $group
* @param string $status
* @param string $recurring
*
* @return bool|int
*/
function bwf_scheduled_action_count( $hook, $args = array(), $group = '', $status = '0', $recurring = 'all' ) {
if ( ! class_exists( 'BWF_AS_Actions_Crud' ) ) {
_doing_it_wrong( __FUNCTION__, __( 'Method is called before plugins_loaded hook.', 'woofunnels' ), BWF_VERSION ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.I18n.TextDomainMismatch
return false;
}
if ( empty( $hook ) ) {
_doing_it_wrong( __FUNCTION__, __( 'Hook is a required entity.', 'woofunnels' ), BWF_VERSION ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.I18n.TextDomainMismatch
return false;
}
$arr = array(
'hook' => $hook,
);
if ( is_array( $args ) && count( $args ) > 0 ) {
$arr['args'] = $args;
}
if ( ! empty( $group ) ) {
$arr['group_slug'] = $group;
}
if ( '' !== $status ) {
$arr['status'] = $status;
}
if ( 'recurring' === $recurring ) {
$arr['recurring_interval'] = '0';
}
$action_ids = BWF_AS_Actions_Crud::find_actions( $arr );
if ( false === $action_ids ) {
return false;
}
return count( $action_ids );
}
/**
* Delete recurring action
*
* @param $hook
* @param $status
* @param $exclude_id
*
* @return void
*/
function bwf_delete_scheduled_recurring_action( $hook, $status, $exclude_id = '' ) {
if ( empty( $hook ) ) {
return;
}
global $wpdb;
$query = "DELETE FROM {$wpdb->prefix}bwf_actions WHERE `hook`=%s AND `status` = %d";
$args = [ $hook, $status ];
if ( ! empty( $exclude_id ) ) {
$query .= " AND `id` != %d";
$args[] = $exclude_id;
}
$query = $wpdb->prepare( $query, $args );
$wpdb->query( $query ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
}

View File

@@ -0,0 +1,183 @@
<?php
if ( ! class_exists( 'BWF_AS_Actions_Crud' ) ) {
#[AllowDynamicProperties]
class BWF_AS_Actions_Crud {
public static $primary_key = 'id';
/**
* Return single action data
*
* @param $action_id
* @param string $return_vars
*
* @return stdClass
*/
public static function get_single_action( $action_id, $return_vars = '*' ) {
global $wpdb;
$table = self::_table();
$p_key = self::$primary_key;
$sql = "SELECT {$return_vars} FROM {$table} WHERE {$p_key}=%d";
$sql = $wpdb->prepare( $sql, $action_id ); //phpcs:ignore WordPress.DB.PreparedSQL
$status = $wpdb->get_results( $sql, ARRAY_A ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
$return = new stdClass();
if ( is_array( $status ) && count( $status ) > 0 && isset( $status[0] ) && is_array( $status[0] ) && count( $status[0] ) > 0 ) {
foreach ( $status[0] as $key => $value ) {
$value = maybe_unserialize( $value );
if ( true === self::is_json( $value ) ) {
$value = json_decode( $value, ARRAY_A );
}
$return->$key = $value;
}
}
return $return;
}
public static function _table() {
global $wpdb;
$table_name = strtolower( 'BWF_Actions' );
return $wpdb->prefix . $table_name;
}
public static function is_json( $string ) {
if ( empty( $string ) ) {
return false;
}
json_decode( $string );
return ( json_last_error() == JSON_ERROR_NONE );
}
public static function get_executable_actions( $status, $group ) {
}
/**
* Find actions based on column inputs
*
* @param $args
*
* @return array|bool
*/
public static function find_actions( $args ) {
global $wpdb;
$table = self::_table();
$p_key = self::$primary_key;
$sql = "SELECT `{$p_key}` FROM $table WHERE 1=1";
$sql_params = [];
if ( isset( $args['hook'] ) && ! empty( trim( $args['hook'] ) ) ) {
$sql .= ' AND `hook` LIKE %s';
$sql_params[] = trim( $args['hook'] );
}
if ( isset( $args['args'] ) && is_array( $args['args'] ) && count( $args['args'] ) > 0 ) {
$sql .= ' AND `args` LIKE %s';
$sql_params[] = wp_json_encode( $args['args'] );
}
if ( isset( $args['group_slug'] ) && ! empty( trim( $args['group_slug'] ) ) ) {
$sql .= ' AND `group_slug` LIKE %s';
$sql_params[] = trim( $args['group_slug'] );
}
if ( isset( $args['status'] ) && '' !== $args['status'] ) {
$sql .= ' AND `status` LIKE %d';
$sql_params[] = $args['status'];
}
/** Always != hard */
if ( isset( $args['recurring_interval'] ) && '' !== $args['recurring_interval'] ) {
$sql .= ' AND `recurring_interval` != %d';
$sql_params[] = $args['recurring_interval'];
}
$sql = $wpdb->prepare( $sql, $sql_params ); //phpcs:ignore WordPress.DB.PreparedSQL
$action_ids = $wpdb->get_results( $sql, ARRAY_A ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
if ( is_array( $action_ids ) && count( $action_ids ) > 0 ) {
$action_ids = array_column( $action_ids, 'id' );
return $action_ids;
}
return false;
}
public static function get_action_status( $action_id ) {
global $wpdb;
$table = self::_table();
$p_key = self::$primary_key;
$sql = "SELECT `status` FROM {$table} WHERE {$p_key}=%d";
$sql = $wpdb->prepare( $sql, $action_id ); //phpcs:ignore WordPress.DB.PreparedSQL
$status = $wpdb->get_var( $sql ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
return $status;
}
public static function insert( $data ) {
global $wpdb;
$wpdb->insert( self::_table(), $data ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
}
public static function delete( $value ) {
global $wpdb;
if ( empty( $value ) ) {
return;
}
$resp = $wpdb->delete( self::_table(), array( static::$primary_key => $value ), array( '%d' ) ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
return $resp;
}
public static function delete_actions( $action_ids ) {
global $wpdb;
$table = self::_table();
$p_key = self::$primary_key;
if ( ! is_array( $action_ids ) || 0 === count( $action_ids ) ) {
BWFAN_Core()->logger->log( 'no action ids to delete, blank array passed', 'sync' );
return false;
}
$type = array_fill( 0, count( $action_ids ), '%d' );
$format = implode( ', ', $type );
$query = "DELETE FROM {$table} WHERE {$p_key} IN ({$format})";
$sql = $wpdb->prepare( $query, $action_ids ); //phpcs:ignore WordPress.DB.PreparedSQL
$rows_affected = $wpdb->query( $sql ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
return $rows_affected;
}
public static function query( $query ) {
global $wpdb;
$query = str_replace( '{table_name}', self::_table(), $query );
$results = $wpdb->query( $query ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
return $results;
}
public static function insert_id() {
global $wpdb;
return $wpdb->insert_id;
}
public static function get_results( $query ) {
global $wpdb;
$query = str_replace( '{table_name}', self::_table(), $query );
$results = $wpdb->get_results( $query, ARRAY_A ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
return $results;
}
}
}

View File

@@ -0,0 +1,2 @@
<?php
// Silence is golden.

View File

@@ -0,0 +1,371 @@
/*general setting*/
.bwf-funnel-common .bwf_menu_list_primary ul li a {
color: #6f6f6f;
font-size: 14px;
padding: 15px 24px;
}
.bwf-widget-tabs .bwf-tab-title, .bwf_setting_inner .vue-form-generator fieldset legend {
line-height: 1.4;
color: #444;
}
.bwf-widget-tabs .bwf-tab-title {
font-size: 15px;
}
.bwf_setting_inner .vue-form-generator fieldset legend {
font-size: 20px;
}
.bwf_setting_inner .vue-form-generator fieldset .form-group > label {
font-size: 14px;
line-height: 1.5;
}
.bwf_setting_inner .vue-form-generator fieldset .form-group > label span, .bwf_setting_inner .vue-form-generator fieldset .field-wrap > input {
margin-left: 0 !important;
}
.bwf_setting_inner .vue-form-generator fieldset .hint {
font-size: 11px;
line-height: 19px;
}
.bwf_setting_inner .vue-form-generator {
background: none;
border: none;
padding: 0;
}
.bwf-funnel-common .bwf_menu_list_primary {
margin: 20px 0;
}
.bwf_setting_inner .form-group.field-input input[type="text"],
.bwf_setting_inner .form-group.field-input input[type="email"],
.bwf_setting_inner .form-group.field-input input[type="password"],
.bwf_setting_inner .form-group.field-input input[type="url"],
.bwf_setting_inner .form-group.field-input input[type="tel"],
.bwf_setting_inner .form-group.field-input input[type="number"],
.bwf_setting_inner textarea {
width: 100%;
max-width: 100%;
height: auto;
font-size: 14px;
line-height: 1.42857143;
padding: 6px 12px;
margin: 0;
display: block;
color: #444;
background-color: #fff;
border: 1px solid #d5d5d5;
box-shadow: none;
border-radius: 0;
-moz-border-radius: 0;
-webkit-border-radius: 0;
-moz-border-radius: 0;
}
.bwf_setting_inner textarea {
height: 200px;
}
.bwf_save_btn_style {
min-width: 84px;
position: relative;
text-align: center;
padding: 0 24px;
border-radius: 6px;
font-size: 13px;
font-size: .8125rem;
min-height: 36px;
box-shadow: none;
text-decoration: none;
display: inline-flex;
text-align: center;
align-items: center;
justify-content: center;
cursor: pointer;
border: 1px solid #0073aa;
color: #fff;
background: #0073aa;
white-space: nowrap;
}
.bwf_save_btn_style:hover, .bwf_save_btn_style:focus {
background-color: #135e96;
}
.bwf-tabs-view-vertical.bwf-widget-tabs {
float: left;
width: 100%;
display: flex;
}
.bwf-widget-tabs.bwf-tabs-view-vertical .bwf-tabs-wrapper {
width: 260px;
position: relative;
-webkit-flex-shrink: 0;
-ms-flex-negative: 0;
flex-shrink: 0;
float: left;
margin-right: 20px;
border-radius: 8px;
padding: 15px 10px;
background: #fff;
border: 1px solid #dedfea;
}
.bwf-widget-tabs .bwf-tab-title {
float: left;
width: 100%;
font-weight: 400;
position: relative;
padding: 18px 18px 17px;
cursor: pointer;
box-sizing: border-box;
}
.bwf-widget-tabs .bwf-tab-title.bwf-active {
background: #f0faff;
border-radius: 8px;
-moz-border-radius: 8px;
-webkit-border-radius: 8px;
color: #0073aa;
cursor: default;
}
.bwf-widget-tabs .bwf-tab-title.bwf-active:after {
content: "";
font-family: dashicons;
float: right;
color: #009fea;
}
.bwf-widget-tabs.bwf-tabs-view-vertical .bwf-tabs-content-wrapper {
width: calc(100% - 260px);
float: left;
background: #fff;
min-height: 240px;
padding: 35px 30px;
position: relative;
border-radius: 8px;
border: 1px solid #dedfea;
}
.bwf_setting_inner .bwf_forms_wrap {
margin-bottom: 20px;
}
.bwf_setting_inner fieldset {
border: 0;
padding: 0;
margin: 0;
}
.bwf_setting_inner .vue-form-generator fieldset legend {
font-weight: bold;
padding: 0 0 15px 10px;
font-size: 20px;
color: #444;
}
.bwf_setting_inner .form-group {
padding: 1em;
margin-bottom: 10px;
}
.bwf_setting_inner .form-group:before, .bwf_setting_inner .form-group:after {
content: "";
clear: both;
display: block;
}
.bwf_setting_inner .vue-form-generator fieldset .form-group > label {
width: 200px;
float: left;
margin-bottom: 0;
box-sizing: border-box;
}
.bwf_setting_inner .vue-form-generator fieldset .field-wrap, .bwf_setting_inner .vue-form-generator fieldset .form-group .hint, .wffn_funnel_setting .form-group .hint {
width: 100%;
float: none;
padding-left: 201px;
display: block;
box-sizing: border-box;
}
.bwf_setting_inner .vue-form-generator fieldset .hint {
margin: 0;
font-weight: 400;
clear: both;
}
.bwf_setting_inner .vue-form-generator fieldset .bwf_gsettings_sec_head {
border-bottom: 1px solid #ddd;
}
.bwf_setting_inner .vue-form-generator fieldset .form-group.bwf_gsettings_sec_head > label {
width: 100%;
font-weight: 600;
}
.bwf-tabs-view-vertical .bwf_setting_inner .bwf_form_button {
position: absolute;
left: -5px;
bottom: 20px;
float: none !important;
padding-left: 0;
margin: 0 !important;
}
#modal-general-settings_success.iziModal {
display: none;
position: fixed;
top: 0;
bottom: 0;
left: auto;
right: 0;
margin: auto;
background: #fff;
box-shadow: 0 0 8px rgba(0, 0, 0, .3);
transition: margin-top 0.3s ease, height 0.3s ease;
transform: translateZ(0);
}
#modal-general-settings_success.iziModal .iziModal-header {
height: auto;
padding: 10px 15px 12px 15px;
background: #f9fdff !important;
box-shadow: none;
border-bottom: 1px solid #eee;
overflow: hidden;
position: relative;
z-index: 10;
}
#modal-general-settings_success.iziModal .iziModal-header-icon {
font-size: 23px;
float: left;
padding: 0 15px 0 0;
margin: 0;
color: rgba(255, 255, 255, 0.5);
}
#modal-general-settings_success.iziModal .iziModal-progressbar {
position: absolute;
left: 0;
top: 0px;
width: 100%;
z-index: 1;
}
#modal-general-settings_success.iziModal .iziModal-progressbar > div {
height: 2px;
width: 100%;
}
#modal-general-settings_success h2.iziModal-header-title {
font-size: 15px !important;
line-height: 1.4;
margin: 3px 0 0 0;
color: #000;
font-weight: 400 !important;
}
#modal-general-settings_success.iziModal .iziModal-header-buttons {
position: absolute;
top: 50%;
right: 14px !important;
margin: -16px 0 0 0;
}
@media (min-width: 1400px) {
.bwf_setting_inner textarea {
width: 600px;
height: 200px;
}
.bwf_setting_inner .form-group.field-input input[type="text"], .bwf_setting_inner .form-group.field-input input[type="email"], .bwf_setting_inner .form-group.field-input input[type="password"], .bwf_setting_inner .form-group.field-input input[type="url"], .bwf_setting_inner .form-group.field-input input[type="tel"], .bwf_setting_inner .form-group.field-input input[type="number"] {
width: 25em;
}
}
.bwf-funnel-common .error, .bwf-funnel-common .notice, .bwf-funnel-common .updated {
display: none;
}
.form-group.valid.wfacp_setting_track_and_events_start.field-label {
width: 200px;
float: left;
box-sizing: border-box;
}
.form-group.bwf_wrap_custom_html_tracking_general > label {
padding-top: 0 !important;
padding-bottom: 0 !important;
}
.form-group.bwf_wrap_custom_html_tracking_general {
margin-bottom: 0px;
}
.form-group.valid.wfacp_checkbox_wrap.wfacp_setting_track_and_events_end.field-checkbox,.form-group.valid.wfacp_checkbox_wrap.wfacp_setting_track_and_events_end.field-checklist {
width: 545px;
display: inline-block;
clear: both;
}
.bwf_setting_inner .vue-form-generator fieldset .form-group.valid.wfacp_checkbox_wrap.wfacp_setting_track_and_events_end.field-checkbox .field-wrap,
.bwf_setting_inner .vue-form-generator fieldset .form-group.valid.wfacp_checkbox_wrap.wfacp_setting_track_and_events_end.field-checklist .field-wrap, .bwf_setting_inner .vue-form-generator fieldset .form-group.rem_hint_pad .hint{
padding-left: 0px;
}
.bwf_setting_inner .vue-form-generator fieldset .listbox.form-control {
padding: 0 !important;
border: none !important;
border-radius: unset !important;
box-shadow: none !important;
overflow: unset !important;
max-height: unset !important;
}
.bwf-vue-custom-msg {
margin: 5px 0 15px;
border: 1px solid #ccd0d4;
display: block !important;
border-left-color: #dc3232;
background: #fff;
border-left-width: 4px;
box-shadow: 0 1px 1px rgba(0, 0, 0, .04);
padding: 1px 12px;
}
.bwf-vue-custom-msg p {
margin: 0.5em 0;
padding: 2px;
}
.bwf-vue-custom-msg a {
text-decoration: underline;
}
.bwf-hide {
display:none;
}
.bwf-hide.bwf-show {
display: block;
clear: both;
}
.bwf_setting_inner .vue-form-generator fieldset .form-group.bwf_vue_checkbox_label > label,
.bwf_setting_inner .vue-form-generator fieldset .form-group.bwf_vue_checkbox_label > .field-wrap {
padding-left: 201px;
width: fit-content;
float: none;
display: inline-block;
}
.bwf_setting_inner .vue-form-generator fieldset .form-group.bwf_vue_checkbox_label > label{
padding-left: 0px;
}
.bwf_setting_inner .vue-form-generator fieldset .form-group.bwf_vue_checkbox_label > .field-wrap{
float: left;
}

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 233.1 147.2" style="enable-background:new 0 0 233.1 147.2;" xml:space="preserve">
<style type="text/css">
.st0{fill:#F0F5FA;}
</style>
<polygon class="st0" points="232,3.8 150.4,143.1 117.9,143.1 198.9,3.8 "/>
<polygon class="st0" points="167.4,3.8 86.8,143.1 5.2,3.8 102.8,3.8 88.2,32.4 86.3,32.4 54.7,32.4 86.3,88.2 134.4,3.8 "/>
</svg>

After

Width:  |  Height:  |  Size: 625 B

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 231 141" style="enable-background:new 0 0 231 141;" xml:space="preserve">
<style type="text/css">
.st0{fill:#1DAAFC;}
.st1{fill:#070045;}
</style>
<polygon class="st0" points="229.3,2.3 147.7,141.6 115.2,141.6 196.3,2.3 "/>
<polygon class="st1" points="164.7,2.3 84.1,141.6 2.6,2.3 100.2,2.3 85.6,30.9 83.7,30.9 52.1,30.9 83.7,86.8 131.7,2.3 "/>
</svg>

After

Width:  |  Height:  |  Size: 641 B

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 233.1 147.2" style="enable-background:new 0 0 233.1 147.2;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;}
</style>
<polygon class="st0" points="232,3.8 150.4,143.1 117.9,143.1 198.9,3.8 "/>
<polygon class="st0" points="167.4,3.8 86.8,143.1 5.2,3.8 102.8,3.8 88.2,32.4 86.3,32.4 54.7,32.4 86.3,88.2 134.4,3.8 "/>
</svg>

After

Width:  |  Height:  |  Size: 625 B

View File

@@ -0,0 +1 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 818.38 141.48"><defs><style>.cls-1{fill:#131144;}.cls-2{fill:#1daafc;}</style></defs><polygon class="cls-1" points="99.25 0 0 0.19 82.76 141.48 164.97 0.06 131.34 0 82.48 86.01 50.35 29.09 84.46 29.09 99.25 0"/><polygon class="cls-2" points="230.55 0 197.18 0 114.71 141.39 147.96 141.39 230.55 0"/><path class="cls-1" d="M381.72,584.09a2.82,2.82,0,0,1-2.16-.9,3,3,0,0,1-.84-2.1v-78a2.88,2.88,0,0,1,3-3h55.2a2.88,2.88,0,0,1,3,3v12.12a2.88,2.88,0,0,1-3,3H399.84v17.63h34.68a2.8,2.8,0,0,1,2.16.91,3.11,3.11,0,0,1,.84,2.22v12a3,3,0,0,1-.84,2.11,2.85,2.85,0,0,1-2.16.89H399.84v27.12a3,3,0,0,1-.84,2.1,2.82,2.82,0,0,1-2.16.9Z" transform="translate(-129.37 -464.22)"/><path class="cls-1" d="M473.88,585.29a23.69,23.69,0,0,1-12.18-3.12,21.11,21.11,0,0,1-8.34-9.17,33.19,33.19,0,0,1-3-14.83V524.69a2.89,2.89,0,0,1,3-3h15a3.14,3.14,0,0,1,2.22.85,2.82,2.82,0,0,1,.9,2.15v32.77q0,11.76,10.44,11.75a10.39,10.39,0,0,0,7.86-3.06c2-2,2.94-4.93,2.94-8.69V524.69a2.89,2.89,0,0,1,3-3h15a2.89,2.89,0,0,1,3,3v56.4a3,3,0,0,1-.84,2.1,2.82,2.82,0,0,1-2.16.9H496.8a3.08,3.08,0,0,1-3-3v-4.55a19.69,19.69,0,0,1-8.1,6.54A29,29,0,0,1,473.88,585.29Z" transform="translate(-129.37 -464.22)"/><path class="cls-1" d="M530.88,584.09a2.81,2.81,0,0,1-2.16-.9,3,3,0,0,1-.84-2.1v-56.4a2.89,2.89,0,0,1,3-3h13.8a3.14,3.14,0,0,1,2.22.85,2.82,2.82,0,0,1,.9,2.15v4.57a23.66,23.66,0,0,1,8-6.24,26.27,26.27,0,0,1,11.88-2.52,24,24,0,0,1,12.3,3.11,21.75,21.75,0,0,1,8.4,9.12q3.06,6,3.06,14.88v33.48a3,3,0,0,1-.84,2.1,2.82,2.82,0,0,1-2.16.9H573.36a3.08,3.08,0,0,1-3-3V548.33c0-3.75-.9-6.66-2.7-8.69s-4.46-3.06-8-3.06a10.39,10.39,0,0,0-7.86,3.06c-2,2-2.94,4.94-2.94,8.69v32.76a3.08,3.08,0,0,1-3,3Z" transform="translate(-129.37 -464.22)"/><path class="cls-1" d="M608,584.09a2.81,2.81,0,0,1-2.16-.9,3,3,0,0,1-.84-2.1v-56.4a2.89,2.89,0,0,1,3-3h13.8a3.14,3.14,0,0,1,2.22.85,2.82,2.82,0,0,1,.9,2.15v4.57a23.66,23.66,0,0,1,8-6.24,26.27,26.27,0,0,1,11.88-2.52,24,24,0,0,1,12.3,3.11,21.81,21.81,0,0,1,8.4,9.12q3.06,6,3.06,14.88v33.48a3,3,0,0,1-.84,2.1,2.82,2.82,0,0,1-2.16.9H650.52a3.08,3.08,0,0,1-3-3V548.33c0-3.75-.9-6.66-2.7-8.69s-4.46-3.06-8-3.06a10.38,10.38,0,0,0-7.86,3.06c-2,2-2.94,4.94-2.94,8.69v32.76a2.86,2.86,0,0,1-.9,2.1,2.89,2.89,0,0,1-2.1.9Z" transform="translate(-129.37 -464.22)"/><path class="cls-1" d="M711,585.29q-14.16,0-22.56-7.68t-8.76-22.8v-4.2a34.87,34.87,0,0,1,4.26-16.26A25.86,25.86,0,0,1,694.73,524a34.9,34.9,0,0,1,16.14-3.54q10.56,0,17.46,4.19a26.78,26.78,0,0,1,10.38,11.41,37.32,37.32,0,0,1,3.48,16.44v2.88a2.88,2.88,0,0,1-3,3h-38.4v.83a18.89,18.89,0,0,0,1.26,6.36,10.22,10.22,0,0,0,3.36,4.56,8.72,8.72,0,0,0,5.46,1.68,9.24,9.24,0,0,0,4-.77,10.35,10.35,0,0,0,2.7-1.81,21.22,21.22,0,0,0,1.68-1.73,5.93,5.93,0,0,1,1.74-1.62,5.38,5.38,0,0,1,2.1-.31H738a2.81,2.81,0,0,1,2,.72,2.18,2.18,0,0,1,.66,1.92,10.51,10.51,0,0,1-2,4.92,24.8,24.8,0,0,1-5.58,5.71,30.8,30.8,0,0,1-9.18,4.62A41.78,41.78,0,0,1,711,585.29Zm-10.2-38.75h20.28v-.25a18,18,0,0,0-1.14-6.77,9.29,9.29,0,0,0-3.48-4.38,9.82,9.82,0,0,0-5.58-1.56,9.33,9.33,0,0,0-5.4,1.56,9.8,9.8,0,0,0-3.48,4.38,17.22,17.22,0,0,0-1.2,6.77Z" transform="translate(-129.37 -464.22)"/><path class="cls-1" d="M756.47,584.09a2.82,2.82,0,0,1-2.16-.9,3,3,0,0,1-.84-2.1V501.9a2.86,2.86,0,0,1,3-3h14.16a2.86,2.86,0,0,1,3,3v79.19a3,3,0,0,1-.84,2.1,2.82,2.82,0,0,1-2.16.9Z" transform="translate(-129.37 -464.22)"/><path class="cls-2" d="M792.11,584.09a2.82,2.82,0,0,1-2.16-.9,3,3,0,0,1-.84-2.1v-78a2.88,2.88,0,0,1,3-3h15.12a2.88,2.88,0,0,1,3,3v26.63l22.2-27.35a6,6,0,0,1,1.62-1.5,5.34,5.34,0,0,1,3.06-.78h17.28a2.35,2.35,0,0,1,1.8.78,2.5,2.5,0,0,1,.72,1.73,2.76,2.76,0,0,1-.36,1.45l-28.8,36.24,31,39.83a2,2,0,0,1,.48,1.45,2.48,2.48,0,0,1-.72,1.73,2.31,2.31,0,0,1-1.8.78H838.79a4.94,4.94,0,0,1-3.3-1,9.62,9.62,0,0,1-1.5-1.44l-23.76-29.64v29a3,3,0,0,1-.84,2.1,2.82,2.82,0,0,1-2.16.9Z" transform="translate(-129.37 -464.22)"/><path class="cls-2" d="M870.23,512.69a2.88,2.88,0,0,1-3-3V498.9a3,3,0,0,1,.84-2.1,2.79,2.79,0,0,1,2.16-.9h14.4a2.84,2.84,0,0,1,2.1.9,2.88,2.88,0,0,1,.9,2.1v10.79a2.79,2.79,0,0,1-.9,2.16,2.94,2.94,0,0,1-2.1.84Zm.12,71.4a2.82,2.82,0,0,1-2.16-.9,3,3,0,0,1-.84-2.1v-56.4a2.89,2.89,0,0,1,3-3h14.16a2.89,2.89,0,0,1,3,3v56.4a3,3,0,0,1-.84,2.1,2.82,2.82,0,0,1-2.16.9Z" transform="translate(-129.37 -464.22)"/><path class="cls-2" d="M933.59,584.09a32.53,32.53,0,0,1-13.26-2.46,18,18,0,0,1-8.58-7.67q-3-5.24-3-13.5v-23h-9.36a3.13,3.13,0,0,1-2.22-.84,2.82,2.82,0,0,1-.9-2.16v-9.73a2.82,2.82,0,0,1,.9-2.15,3.14,3.14,0,0,1,2.22-.85h9.36V501.9a2.86,2.86,0,0,1,.9-2.17,3,3,0,0,1,2.1-.83h13.92a2.86,2.86,0,0,1,3,3v19.79h15a3.14,3.14,0,0,1,2.22.85,2.82,2.82,0,0,1,.9,2.15v9.73a2.82,2.82,0,0,1-.9,2.16,3.13,3.13,0,0,1-2.22.84h-15v21.35a11.72,11.72,0,0,0,1.56,6.48c1,1.61,2.8,2.4,5.28,2.4h9.24a2.89,2.89,0,0,1,3,3v10.44a3,3,0,0,1-.84,2.1,2.82,2.82,0,0,1-2.16.9Z" transform="translate(-129.37 -464.22)"/></svg>

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="40" width="200" viewBox="0 0 850 150" data-name="Layer 1" id="Layer_1"><defs><style>.cls-1{fill:#131144;}.cls-2{fill:#1daafc;}</style></defs><polygon class="cls-1" points="99.25 0 0 0.19 82.76 141.48 164.97 0.06 131.34 0 82.48 86.01 50.35 29.09 84.46 29.09 99.25 0"/><polygon class="cls-2" points="230.55 0 197.18 0 114.71 141.39 147.96 141.39 230.55 0"/><path class="cls-1" d="M381.72,584.09a2.82,2.82,0,0,1-2.16-.9,3,3,0,0,1-.84-2.1v-78a2.88,2.88,0,0,1,3-3h55.2a2.88,2.88,0,0,1,3,3v12.12a2.88,2.88,0,0,1-3,3H399.84v17.63h34.68a2.8,2.8,0,0,1,2.16.91,3.11,3.11,0,0,1,.84,2.22v12a3,3,0,0,1-.84,2.11,2.85,2.85,0,0,1-2.16.89H399.84v27.12a3,3,0,0,1-.84,2.1,2.82,2.82,0,0,1-2.16.9Z" transform="translate(-129.37 -464.22)"/><path class="cls-1" d="M473.88,585.29a23.69,23.69,0,0,1-12.18-3.12,21.11,21.11,0,0,1-8.34-9.17,33.19,33.19,0,0,1-3-14.83V524.69a2.89,2.89,0,0,1,3-3h15a3.14,3.14,0,0,1,2.22.85,2.82,2.82,0,0,1,.9,2.15v32.77q0,11.76,10.44,11.75a10.39,10.39,0,0,0,7.86-3.06c2-2,2.94-4.93,2.94-8.69V524.69a2.89,2.89,0,0,1,3-3h15a2.89,2.89,0,0,1,3,3v56.4a3,3,0,0,1-.84,2.1,2.82,2.82,0,0,1-2.16.9H496.8a3.08,3.08,0,0,1-3-3v-4.55a19.69,19.69,0,0,1-8.1,6.54A29,29,0,0,1,473.88,585.29Z" transform="translate(-129.37 -464.22)"/><path class="cls-1" d="M530.88,584.09a2.81,2.81,0,0,1-2.16-.9,3,3,0,0,1-.84-2.1v-56.4a2.89,2.89,0,0,1,3-3h13.8a3.14,3.14,0,0,1,2.22.85,2.82,2.82,0,0,1,.9,2.15v4.57a23.66,23.66,0,0,1,8-6.24,26.27,26.27,0,0,1,11.88-2.52,24,24,0,0,1,12.3,3.11,21.75,21.75,0,0,1,8.4,9.12q3.06,6,3.06,14.88v33.48a3,3,0,0,1-.84,2.1,2.82,2.82,0,0,1-2.16.9H573.36a3.08,3.08,0,0,1-3-3V548.33c0-3.75-.9-6.66-2.7-8.69s-4.46-3.06-8-3.06a10.39,10.39,0,0,0-7.86,3.06c-2,2-2.94,4.94-2.94,8.69v32.76a3.08,3.08,0,0,1-3,3Z" transform="translate(-129.37 -464.22)"/><path class="cls-1" d="M608,584.09a2.81,2.81,0,0,1-2.16-.9,3,3,0,0,1-.84-2.1v-56.4a2.89,2.89,0,0,1,3-3h13.8a3.14,3.14,0,0,1,2.22.85,2.82,2.82,0,0,1,.9,2.15v4.57a23.66,23.66,0,0,1,8-6.24,26.27,26.27,0,0,1,11.88-2.52,24,24,0,0,1,12.3,3.11,21.81,21.81,0,0,1,8.4,9.12q3.06,6,3.06,14.88v33.48a3,3,0,0,1-.84,2.1,2.82,2.82,0,0,1-2.16.9H650.52a3.08,3.08,0,0,1-3-3V548.33c0-3.75-.9-6.66-2.7-8.69s-4.46-3.06-8-3.06a10.38,10.38,0,0,0-7.86,3.06c-2,2-2.94,4.94-2.94,8.69v32.76a2.86,2.86,0,0,1-.9,2.1,2.89,2.89,0,0,1-2.1.9Z" transform="translate(-129.37 -464.22)"/><path class="cls-1" d="M711,585.29q-14.16,0-22.56-7.68t-8.76-22.8v-4.2a34.87,34.87,0,0,1,4.26-16.26A25.86,25.86,0,0,1,694.73,524a34.9,34.9,0,0,1,16.14-3.54q10.56,0,17.46,4.19a26.78,26.78,0,0,1,10.38,11.41,37.32,37.32,0,0,1,3.48,16.44v2.88a2.88,2.88,0,0,1-3,3h-38.4v.83a18.89,18.89,0,0,0,1.26,6.36,10.22,10.22,0,0,0,3.36,4.56,8.72,8.72,0,0,0,5.46,1.68,9.24,9.24,0,0,0,4-.77,10.35,10.35,0,0,0,2.7-1.81,21.22,21.22,0,0,0,1.68-1.73,5.93,5.93,0,0,1,1.74-1.62,5.38,5.38,0,0,1,2.1-.31H738a2.81,2.81,0,0,1,2,.72,2.18,2.18,0,0,1,.66,1.92,10.51,10.51,0,0,1-2,4.92,24.8,24.8,0,0,1-5.58,5.71,30.8,30.8,0,0,1-9.18,4.62A41.78,41.78,0,0,1,711,585.29Zm-10.2-38.75h20.28v-.25a18,18,0,0,0-1.14-6.77,9.29,9.29,0,0,0-3.48-4.38,9.82,9.82,0,0,0-5.58-1.56,9.33,9.33,0,0,0-5.4,1.56,9.8,9.8,0,0,0-3.48,4.38,17.22,17.22,0,0,0-1.2,6.77Z" transform="translate(-129.37 -464.22)"/><path class="cls-1" d="M756.47,584.09a2.82,2.82,0,0,1-2.16-.9,3,3,0,0,1-.84-2.1V501.9a2.86,2.86,0,0,1,3-3h14.16a2.86,2.86,0,0,1,3,3v79.19a3,3,0,0,1-.84,2.1,2.82,2.82,0,0,1-2.16.9Z" transform="translate(-129.37 -464.22)"/><path class="cls-2" d="M792.11,584.09a2.82,2.82,0,0,1-2.16-.9,3,3,0,0,1-.84-2.1v-78a2.88,2.88,0,0,1,3-3h15.12a2.88,2.88,0,0,1,3,3v26.63l22.2-27.35a6,6,0,0,1,1.62-1.5,5.34,5.34,0,0,1,3.06-.78h17.28a2.35,2.35,0,0,1,1.8.78,2.5,2.5,0,0,1,.72,1.73,2.76,2.76,0,0,1-.36,1.45l-28.8,36.24,31,39.83a2,2,0,0,1,.48,1.45,2.48,2.48,0,0,1-.72,1.73,2.31,2.31,0,0,1-1.8.78H838.79a4.94,4.94,0,0,1-3.3-1,9.62,9.62,0,0,1-1.5-1.44l-23.76-29.64v29a3,3,0,0,1-.84,2.1,2.82,2.82,0,0,1-2.16.9Z" transform="translate(-129.37 -464.22)"/><path class="cls-2" d="M870.23,512.69a2.88,2.88,0,0,1-3-3V498.9a3,3,0,0,1,.84-2.1,2.79,2.79,0,0,1,2.16-.9h14.4a2.84,2.84,0,0,1,2.1.9,2.88,2.88,0,0,1,.9,2.1v10.79a2.79,2.79,0,0,1-.9,2.16,2.94,2.94,0,0,1-2.1.84Zm.12,71.4a2.82,2.82,0,0,1-2.16-.9,3,3,0,0,1-.84-2.1v-56.4a2.89,2.89,0,0,1,3-3h14.16a2.89,2.89,0,0,1,3,3v56.4a3,3,0,0,1-.84,2.1,2.82,2.82,0,0,1-2.16.9Z" transform="translate(-129.37 -464.22)"/><path class="cls-2" d="M933.59,584.09a32.53,32.53,0,0,1-13.26-2.46,18,18,0,0,1-8.58-7.67q-3-5.24-3-13.5v-23h-9.36a3.13,3.13,0,0,1-2.22-.84,2.82,2.82,0,0,1-.9-2.16v-9.73a2.82,2.82,0,0,1,.9-2.15,3.14,3.14,0,0,1,2.22-.85h9.36V501.9a2.86,2.86,0,0,1,.9-2.17,3,3,0,0,1,2.1-.83h13.92a2.86,2.86,0,0,1,3,3v19.79h15a3.14,3.14,0,0,1,2.22.85,2.82,2.82,0,0,1,.9,2.15v9.73a2.82,2.82,0,0,1-.9,2.16,3.13,3.13,0,0,1-2.22.84h-15v21.35a11.72,11.72,0,0,0,1.56,6.48c1,1.61,2.8,2.4,5.28,2.4h9.24a2.89,2.89,0,0,1,3,3v10.44a3,3,0,0,1-.84,2.1,2.82,2.82,0,0,1-2.16.9Z" transform="translate(-129.37 -464.22)"/></svg>

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

@@ -0,0 +1,359 @@
/*global wffnUtm */
var wffnUtm_terms = wffnUtm.cookieKeys, wffnCookieManage = {
setCookie: function (e, o, t) {
var r = new Date();
r.setTime(r.getTime() + 24 * t * 60 * 60 * 1e3);
var c = "expires=" + r.toUTCString();
var basehost = ';domain=.' + wffnGetHost(document.location.hostname);
document.cookie = e + "=" + o + ";" + c + basehost + ";path=/";
}, getCookie: function (e) {
for (var o = e + "=", t = document.cookie.split(";"), r = 0; r < t.length; r++) {
for (var c = t[r]; " " == c.charAt(0);) c = c.substring(1);
if (0 == c.indexOf(o)) return c.substring(o.length, c.length);
}
return "";
}, remove: function (e) {
var o = new Date();
o.setTime(o.getTime() - 864e5);
var t = "expires=" + o.toUTCString();
document.cookie = e + "=;" + t + ";path=/";
}, commons: {
inArray: function (e, o) {
return -1 === o.indexOf(e);
}
}
};
function wffnGetHost(url) {
var o = {
strictMode: false,
key: ['source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'anchor'],
q: {
name: 'queryKey',
parser: /(?:^|&)([^&=]*)=?([^&]*)/g
},
parser: {
strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,
loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/
}
},
m = o.parser[o.strictMode ? 'strict' : 'loose'].exec(url),
uri = {},
i = 14;
while (i--) {
uri[o.key[i]] = m[i] || '';
}
uri[o.q.name] = {};
uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) {
if ($1) {
uri[o.q.name][$1] = $2;
}
});
return uri.host.replace('www.', '');
}
function wffnGetQueryVars() {
try {
var result = {}, tmp = [];
window.location.search
.substr(1)
.split("&")
.forEach(function (item) {
tmp = item.split('=');
if (tmp.length > 1) {
result[tmp[0]] = tmp[1];
}
});
return wffnDefaultEvent(result);
} catch (e) {
console.log(e);
}
}
/** Add default parameter utm event **/
function wffnDefaultEvent(result) {
if (typeof Intl === "object" && typeof Intl.DateTimeFormat() === "object") {
let resolved = Intl.DateTimeFormat().resolvedOptions();
if (resolved.hasOwnProperty('timeZone')) {
result.timezone = resolved.timeZone;
}
}
result.flt = wffnGetAdminTime();
/**
* save referrer when manually pass by url
*/
if (result.hasOwnProperty('fkreferrer') && result.fkreferrer !== '') {
result.referrer = result.fkreferrer;
delete result.fkreferrer;
} else {
const WffnfkRef = document.referrer;
const getDomain = url => new URL(url).hostname;
result.referrer = (WffnfkRef && !wffnUtm.excludeDomain.some(domain => getDomain(WffnfkRef).endsWith(domain)) && !WffnfkRef.includes(window.location.hostname)) ? WffnfkRef : '';
}
result.fl_url = (typeof window.location.pathname !== "undefined") ? window.location.pathname : '/';
let getDevice = wffnDetectDevice();
if (typeof getDevice !== "undefined" && getDevice !== "") {
if (typeof getDevice.browser.name !== "undefined") {
result.browser = getDevice.browser.name;
}
if (typeof getDevice.is_mobile !== "undefined") {
result.is_mobile = getDevice.is_mobile;
}
}
return result;
}
/** get wp admin current time*/
function wffnGetAdminTime(getEpochTime = false, isObject = false) {
var getTime = new Date();
var getIsoString = getTime.toISOString();
// Convert the ISO string to a Date object
var dateFromIso = new Date(getIsoString);
// Set Admin offset to get user time according admin
dateFromIso.setMinutes(dateFromIso.getMinutes() + parseInt(wffnUtm.utc_offset));
getIsoString = dateFromIso.toISOString();
const [datePart, timePart] = getIsoString.split("T");
// Extract year, month, day
const [getYear, getMonth, getDay] = datePart.split("-").map(Number);
// Extract hours, minutes, seconds
const [getHours, getMinutes, secondsWithMillis] = timePart.split(":");
const getSeconds = secondsWithMillis.split(".")[0];
if (true === getEpochTime) {
/** get time in seconds **/
dateFromIso = new Date(getYear + '-' + (getMonth) + '-' + getDay + ' ' + getHours + ':' + getMinutes + ':' + getSeconds);
return Math.round(dateFromIso.getTime() / 1000);
}
if (true === isObject) {
return new Date(getYear + '-' + (getMonth) + '-' + getDay + ' ' + getHours + ':' + getMinutes + ':' + getSeconds);
}
return getYear + '-' + (getMonth) + '-' + getDay + ' ' + getHours + ':' + getMinutes + ':' + getSeconds;
}
function wffnGetTrafficSource() {
try {
var referrer = document.referrer.toString();
var direct = referrer.length === 0;
//noinspection JSUnresolvedVariable
var internal = direct ? false : referrer.indexOf(wffnUtm.site_url) === 0;
var external = !(direct || internal);
var cookie = wffnCookieManage.getCookie('wffn_traffic_source') === '' ? false : wffnCookieManage.getCookie('wffn_traffic_source');
if (external === false) {
return cookie ? cookie : 'direct';
} else {
return cookie && cookie === referrer ? cookie : referrer;
}
} catch (e) {
return '';
}
}
function wffnManageCookies() {
try {
var source = wffnGetTrafficSource();
if (source !== 'direct') {
wffnCookieManage.setCookie('wffn_traffic_source', source, 2);
} else {
wffnCookieManage.remove('wffn_traffic_source');
}
var queryVars = wffnGetQueryVars();
for (var k in wffnUtm_terms) {
if (Object.prototype.hasOwnProperty.call(queryVars, wffnUtm_terms[k])) {
/**
* restricted override cookies for user journey
*/
if (['flt', 'fl_url', 'referrer'].indexOf(wffnUtm_terms[k]) !== -1) {
if ('undefined' !== typeof wffnCookieManage && '' === wffnCookieManage.getCookie('wffn_' + wffnUtm_terms[k])) {
wffnCookieManage.setCookie('wffn_' + wffnUtm_terms[k], queryVars[wffnUtm_terms[k]], 2);
}
} else {
wffnCookieManage.setCookie('wffn_' + wffnUtm_terms[k], queryVars[wffnUtm_terms[k]], 2);
}
}
}
} catch (e) {
console.log(e);
}
}
/**
* Return UTM terms from request query variables or from cookies.
*/
function wffnGetUTMs() {
try {
var terms = {};
var queryVars = wffnGetQueryVars();
/** exclude parameter for utm event **/
var excludeArray = ["flt", "timezone", "is_mobile", "browser", "fbclid", "gclid", "referrer", "fl_url"];
for (var k in wffnUtm_terms) {
if (wffnCookieManage.getCookie('wffn_' + wffnUtm_terms[k]) === '' && Object.prototype.hasOwnProperty.call(queryVars, wffnUtm_terms[k])) {
terms[wffnUtm_terms[k]] = wffnCookieManage.getCookie('wffn_' + wffnUtm_terms[k]);
}
}
return terms;
} catch (e) {
return {};
}
}
/* eslint-disable no-unused-vars */
function wffnAddTrafficParamsToEvent(params) {
try {
var get_generic_params = wffnUtm.genericParamEvents;
var json_get_generic_params = JSON.parse(get_generic_params);
for (var k in json_get_generic_params) {
params[k] = json_get_generic_params[k];
}
/**
* getting current day and time to send with this event
*/
var e = wffnGetAdminTime(false, true);
var a = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"][e.getDay()],
b = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"][e.getMonth()],
c = ["00-01", "01-02", "02-03", "03-04", "04-05", "05-06", "06-07", "07-08", "08-09", "09-10", "10-11", "11-12", "12-13", "13-14", "14-15", "15-16", "16-17", "17-18", "18-19", "19-20", "20-21", "21-22", "22-23", "23-24"][e.getHours()];
params.event_month = b;
params.event_day = a;
params.event_hour = c;
params.traffic_source = wffnGetTrafficSource();
var getUTMs = wffnGetUTMs();
for (var ki in getUTMs) {
params[ki] = getUTMs[ki];
}
return params;
} catch (eeX) {
return params;
}
}
/** return device and browser info **/
function wffnDetectDevice() {
let header = [navigator.userAgent, navigator.vendor, window.opera];
let is_mobile = false;
if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
is_mobile = true;
}
/** check device for facebook application **/
if (false === is_mobile) {
let fbAgent = navigator.userAgent || navigator.vendor || window.opera;
if ((fbAgent.indexOf("FBAN") > -1) || (fbAgent.indexOf("FBAV") > -1)) {
is_mobile = true;
}
}
let databrowser = [
{name: 'Chrome', value: 'Chrome', version: 'Chrome'},
{name: 'Firefox', value: 'Firefox', version: 'Firefox'},
{name: 'Safari', value: 'Safari', version: 'Version'},
{name: 'Internet Explorer', value: 'MSIE', version: 'MSIE'},
{name: 'Opera', value: 'Opera', version: 'Opera'},
{name: 'BlackBerry', value: 'CLDC', version: 'CLDC'},
{name: 'Mozilla', value: 'Mozilla', version: 'Mozilla'}
];
var agent = header.join(' '),
browser = wffnDetectBrowser(agent, databrowser);
return {is_mobile: is_mobile, browser: browser};
}
function wffnDetectBrowser(string, data) {
var i = 0,
j = 0,
regex,
regexv,
match,
matches,
version;
for (i = 0; i < data.length; i += 1) {
regex = new RegExp(data[i].value, 'i');
match = regex.test(string);
if (match) {
regexv = new RegExp(data[i].version + '[- /:;]([\\d._]+)', 'i');
matches = string.match(regexv);
version = '';
if (matches) {
if (matches[1]) {
matches = matches[1];
}
}
if (matches) {
matches = matches.split(/[._]+/);
for (j = 0; j < matches.length; j += 1) {
if (j === 0) {
version += matches[j] + '.';
} else {
version += matches[j];
}
}
} else {
version = '0';
}
return {
name: data[i].name,
version: parseFloat(version)
};
}
}
return {name: 'unknown', version: 0};
}
wffnManageCookies();

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,48 @@
<?php
if ( ! class_exists( 'BWF_Compatibility_With_CURCY' ) ) {
#[AllowDynamicProperties]
class BWF_Compatibility_With_CURCY {
public function __construct() {
}
public function is_enable() {
return class_exists( 'WOOMULTI_CURRENCY_F_Data' );
}
public function alter_fixed_amount( $price, $currency = null ) {
if ( class_exists( 'WOOMULTI_CURRENCY_F_Data' ) ) {
$currentCurrencyRate = 1;
$multiCurrencySettings = WOOMULTI_CURRENCY_F_Data::get_ins();
$wmcCurrencies = $multiCurrencySettings->get_list_currencies();
$currentCurrency = $multiCurrencySettings->get_current_currency();
$currentCurrencyRate = floatval( $wmcCurrencies[ $currentCurrency ]['rate'] );
// Convert the price to the base currency
$price = $price / $currentCurrencyRate;
}
return $price;
}
public function get_fixed_currency_price_reverse( $price, $from = null, $base = null ) {
if ( class_exists( 'WOOMULTI_CURRENCY_F_Data' ) ) {
$data = new WOOMULTI_CURRENCY_F_Data();
$from = ( is_null( $from ) ) ? $data->get_current_currency() : $from;
$base = ( is_null( $base ) ) ? get_option( 'woocommerce_currency' ) : $base;
$rates = $data->get_exchange( $from, $base );
if ( is_array( $rates ) && isset( $rates[ $base ] ) ) {
$price = $price * $rates[ $base ];
}
}
return $price;
}
}
BWF_Plugin_Compatibilities::register( new BWF_Compatibility_With_CURCY(), 'curcy' );
}

View File

@@ -0,0 +1,88 @@
<?php
if ( ! class_exists( 'BWF_Compatibility_With_Aelia_CS' ) ) {
#[AllowDynamicProperties]
class BWF_Compatibility_With_Aelia_CS {
public function __construct() {
}
public function is_enable() {
if ( false === class_exists( 'Aelia\WC\CurrencySwitcher\WC_Aelia_CurrencySwitcher' ) ) {
return false;
}
return true;
}
/**
*
* Modifies the amount for the fixed discount given by the admin in the currency selected.
*
* @param integer|float $price
*
* @return float
*/
public function alter_fixed_amount( $price, $currency = null ) {
return $this->get_price_in_currency( $price, $currency );
}
/**
* Basic integration with WooCommerce Currency Switcher, developed by Aelia
* (http://aelia.co). This method can be used by any 3rd party plugin to
* return prices converted to the active currency.
*
* Need a consultation? Find us on Codeable: https://aelia.co/hire_us
*
* @param double price The source price.
* @param string to_currency The target currency. If empty, the active currency
* will be taken.
* @param string from_currency The source currency. If empty, WooCommerce base
* currency will be taken.
*
* @return double The price converted from source to destination currency.
* @author Aelia <support@aelia.co>
* @link https://aelia.co
*/
public function get_price_in_currency( $price, $to_currency = null, $from_currency = null ) {
// If source currency is not specified, take the shop's base currency as a default
if ( empty( $from_currency ) ) {
$from_currency = get_option( 'woocommerce_currency' );
}
// If target currency is not specified, take the active currency as a default.
// The Currency Switcher sets this currency automatically, based on the context. Other
// plugins can also override it, based on their own custom criteria, by implementing
// a filter for the "woocommerce_currency" hook.
//
// For example, a subscription plugin may decide that the active currency is the one
// taken from a previous subscription, because it's processing a renewal, and such
// renewal should keep the original prices, in the original currency.
if ( empty( $to_currency ) ) {
$to_currency = get_woocommerce_currency();
}
// Call the currency conversion filter. Using a filter allows for loose coupling. If the
// Aelia Currency Switcher is not installed, the filter call will return the original
// amount, without any conversion being performed. Your plugin won't even need to know if
// the multi-currency plugin is installed or active
return apply_filters( 'wc_aelia_cs_convert', $price, $from_currency, $to_currency );
}
function get_fixed_currency_price_reverse( $price, $from = null, $base = null ) {
$base = ( is_null( $base ) ) ? get_option( 'woocommerce_currency' ) : $base;
$price = $this->get_price_in_currency( $price, $base, $from );
return $price;
}
}
BWF_Plugin_Compatibilities::register( new BWF_Compatibility_With_Aelia_CS(), 'aelia_cs' );
}

View File

@@ -0,0 +1,63 @@
<?php
if ( ! class_exists( 'BWF_Compatibility_With_WC_Price_Based_On_Country' ) ) {
#[AllowDynamicProperties]
class BWF_Compatibility_With_WC_Price_Based_On_Country {
public function is_enable() {
return class_exists( 'WC_Product_Price_Based_Country' );
}
/**
*
* Modifies the amount for the fixed discount given by the admin in the currency selected.
*
* @param integer|float $price
*
* @return float
*/
public function alter_fixed_amount( $price, $currency = null ) {
if ( ! $this->is_enable() ) {
return $price;
}
$rate = $this->get_exchange_rate( $currency );
return $price * $rate;
}
public function get_fixed_currency_price_reverse( $price, $currency = null, $base = null ) {
if ( ! $this->is_enable() ) {
return $price;
}
$rate = $this->get_exchange_rate( $currency );
return $price / $rate;
}
/**
* Get exchange rate
*
* @param $currency
*
* @return float|int
*/
public function get_exchange_rate( $currency ) {
if ( ! class_exists( 'WCPBC_Pricing_Zones' ) ) {
return 1;
}
$zones = WCPBC_Pricing_Zones::get_zones();
foreach ( $zones as $zone ) {
/** @var $zone WCPBC_Pricing_Zone */
if ( $currency !== $zone->get_currency() ) {
continue;
}
return $zone->get_exchange_rate();
}
return 1;
}
}
BWF_Plugin_Compatibilities::register( new BWF_Compatibility_With_WC_Price_Based_On_Country(), 'wc_price_based_on_country' );
}

View File

@@ -0,0 +1,162 @@
<?php
if ( ! class_exists( 'BWF_Compatibility_With_WooCommerce_Payments' ) ) {
#[AllowDynamicProperties]
class BWF_Compatibility_With_WooCommerce_Payments {
public function __construct() {
}
public function is_enable() {
if ( class_exists( 'WCPay\MultiCurrency\MultiCurrency' ) && function_exists( 'WC_Payments_Multi_Currency' ) ) {
return true;
}
return false;
}
/**
* Adds currency parameter to URLs to maintain currency context
*
* @param string $url
* @param WC_Order $order
*
* @return string
*/
public function maybe_add_currency_converter_url( $url, $order ) {
if ( ! $order instanceof WC_Order ) {
return $url;
}
$currency = $order->get_currency();
if ( $currency ) {
$url = add_query_arg( array( 'currency' => strtoupper( $currency ) ), $url );
}
return $url;
}
/**
* Modifies the amount for the fixed discount given by the admin in the currency selected.
*
* @param integer|float $price
* @param string|null $currency
*
* @return float
*/
public function alter_fixed_amount( $price, $currency = null ) {
if ( ! $this->is_enable() ) {
return $price;
}
$multi_currency = WC_Payments_Multi_Currency();
if ( ! $multi_currency ) {
return $price;
}
return $multi_currency->get_price( $price, 'product' );
}
/**
* Converts price back to the base currency (reverse conversion)
*
* @param float $price
* @param string|null $from
* @param string|null $base
*
* @return float
*/
public function get_fixed_currency_price_reverse( $price, $from = null, $base = null ) {
if ( ! $this->is_enable() ) {
return $price;
}
$multi_currency = WC_Payments_Multi_Currency();
if ( ! $multi_currency ) {
return $price;
}
$from = ( is_null( $from ) ) ? $multi_currency->get_selected_currency()->get_code() : $from;
$base = ( is_null( $base ) ) ? $multi_currency->get_default_currency()->get_code() : $base;
// If currencies are the same, no conversion needed
if ( $from === $base ) {
return $price;
}
try {
// Use WooCommerce Payments' raw conversion method
return $multi_currency->get_raw_conversion( $price, $base, $from );
} catch ( Exception $e ) {
// If conversion fails, return original price
return $price;
}
}
/**
* Gets the current selected currency code
*
* @return string|null
*/
public function get_current_currency() {
if ( ! $this->is_enable() ) {
return null;
}
$multi_currency = WC_Payments_Multi_Currency();
if ( ! $multi_currency ) {
return null;
}
return $multi_currency->get_selected_currency()->get_code();
}
/**
* Gets the default store currency code
*
* @return string|null
*/
public function get_default_currency() {
if ( ! $this->is_enable() ) {
return null;
}
$multi_currency = WC_Payments_Multi_Currency();
if ( ! $multi_currency ) {
return null;
}
return $multi_currency->get_default_currency()->get_code();
}
/**
* Gets the exchange rate for a currency
*
* @param string $currency_code
*
* @return float
*/
public function get_exchange_rate( $currency_code ) {
if ( ! $this->is_enable() ) {
return 1.0;
}
$multi_currency = WC_Payments_Multi_Currency();
if ( ! $multi_currency ) {
return 1.0;
}
$enabled_currencies = $multi_currency->get_enabled_currencies();
if ( isset( $enabled_currencies[ $currency_code ] ) ) {
return $enabled_currencies[ $currency_code ]->get_rate();
}
return 1.0;
}
}
BWF_Plugin_Compatibilities::register( new BWF_Compatibility_With_WooCommerce_Payments(), 'woocommerce_payments' );
}

View File

@@ -0,0 +1,56 @@
<?php
if ( ! class_exists( 'BWF_Compatibility_With_WOOCS' ) ) {
#[AllowDynamicProperties]
class BWF_Compatibility_With_WOOCS {
public function __construct() {
}
public function is_enable() {
if ( isset( $GLOBALS['WOOCS'] ) && $GLOBALS['WOOCS'] instanceof WOOCS ) {
return true;
}
return false;
}
public function get_currency_symbol( $currency ) {
global $WOOCS;
$WOOCS->current_currency = $currency;
return get_woocommerce_currency_symbol( $currency );
}
/**
*
* Modifies the amount for the fixed discount given by the admin in the currency selected.
*
* @param integer|float $price
*
* @return float
*/
public function alter_fixed_amount( $price, $currency = null ) {
return $GLOBALS['WOOCS']->woocs_exchange_value( $price );
}
function get_fixed_currency_price_reverse( $price, $from = null, $base = null ) { //phpcs:ignore
$currencies = get_option( 'woocs' );
$from = ( is_null( $from ) ) ? $GLOBALS['WOOCS']->current_currency : $from;
if ( is_array( $currencies ) && ! empty( $currencies )) {
foreach ( $currencies as $key => $value ) {
if ( $key === $from ) {
$rate = $value['rate'];
$price = $price * ( 1 / $rate );
}
}
}
return $price;
}
}
BWF_Plugin_Compatibilities::register( new BWF_Compatibility_With_WOOCS(), 'woocs' );
}

View File

@@ -0,0 +1,68 @@
<?php
if ( ! class_exists( 'BWF_Compatibility_With_WooMultiCurrency' ) ) {
#[AllowDynamicProperties]
class BWF_Compatibility_With_WooMultiCurrency {
public function __construct() {
}
public function is_enable() {
if ( defined( 'WOOMULTI_CURRENCY_VERSION' ) ) {
return true;
}
return false;
}
/**
*
* @param $url
* @param WC_Order $order
*
* @return string
*/
public function maybe_add_currency_converter_url( $url, $order ) {
if ( ! $order instanceof WC_Order ) {
return $url;
}
return add_query_arg( array( 'wmc-currency' => strtoupper( $order->get_currency() ) ), $url );
}
/**
*
* Modifies the amount for the fixed discount given by the admin in the currency selected.
*
* @param integer|float $price
*
* @return float
*/
public function alter_fixed_amount( $price, $currency = null ) {
return wmc_get_price( $price, $currency );
}
function get_fixed_currency_price_reverse( $price, $from = null, $base = null ) {
$data = new WOOMULTI_CURRENCY_Data();
$from = ( is_null( $from ) ) ? $data->get_current_currency() : $from;
$base = ( is_null( $base ) ) ? get_option( 'woocommerce_currency' ) : $base;
$rates = $data->get_exchange( $from, $base );
if ( is_array( $rates ) && isset( $rates[ $base ] ) ) {
$price = $price * $rates[ $base ];
}
return $price;
}
}
BWF_Plugin_Compatibilities::register( new BWF_Compatibility_With_WooMultiCurrency(), 'woomulticurrency' );
}

View File

@@ -0,0 +1,65 @@
<?php
if ( ! class_exists( 'BWF_Compatibility_With_WPML_MultiCurrency' ) ) {
#[AllowDynamicProperties]
class BWF_Compatibility_With_WPML_MultiCurrency {
public function __construct() {
}
public function is_enable() {
global $woocommerce_wpml;
if ( class_exists( 'woocommerce_wpml' ) && $woocommerce_wpml instanceof woocommerce_wpml ) {
return true;
}
return false;
}
/**
*
* Modifies the amount for the fixed discount given by the admin in the currency selected.
*
* @param integer|float $price
*
* @return float
*/
public function alter_fixed_amount( $price, $currency = null ) {
if ( ! class_exists( 'SitePress' ) ) {
return $price;
}
global $woocommerce_wpml;
if ( WCML_MULTI_CURRENCIES_INDEPENDENT !== $woocommerce_wpml->settings['enable_multi_currency'] ) {
return $price;
}
return $woocommerce_wpml->get_multi_currency()->prices->convert_price_amount( $price );
}
function get_fixed_currency_price_reverse( $price, $from = null, $base = null ) {
if ( ! class_exists( 'SitePress' ) ) {
return $price;
}
global $woocommerce_wpml;
if ( WCML_MULTI_CURRENCIES_INDEPENDENT !== $woocommerce_wpml->settings['enable_multi_currency'] ) {
return $price;
}
$price = $woocommerce_wpml->get_multi_currency()->prices->unconvert_price_amount( $price, $from );
return $price;
}
}
BWF_Plugin_Compatibilities::register( new BWF_Compatibility_With_WPML_MultiCurrency(), 'woowpmlmulticurrency' );
}

View File

@@ -0,0 +1,65 @@
<?php
if ( ! class_exists( 'BWF_Compatibility_With_YayCurrency' ) ) {
#[AllowDynamicProperties]
class BWF_Compatibility_With_YayCurrency {
public function is_enable() {
return class_exists( 'Yay_Currency\Helpers\YayCurrencyHelper' );
}
/**
* Modifies the amount for the fixed discount given by the admin in the currency selected.
*
* @param integer|float $price
*
* @return float
*/
public function alter_fixed_amount( $price, $currency = null ) {
if ( ! $this->is_enable() ) {
return $price;
}
$currency = $this->get_formatted_currency( $currency );
if ( empty( $currency ) ) {
return $price;
}
return Yay_Currency\Helpers\YayCurrencyHelper::calculate_price_by_currency( $price, false, $currency );
}
function get_fixed_currency_price_reverse( $price, $from = null, $base = null ) {
if ( ! $this->is_enable() ) {
return $price;
}
$currency = $this->get_formatted_currency( $from );
if ( empty( $currency ) ) {
return $price;
}
return Yay_Currency\Helpers\YayCurrencyHelper::reverse_calculate_price_by_currency( $price, $currency );
}
public function get_formatted_currency( $from ) {
if ( ! $this->is_enable() ) {
return [];
}
return Yay_Currency\Helpers\YayCurrencyHelper::get_currency_by_currency_code( $from );
}
public function get_currency_symbol( $currency ) {
if ( ! class_exists( 'Yay_Currency\Helpers\YayCurrencyHelper' ) ) {
return '';
}
$apply_currency = $this->get_formatted_currency( $currency );
add_filter( 'yay_currency_detect_current_currency', function () use ( $apply_currency ) {
return $apply_currency;
} );
return Yay_Currency\Helpers\YayCurrencyHelper::get_symbol_by_currency_code( $currency );
}
}
BWF_Plugin_Compatibilities::register( new BWF_Compatibility_With_YayCurrency(), 'yaycurrency' );
}

View File

@@ -0,0 +1,116 @@
<?php
if ( ! class_exists( 'BWF_Plugin_Compatibilities' ) ) {
/**
* Class BWF_Plugin_Compatibilities
* Loads all the compatibilities files we have to provide compatibility with each plugin
*/
#[AllowDynamicProperties]
class BWF_Plugin_Compatibilities {
public static $plugin_compatibilities = array();
public static function load_all_compatibilities() {
$compat = [
'class-bwf-compatibilitiy-with-curcy.php' => class_exists( 'WOOMULTI_CURRENCY_F_VERSION' ),
'class-bwf-compatibility-with-aelia-cs.php' => class_exists( 'Aelia\WC\CurrencySwitcher\WC_Aelia_CurrencySwitcher' ),
'class-bwf-compatibility-with-woocs.php' => isset( $GLOBALS['WOOCS'] ) && $GLOBALS['WOOCS'] instanceof WOOCS,
'class-bwf-compatibility-with-woomulticurrency.php' => defined( 'WOOMULTI_CURRENCY_VERSION' ),
'class-bwf-compatibility-with-wpml-multicurrency.php' => class_exists( 'woocommerce_wpml' ),
'class-bwf-compatibility-with-yaycurrency.php' => class_exists( 'Yay_Currency\Helpers\YayCurrencyHelper' ),
'class-bwf-compatibility-with-wc-price-based-on-country.php' => class_exists( 'WC_Product_Price_Based_Country' ),
'class-bwf-compatibility-with-woocommerce-payments.php' => function_exists( 'WC_Payments_Multi_Currency' ),
];
self::add_files( $compat );
}
public static function register( $object, $slug ) {
self::$plugin_compatibilities[ $slug ] = $object;
}
public static function get_compatibility_class( $slug ) {
return ( isset( self::$plugin_compatibilities[ $slug ] ) ) ? self::$plugin_compatibilities[ $slug ] : false;
}
public static function get_fixed_currency_price( $price, $currency = null ) {
if ( empty( self::$plugin_compatibilities ) ) {
return $price;
}
foreach ( self::$plugin_compatibilities as $plugins_class ) {
if ( method_exists( $plugins_class, 'is_enable' ) && $plugins_class->is_enable() && is_callable( array( $plugins_class, 'alter_fixed_amount' ) ) ) {
return call_user_func( array( $plugins_class, 'alter_fixed_amount' ), $price, $currency );
}
}
return $price;
}
public static function get_fixed_currency_price_reverse( $price, $from = null, $to = null ) {
try {
if ( empty( self::$plugin_compatibilities ) ) {
BWF_Plugin_Compatibilities::load_all_compatibilities();
}
if ( empty( self::$plugin_compatibilities ) ) {
return $price;
}
foreach ( self::$plugin_compatibilities as $plugins_class ) {
if ( method_exists( $plugins_class, 'is_enable' ) && $plugins_class->is_enable() && is_callable( array( $plugins_class, 'get_fixed_currency_price_reverse' ) ) ) {
return call_user_func( array( $plugins_class, 'get_fixed_currency_price_reverse' ), $price, $from, $to );
}
}
} catch ( Exception|Error $e ) {
BWF_Logger::get_instance()->log( 'Error while getting reversed price through compatibility files: ' . $e->getMessage(), 'bwf-compatibilities', 'buildwoofunnels', true );
}
return $price;
}
/**
* Get currency symbol
*
* @param $currency
*
* @return mixed|string
*/
public static function get_currency_symbol( $currency ) {
if ( empty( self::$plugin_compatibilities ) ) {
BWF_Plugin_Compatibilities::load_all_compatibilities();
}
if ( empty( self::$plugin_compatibilities ) ) {
return '';
}
foreach ( self::$plugin_compatibilities as $plugins_class ) {
if ( method_exists( $plugins_class, 'is_enable' ) && $plugins_class->is_enable() && is_callable( array( $plugins_class, 'get_currency_symbol' ) ) ) {
return call_user_func( array( $plugins_class, 'get_currency_symbol' ), $currency );
}
}
return '';
}
public static function add_files( $paths ) {
try {
foreach ( $paths as $file => $condition ) {
if ( false === $condition ) {
continue;
}
include_once __DIR__ . '/' . $file;
}
} catch ( Exception|Error $e ) {
BWF_Logger::get_instance()->log( 'Error while loading compatibility files: ' . $e->getMessage(), 'bwf-compatibilities' );
}
}
}
}

View File

@@ -0,0 +1,591 @@
<?php
/**
* WooCommerce Plugin Compatibility
*
* This source file is subject to the GNU General Public License v3.0
* that is bundled with this package in the file license.txt.
* It is also available through the world-wide-web at this URL:
* http://www.gnu.org/licenses/gpl-3.0.html
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@skyverge.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade the plugin to newer
* versions in the future. If you wish to customize the plugin for your
* needs please refer to http://www.skyverge.com
*
* @author SkyVerge
* @copyright Copyright (c) 2013, SkyVerge, Inc.
* @license http://www.gnu.org/licenses/gpl-3.0.html GNU General Public License v3.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
} // Exit if accessed directly
if ( ! class_exists( 'BWF_WC_Compatibility' ) ) :
/**
* WooCommerce Compatibility Utility Class
*
* The unfortunate purpose of this class is to provide a single point of
* compatibility functions for dealing with supporting multiple versions
* of WooCommerce.
*
* The recommended procedure is to rename this file/class, replacing "my plugin"
* with the particular plugin name, so as to avoid clashes between plugins.
* Over time we expect to remove methods from this class, using the current
* ones directly, as support for older versions of WooCommerce is dropped.
*
* Current Compatibility: 2.0.x - 2.1
*
* @version 1.0
*/
#[AllowDynamicProperties]
class BWF_WC_Compatibility {
/**
* Compatibility function for outputting a woocommerce attribute label
*
* @param string $label the label to display
*
* @return string the label to display
* @since 1.0
*
*/
public static function wc_attribute_label( $label ) {
return wc_attribute_label( $label );
}
public static function wc_attribute_taxonomy_name( $name ) {
return wc_attribute_taxonomy_name( $name );
}
public static function wc_get_attribute_taxonomies() {
return wc_get_attribute_taxonomies();
}
public static function wc_placeholder_img_src() {
return wc_placeholder_img_src();
}
/**
* @param WC_Product $product
*
* @return string
*/
public static function woocommerce_get_formatted_product_name( $product ) {
if ( ! $product instanceof WC_Product ) {
return __( 'No title', 'woofunnels' ); // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
}
return $product->get_formatted_name();
}
/**
* @param $order
* @param $item
*
* @return WC_Product
*/
public static function get_product_from_item( $order, $item ) {
return $item->get_product();
}
public static function get_short_description( $product ) {
if ( $product === false ) {
return '';
}
return apply_filters( 'woocommerce_short_description', $product->get_short_description() );
}
public static function get_productname_from_item( $order, $item ) {
return $item->get_name();
}
public static function get_qty_from_item( $order, $item ) {
return $item->get_quantity();
}
public static function get_display_item_meta( $order, $item ) {
wc_display_item_meta( $item );
}
public static function get_display_item_downloads( $order, $item ) {
wc_display_item_downloads( $item );
}
public static function get_purchase_note( $product ) {
return $product ? $product->get_purchase_note() : '';
}
/**
* @param WC_Order $order
*
* @return mixed|string
*/
public static function get_order_currency( $order ) {
return $order instanceof WC_Order ? $order->get_currency() : get_woocommerce_currency();
}
public static function get_payment_gateway_from_order( $order ) {
return $order->get_payment_method();
}
public static function get_item_subtotal( $order, $item ) {
return $item->get_subtotal();
}
public static function get_shipping_country_from_order( $order ) {
return $order->get_shipping_country();
}
public static function get_billing_country_from_order( $order ) {
return $order->get_billing_country();
}
public static function get_order_id( $order ) {
if ( ! $order instanceof WC_Order ) {
return $order;
}
return $order->get_id();
}
/**
* @param WC_Order $order
*
* @return mixed
*/
public static function get_order_billing_1( $order ) {
return $order->get_billing_address_1();
}
/**
* @param WC_Order $order
*
* @return mixed
*/
public static function get_order_data( $order, $key ) {
if ( method_exists( $order, 'get_' . $key ) ) {
return call_user_func( array( $order, 'get_' . $key ) );
}
return self::get_order_meta( $order, $key );
}
/**
* @param WC_Order $order
*
* @return mixed
*/
public static function get_billing_first_name( $order ) {
return $order->get_billing_first_name();
}
/**
* @param WC_Order $order
*
* @return mixed
*/
public static function get_billing_last_name( $order ) {
return $order->get_billing_last_name();
}
/**
* @param WC_Order $order
*
* @return mixed
*/
public static function get_order_status( $order ) {
$status = $order->get_status();
return ( strpos( $status, 'wc-' ) === false ) ? 'wc-' . $status : $status;
}
/**
* @param WC_Order $order
*
* @return mixed
*/
public static function get_order_billing_2( $order ) {
return $order->get_billing_address_2();
}
/**
* @param WC_Order $order
*
* @return mixed
*/
public static function get_order_shipping_1( $order ) {
return $order->get_shipping_address_1();
}
/**
* Returns true if the installed version of WooCommerce is 2.6 or greater
*
* @return boolean true if the installed version of WooCommerce is 2.1 or greater
* @since 1.0
*/
public static function is_wc_version_gte_3_7() {
return version_compare( self::get_wc_version(), '3.7.0', 'ge' );
}
/**
* @param WC_Order $order
*
* @return mixed
*/
public static function get_used_coupons( $order ) {
return $order->get_coupon_codes();
}
/**
* @param WC_Order $order
*
* @return mixed
*/
public static function get_order_shipping_total( $order ) {
return $order->get_shipping_total();
}
/**
* @param WC_Order $order
*
* @return mixed
*/
public static function get_order_shipping_2( $order ) {
return $order->get_shipping_address_2();
}
/**
* @param WC_Order $order
*
* @return mixed
*/
public static function get_order_date( $order ) {
return $order->get_date_created();
}
/**
* @param WC_Order $order
*
* @return mixed
*/
public static function get_payment_method( $order ) {
return $order->get_payment_method_title();
}
/**
* @param WC_Order $order
*
* @return mixed
*/
public static function get_customer_ip_address( $order ) {
return $order->get_customer_ip_address();
}
/**
* @param WC_Order $order
*
* @return mixed
*/
public static function get_customer_note( $order ) {
return $order->get_customer_note();
}
/**
* @param $date
* @param string $format
*
* @return string
*/
public static function get_formatted_date( $date, $format = '' ) {
if ( empty( $format ) ) {
$format = get_option( 'date_format' );
}
return wc_format_datetime( $date, $format );
}
/**
* Compatibility function to add and store a notice
*
* @param string $message The text to display in the notice.
* @param string $notice_type The singular name of the notice type - either error, success or notice. [optional]
*
* @since 1.0
*
*/
public static function wc_add_notice( $message, $notice_type = 'success' ) {
wc_add_notice( $message, $notice_type );
}
/**
* Prints messages and errors which are stored in the session, then clears them.
*
* @since 1.0
*/
public static function wc_print_notices() {
wc_print_notices();
}
/**
* Compatibility function to queue some JavaScript code to be output in the footer.
*
* @param string $code javascript
*
* @since 1.0
*
*/
public static function wc_enqueue_js( $code ) {
wc_enqueue_js( $code );
}
/**
* Sets WooCommerce messages
*
* @since 1.0
*/
public static function set_messages() {
if ( ! self::is_wc_version_gte_2_1() ) {
global $woocommerce;
$woocommerce->set_messages();
}
}
/**
* Returns a new instance of the woocommerce logger
*
* @return WC_Logger logger
* @since 1.0
*/
public static function new_wc_logger() {
return new WC_Logger();
}
/**
* Format decimal numbers ready for DB storage
*
* Sanitize, remove locale formatting, and optionally round + trim off zeros
*
* @param float|string $number Expects either a float or a string with a decimal separator only (no thousands)
* @param mixed $dp number of decimal points to use, blank to use woocommerce_price_num_decimals, or false to avoid all rounding.
* @param boolean $trim_zeros from end of string
*
* @return string
* @since 1.0
*
*/
public static function wc_format_decimal( $number, $dp = false, $trim_zeros = false ) {
return wc_format_decimal( $number, $dp, $trim_zeros );
}
/**
* Get the count of notices added, either for all notices (default) or for one particular notice type specified
* by $notice_type.
*
* @param string $notice_type The name of the notice type - either error, success or notice. [optional]
*
* @return int the notice count
* @since 1.0
*
*/
public static function wc_notice_count( $notice_type = '' ) {
return wc_notice_count( $notice_type );
}
/**
* Compatibility function to use the new WC_Admin_Meta_Boxes class for the save_errors() function
*
* @return old save_errors function or new class
* @since 1.0-1
*/
public static function save_errors() {
WC_Admin_Meta_Boxes::save_errors();
}
/**
* Compatibility function to get the version of the currently installed WooCommerce
*
* @return string woocommerce version number or null
* @since 1.0
*/
public static function get_wc_version() {
// WOOCOMMERCE_VERSION is now WC_VERSION, though WOOCOMMERCE_VERSION is still available for backwards compatibility, we'll disregard it on 2.1+
if ( defined( 'WC_VERSION' ) && WC_VERSION ) {
return WC_VERSION;
}
if ( defined( 'WOOCOMMERCE_VERSION' ) && WOOCOMMERCE_VERSION ) {
return WOOCOMMERCE_VERSION;
}
return null;
}
/**
* Returns the WooCommerce instance
*
* @return WooCommerce woocommerce instance
* @since 1.0
*/
public static function WC() {
return WC();
}
/**
* Returns true if the WooCommerce plugin is loaded
*
* @return boolean true if WooCommerce is loaded
* @since 1.0
*/
public static function is_wc_loaded() {
return class_exists( 'WooCommerce' );
}
/**
* Returns true if the installed version of WooCommerce is 2.1 or greater
*
* @return boolean true if the installed version of WooCommerce is 2.1 or greater
* @since 1.0
*/
public static function is_wc_version_gte_2_1() {
// can't use gte 2.1 at the moment because 2.1-BETA < 2.1
return self::is_wc_version_gt( '2.0.20' );
}
/**
* Returns true if the installed version of WooCommerce is 2.6 or greater
*
* @return boolean true if the installed version of WooCommerce is 2.1 or greater
* @since 1.0
*/
public static function is_wc_version_gte_2_6() {
return version_compare( self::get_wc_version(), '2.6.0', 'ge' );
}
/**
* Returns true if the installed version of WooCommerce is 2.6 or greater
*
* @return boolean true if the installed version of WooCommerce is 2.1 or greater
* @since 1.0
*/
public static function is_wc_version_gte_3_0() {
return version_compare( self::get_wc_version(), '3.0.0', 'ge' );
}
/**
* @param WC_Order_Item_Shipping $method
*
* @return string
*/
public static function get_method_id( $method ) {
$method_id = $method->get_method_id();
if ( empty( $method_id ) ) {
return '';
}
$method_exp = explode( ':', $method_id );
return $method_exp[0];
}
/**
* @param WC_Order_Item_Shipping $method
*
* @return string
*/
public static function get_instance_id( $method ) {
$method_id = $method->get_method_id();
if ( empty( $method_id ) ) {
return '';
}
$method_exp = explode( ':', $method_id );
if ( ! is_array( $method_exp ) ) {
return '';
}
if ( 2 === count( $method_exp ) ) {
return $method_exp[1];
}
if ( is_callable( array( $method, 'get_instance_id' ) ) ) {
return $method->get_instance_id();
}
return '';
}
/**
* Returns true if the installed version of WooCommerce is greater than $version
*
* @param string $version the version to compare
*
* @return boolean true if the installed version of WooCommerce is > $version
* @since 1.0
*
*/
public static function is_wc_version_gt( $version ) {
return self::get_wc_version() && version_compare( self::get_wc_version(), $version, '>' );
}
public static function display_prices_including_tax() {
if ( version_compare( self::get_wc_version(), '3.3.0', 'ge' ) ) {
return 'incl' === get_option( 'woocommerce_tax_display_cart' );
}
}
/**
* Get order meta, checking if HPOS enabled
*
* @param $order
* @param $key
*
* @return array|mixed|string|null
*/
public static function get_order_meta( $order, $key = '' ) {
if ( empty( $key ) ) {
return '';
}
if ( ! $order instanceof WC_Abstract_Order ) {
return '';
}
$meta_value = $order->get_meta( $key );
if ( ! empty( $meta_value ) ) {
return $meta_value;
}
global $wpdb;
if ( true === self::is_hpos_enabled() ) {
$meta_value = $wpdb->get_var( $wpdb->prepare( "SELECT `meta_value` FROM `{$wpdb->prefix}wc_orders_meta` WHERE `meta_key`=%s AND `order_id`=%d", $key, $order->get_id() ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
} else {
$meta_value = $wpdb->get_var( $wpdb->prepare( "SELECT `meta_value` FROM {$wpdb->postmeta} WHERE `post_id` = %d AND `meta_key` = %s ORDER BY `post_id` DESC LIMIT 1", $order->get_id(), $key ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
}
if ( ! empty( $meta_value ) ) {
return maybe_unserialize( $meta_value );
}
return $meta_value;
}
/**
* Checks if HPOS enabled
*
* @return bool
*/
public static function is_hpos_enabled() {
return function_exists( 'wc_get_container' ) && ( class_exists( '\Automattic\WooCommerce\Utilities\OrderUtil' ) && method_exists( '\Automattic\WooCommerce\Utilities\OrderUtil', 'custom_orders_table_usage_is_enabled' ) && \Automattic\WooCommerce\Utilities\OrderUtil::custom_orders_table_usage_is_enabled() );
}
}
endif; // Class exists check

View File

@@ -0,0 +1,2 @@
<?php
// Silence is golden.

View File

@@ -0,0 +1,291 @@
const bwf_ajax = function (cls, is_form, cb) {
let $ = jQuery;
const self = this;
let element = null;
let handler = {};
let prefix = "bwfan_";
this.action = null;
this.change_prefix = function (new_prefix) {
if (new_prefix !== undefined) {
prefix = new_prefix;
}
};
this.data = function (form_data, formEl = null) {
return form_data;
};
this.before_send = function (formEl) {
};
this.async = function (bool) {
return bool;
};
this.method = function (method) {
return method;
};
this.success = function (rsp, fieldset, loader, jqxhr, status) {
};
this.complete = function (rsp, fieldset, loader, jqxhr, status) {
};
this.error = function (rsp, fieldset, loader, jqxhr, status) {
};
this.action = function (action) {
return action;
};
this.element = function () {
return element;
};
this.validate = function (formEl, action, form_data) {
return true;
};
function reset_form(action, fieldset, loader, rsp, jqxhr, status) {
if (fieldset.length > 0) {
fieldset.prop('disabled', false);
}
loader.remove();
let loader2;
loader2 = $(".bwf_ajax_btn_bottom_container");
loader2.removeClass('ajax_loader_show');
if (self.hasOwnProperty(action) === true && typeof self[action] === 'function') {
self[action](rsp, fieldset, loader, jqxhr, status);
}
}
function form_post(action) {
let formEl = element;
let ajax_loader = null;
let form_data = new FormData(formEl);
form_data.append('action', action);
form_data.append('bwf_nonce', bwf_secure.nonce);
let form_method = $(formEl).attr('method');
if ($(formEl).find("." + action + "_ajax_loader").length === 0) {
$(formEl).find(".bwf_form_submit").prepend("<span class='" + action + "_ajax_loader spinner" + "'></span>");
ajax_loader = $(formEl).find("." + action + "_ajax_loader");
} else {
ajax_loader = $(formEl).find("." + action + "_ajax_loader");
}
let ajax_loader2 = $(".bwf_ajax_btn_bottom_container");
ajax_loader.addClass('ajax_loader_show');
ajax_loader2.addClass('ajax_loader_show');
let fieldset = $(formEl).find("fieldset");
if (fieldset.length > 0) {
fieldset.prop('disabled', true);
}
self.before_send(formEl, action);
let data = self.data(form_data, formEl);
let validated = self.validate(formEl, action, form_data);
if (true !== validated) {
return;
}
let request = {
url: ajaxurl,
async: self.async(true),
method: self.method('POST'),
data: data,
processData: false,
contentType: false,
// contentType: self.content_type(false),
success: function (rsp, jqxhr, status) {
if (typeof rsp === 'object' && rsp.hasOwnProperty('nonce')) {
bwf_secure.nonce = rsp.nonce;
delete rsp.nonce;
}
reset_form(action + "_ajax_success", fieldset, ajax_loader, rsp, jqxhr, status);
self.success(rsp, jqxhr, status, element, ajax_loader, fieldset);
},
complete: function (rsp, jqxhr, status) {
reset_form(action + "_ajax_complete", fieldset, ajax_loader, rsp, jqxhr, status);
self.complete(rsp, jqxhr, status, element, ajax_loader, fieldset);
},
error: function (rsp, jqxhr, status) {
reset_form(action + "_ajax_error", fieldset, ajax_loader, rsp, jqxhr, status);
self.error(rsp, jqxhr, status, element, ajax_loader, fieldset);
}
};
if (handler.hasOwnProperty(action)) {
clearTimeout(handler[action]);
} else {
handler[action] = null;
}
handler[action] = setTimeout(
function (request) {
$.ajax(request);
},
200,
request
);
}
function send_json(action) {
let formEl = element;
let data = self.data({}, formEl);
if (typeof data === 'object') {
data.action = action;
} else {
data = {
'action': action
};
}
self.before_send(formEl, action);
let validated = self.validate(formEl, action);
if (true !== validated) {
return;
}
data.bwf_nonce = bwf_secure.nonce;
let request = {
url: ajaxurl,
async: self.async(true),
method: self.method('POST'),
data: data,
success: function (rsp, jqxhr, status, element) {
if (typeof rsp === 'object' && rsp.hasOwnProperty('nonce')) {
bwf_secure.nonce = rsp.nonce;
delete rsp.nonce;
}
self.success(rsp, jqxhr, status, element);
},
complete: function (rsp, jqxhr, status, element) {
self.complete(rsp, jqxhr, status, element);
},
error: function (rsp, jqxhr, status) {
self.error(rsp, jqxhr, status, element);
}
};
if (handler.hasOwnProperty(action)) {
clearTimeout(handler[action]);
} else {
handler[action] = null;
}
handler[action] = setTimeout(
function (request) {
$.ajax(request);
},
200,
request
);
}
this.ajax = function (action, data) {
if (typeof data === 'object') {
data.action = action;
} else {
data = {
'action': action
};
}
data.action = prefix + action;
self.before_send(document.body, action);
let validated = self.validate(document.body, action, data);
if (true !== validated) {
return;
}
data.bwf_nonce = bwf_secure.nonce;
let request = {
url: ajaxurl,
async: self.async(true),
method: self.method('POST'),
data: data,
success: function (rsp, jqxhr, status) {
if (typeof rsp === 'object' && rsp.hasOwnProperty('nonce')) {
bwf_secure.nonce = rsp.nonce;
delete rsp.nonce;
}
self.success(rsp, jqxhr, status, action);
},
complete: function (rsp, jqxhr, status) {
self.complete(rsp, jqxhr, status, action);
},
error: function (rsp, jqxhr, status) {
self.error(rsp, jqxhr, status, action);
}
};
if (handler.hasOwnProperty(action)) {
clearTimeout(handler[action]);
} else {
handler[action] = null;
}
handler[action] = setTimeout(
function (request) {
$.ajax(request);
},
200,
request
);
};
function form_init(cls) {
if ($(cls).length === 0) {
return;
}
$(cls).on(
"submit",
function (e) {
e.preventDefault();
let action = $(this).data('bwf-action');
if (action !== 'undefined') {
action = prefix + action;
action = action.trim();
element = this;
self.action = action;
form_post(action);
}
}
);
if (typeof cb === 'function') {
cb(self);
}
}
function click_init(cls) {
if ($(cls).length === 0) {
return;
}
$(cls).on(
"click",
function (e) {
e.preventDefault();
let action = $(this).data('bwf-action');
if (action !== 'undefined') {
action = prefix + action;
action = action.trim();
element = this;
self.action = action;
send_json(action);
}
}
);
if (typeof cb === 'function') {
cb(self);
}
}
if (is_form === true) {
form_init(cls, cb);
return this;
}
if (is_form === false) {
click_init(cls, cb);
return this;
}
return this;
};

View File

@@ -0,0 +1,217 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
if ( ! class_exists( 'WFCO_Admin' ) ) {
#[AllowDynamicProperties]
class WFCO_Admin {
private static $ins = null;
public $admin_path;
public $admin_url;
public $section_page = '';
public $should_show_shortcodes = null;
public function __construct() {
define( 'WFCO_PLUGIN_FILE', __FILE__ );
define( 'WFCO_PLUGIN_DIR', __DIR__ );
define( 'WFCO_PLUGIN_URL', untrailingslashit( plugin_dir_url( WFCO_PLUGIN_FILE ) ) );
$this->admin_path = WFCO_PLUGIN_DIR;
$this->admin_url = WFCO_PLUGIN_URL;
add_action( 'admin_enqueue_scripts', array( $this, 'include_global_assets' ), 98 );
$should_include = apply_filters( 'wfco_include_connector', false );
if ( false === $should_include ) {
return;
}
$this->initialize_connector();
}
private function initialize_connector() {
include_once( $this->admin_path . '/class-wfco-connector.php' ); //phpcs:ignore WordPressVIPMinimum.Files.IncludingFile.UsingVariable
include_once( $this->admin_path . '/class-wfco-call.php' ); //phpcs:ignore WordPressVIPMinimum.Files.IncludingFile.UsingVariable
include_once( $this->admin_path . '/class-wfco-load-connectors.php' ); //phpcs:ignore WordPressVIPMinimum.Files.IncludingFile.UsingVariable
include_once( $this->admin_path . '/class-wfco-common.php' ); //phpcs:ignore WordPressVIPMinimum.Files.IncludingFile.UsingVariable
include_once( $this->admin_path . '/class-wfco-db.php' ); //phpcs:ignore WordPressVIPMinimum.Files.IncludingFile.UsingVariable
include_once( $this->admin_path . '/class-wfco-connector-api.php' ); //phpcs:ignore WordPressVIPMinimum.Files.IncludingFile.UsingVariable
WFCO_Common::init();
}
public static function get_instance() {
if ( null === self::$ins ) {
self::$ins = new self;
}
return self::$ins;
}
public static function get_plugins() {
return apply_filters( 'all_plugins', get_plugins() );
}
public static function get_oauth_connector() {
$oauth_connectors = [];
$all_connector = WFCO_Admin::get_available_connectors();
if ( empty( $all_connector ) ) {
return $oauth_connectors;
}
foreach ( $all_connector as $addons ) {
if ( empty( $addons ) ) {
continue;
}
foreach ( $addons as $addons_slug => $addon ) {
if ( $addon->is_activated() ) {
$instance = $addons_slug::get_instance();
if ( $instance->is_oauth() ) {
$oauth_connectors[] = $addons_slug;
}
}
}
}
return $oauth_connectors;
}
public static function get_available_connectors( $type = '' ) {
$woofunnels_cache_object = WooFunnels_Cache::get_instance();
$woofunnels_transient_obj = WooFunnels_Transient::get_instance();
$data = $woofunnels_cache_object->get_cache( 'get_available_connectors' );
if ( empty( $data ) ) {
$data = $woofunnels_transient_obj->get_transient( 'get_available_connectors' );
}
if ( ! empty( $data ) && is_array( $data ) ) {
$data = apply_filters( 'wfco_connectors_loaded', $data );
return self::load_connector_screens( $data, $type );
}
$connector_api = new WFCO_Connector_api();
$response_data = $connector_api->set_action( 'get_available_connectors' )->get()->get_package();
if ( is_array( $response_data ) ) {
$woofunnels_transient_obj->set_transient( 'get_available_connectors', $response_data, 3 * HOUR_IN_SECONDS );
}
$response_data = apply_filters( 'wfco_connectors_loaded', $response_data );
if ( '' !== $type ) {
return isset( $response_data[ $type ] ) ? $response_data[ $type ] : [];
}
return self::load_connector_screens( $response_data, $type );
}
private static function load_connector_screens( $response_data, $type = '' ) {
foreach ( $response_data as $slug => $data ) {
$connectors = $data['connectors'];
foreach ( $connectors as $c_slug => $connector ) {
$connector['type'] = $slug;
if ( isset( $data['source'] ) && ! empty( $data['source'] ) ) {
$connector['source'] = $data['source'];
}
if ( isset( $data['file'] ) && ! empty( $data['file'] ) ) {
$connector['file'] = $data['file'];
}
if ( isset( $data['support'] ) && ! empty( $data['support'] ) ) {
$connector['support'] = $data['support'];
}
if ( isset( $data['connector_class'] ) && ! empty( $data['connector_class'] ) ) {
$connector['connector_class'] = $data['connector_class'];
}
WFCO_Connector_Screen_Factory::create( $c_slug, $connector );
}
}
return WFCO_Connector_Screen_Factory::getAll( $type );
}
public static function get_error_message() {
$errors = [];
$errors[100] = __( 'Connector not found', 'woofunnels' ); // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
$errors[101] = __( 'FunnelKit Automations license is required in order to install a connector', 'woofunnels' ); // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
$errors[102] = __( 'FunnelKit Automations license is invalid, kindly contact woofunnels team.', 'woofunnels' ); // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
$errors[103] = __( 'FunnelKit Automations license is expired, kindly renew and activate it first.', 'woofunnels' ); // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
return $errors;
}
public static function js_text() {
$data = array(
// phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'text_copied' => __( 'Text Copied', 'woofunnels' ),
// phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'sync_title' => __( 'Sync Connector', 'woofunnels' ),
// phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'sync_text' => __( 'All the data of this Connector will be Synced.', 'woofunnels' ),
// phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'sync_wait' => __( 'Please Wait...', 'woofunnels' ),
// phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'sync_progress' => __( 'Sync in progress...', 'woofunnels' ),
// phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'sync_success_title' => __( 'Connector Synced', 'woofunnels' ),
// phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'sync_success_text' => __( 'We have detected change in the connector during syncing. Please re-save the Automations.', 'woofunnels' ),
// phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'oops_title' => __( 'Oops', 'woofunnels' ),
// phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'oops_text' => __( 'There was some error. Please try again later.', 'woofunnels' ),
// phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'delete_int_title' => __( 'There was some error. Please try again later.', 'woofunnels' ),
// phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'delete_int_text' => __( 'There was some error. Please try again later.', 'woofunnels' ),
// phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'update_int_prompt_title' => __( 'Connector Updated', 'woofunnels' ),
// phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'update_int_prompt_text' => __( 'We have detected change in the connector during updating. Please re-save the Automations.', 'woofunnels' ),
// phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'delete_int_prompt_title' => __( 'Disconnecting Connector?', 'woofunnels' ),
// phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'delete_int_prompt_text' => __( 'All the action, tasks, logs of this connector will be deleted.', 'woofunnels' ),
// phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'delete_int_wait_title' => __( 'Please Wait...', 'woofunnels' ),
// phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'delete_int_wait_text' => __( 'Disconnecting the connector ...', 'woofunnels' ),
// phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'delete_int_success' => __( 'Connector Disconnected', 'woofunnels' ),
// phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'update_btn' => __( 'Update', 'woofunnels' ),
// phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'save_progress' => __( 'Saving in progress...', 'woofunnels' ),
// phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'update_btn_process' => __( 'Updating...', 'woofunnels' ),
// phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'connect_btn_process' => __( 'Connecting...', 'woofunnels' ),
// phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'install_success_title' => __( 'Connector Installed Successfully', 'woofunnels' ),
// phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'connect_success_title' => __( 'Connected Successfully', 'woofunnels' ),
);
return $data;
}
public function get_admin_url() {
return plugin_dir_url( WFCO_PLUGIN_FILE ) . 'admin';
}
public function include_global_assets() {
wp_enqueue_script( 'wfco-admin-ajax', $this->admin_url . '/assets/js/wfco-admin-ajax.js', array(), WooFunnel_Loader::$version );
wp_localize_script( 'wfco-admin-ajax', 'bwf_secure', [
'nonce' => wp_create_nonce( 'bwf_secure_key' ),
] );
}
public function tooltip( $text ) {
?>
<span class="wfco-help"><i class="icon"></i><div class="helpText"><?php echo $text; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></div></span>
<?php
}
}
}

View File

@@ -0,0 +1,175 @@
<?php
if ( ! class_exists( 'WFCO_Call' ) ) {
#[AllowDynamicProperties]
abstract class WFCO_Call {
protected $data = array();
protected $allowed_responses = array( 200, 201, 202 );
protected $connector_slug = null;
protected $required_fields = array();
protected $missing_field = false;
public function get_slug() {
return sanitize_title( get_class( $this ) );
}
public function get_connector_slug() {
return $this->connector_slug;
}
public function set_connector_slug( $slug ) {
$this->connector_slug = $slug;
}
public function get_random_api_error() {
return __( 'Api Error: No response from API', 'woofunnels' ); // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
}
public function process() {
return [];
}
/**
* Checks the required fields for every action
*
* @param $data
* @param $required_fields
*
* @return bool
*/
public function check_fields( $data, $required_fields ) {
$failed = false;
foreach ( $required_fields as $single_field ) {
$failed = ! isset( $data[ $single_field ] );
/** Existence Checking */
$failed = $failed || ( is_array( $data[ $single_field ] ) && empty( $data[ $single_field ] ) );
/** Array Checking */
$failed = $failed || ( is_null( $data[ $single_field ] ) || '' === $data[ $single_field ] );
/** Null or Empty String Checking */
if ( true === $failed ) {
$this->missing_field = $single_field;
break;
}
}
return ! $failed;
}
/**
* Return the error
*
* @return array
*/
public function show_fields_error() {
return array(
'response' => 502,
'body' => array( 'Required Field Missing' . ( false !== $this->missing_field ? ' : ' . $this->missing_field : '' ) ),
);
}
/**
* Set the data for every action
*
* @param $data
*/
public function set_data( $data ) {
$data = apply_filters( 'modify_set_data', $data );
$this->data = $data;
}
/**
* Sends a wp remote call to Third party softwares.
*
* @param $url
* @param array $params
* @param int $req_method
*
* @return array|mixed|object|string
*/
public function make_wp_requests( $url, $params = array(), $headers = array(), $req_method = 1 ) {
$body = array(
'response' => 500,
'body' => array( __( 'CURL Error', 'woofunnels' ) ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
);
// $req_method
// 1 stands for get
// 2 stands for post
// 3 stands for delete
$args = array(
'timeout' => 45,
'httpversion' => '1.0',
'blocking' => true,
'body' => $params,
);
if ( is_array( $headers ) && count( $headers ) > 0 ) {
$args['headers'] = $headers;
}
switch ( $req_method ) {
case 2:
$args['method'] = 'POST';
break;
case 3:
$args['method'] = 'DELETE';
break;
case 4:
$args['method'] = 'PUT';
break;
case 5:
$args['method'] = 'PATCH';
break;
default:
$args['method'] = 'GET';
break;
}
$response = wp_remote_request( $url, $args );
if ( ! is_wp_error( $response ) ) {
$body = wp_remote_retrieve_body( $response );
$headers = wp_remote_retrieve_headers( $response );
if ( $this->is_json( $body ) ) {
$body = json_decode( $body, true );
}
$body = maybe_unserialize( $body );
if ( in_array( $response['response']['code'], $this->allowed_responses, true ) ) {
$response_code = 200;
} else {
$response_code = $response['response']['code'];
}
$body = array(
'response' => intval( $response_code ),
'body' => $body,
'headers' => $headers,
);
return $body;
}
$body['body'] = [ $response->get_error_message() ];
return $body;
}
/**
* check if a string is json or not
*
* @param $string
*
* @return bool
*/
public function is_json( $string ) {
json_decode( $string );
return ( json_last_error() === JSON_ERROR_NONE );
}
}
}

View File

@@ -0,0 +1,640 @@
<?php
if ( ! class_exists( 'WFCO_Common' ) ) {
#[AllowDynamicProperties]
class WFCO_Common {
public static $ins = null;
public static $http;
public static $connectors_saved_data = array();
public static $saved_data = false;
public static function init() {
add_filter( 'bwf_add_db_table_schema', [ __CLASS__, 'create_db_tables' ], 10, 2 );
}
public static function get_instance() {
if ( null === self::$ins ) {
self::$ins = new self;
}
return self::$ins;
}
/**
* Create required tables
*/
public static function create_db_tables( $args, $tables ) {
$max_index_length = 191;
if ( $tables['version'] !== BWF_DB_VERSION || ! in_array( 'wfco_connectors', $tables['tables'], true ) ) {
$args[] = [
'name' => 'wfco_connectors',
'schema' => "CREATE TABLE `{table_prefix}wfco_connectors` (
ID bigint(20) unsigned NOT NULL auto_increment,
last_sync datetime NOT NULL default '0000-00-00 00:00:00',
slug varchar(255) default NULL,
status tinyint(1) not null default 0 COMMENT '1 - Active 2 - Inactive',
PRIMARY KEY (ID),
KEY slug (slug($max_index_length)),
KEY status (status)
) {table_collate};",
];
}
if ( $tables['version'] !== BWF_DB_VERSION || ! in_array( 'wfco_connectormeta', $tables['tables'], true ) ) {
$args[] = [
'name' => 'wfco_connectormeta',
'schema' => "CREATE TABLE `{table_prefix}wfco_connectormeta` (
ID bigint(20) unsigned NOT NULL auto_increment,
connector_id bigint(20) unsigned NOT NULL default '0',
meta_key varchar(255) default NULL,
meta_value longtext,
PRIMARY KEY (ID),
KEY connector_id (connector_id),
KEY meta_key (meta_key($max_index_length))
) {table_collate};",
];
}
return $args;
}
/**
* Send remote call
*
* @param $api_url
* @param $data
* @param string $method_type
*
* @return array|mixed|null|object|string
*/
public static function send_remote_call( $api_url, $data, $method_type = 'post' ) {
if ( 'get' === $method_type ) {
$httpPostRequest = self::http()->get( $api_url, array(
'body' => $data,
'sslverify' => false,
'timeout' => 30,
) );
} else {
$httpPostRequest = self::http()->post( $api_url, array(
'body' => $data,
'sslverify' => false,
'timeout' => 30,
) );
}
if ( isset( $httpPostRequest->errors ) ) {
$response = null;
} elseif ( isset( $httpPostRequest['body'] ) && '' !== $httpPostRequest['body'] ) {
$body = $httpPostRequest['body'];
$response = json_decode( $body, true );
} else {
$response = 'No result';
}
return $response;
}
public static function http() {
if ( self::$http === null ) {
self::$http = new WP_Http();
}
return self::$http;
}
/**
* Save connector data
*
* @param $data
* @param $slug
* @param $status
*
* @return int
*/
public static function save_connector_data( $data, $slug, $status ) {
$settings = array();
$settings['last_sync'] = current_time( 'mysql', 1 );
$settings['slug'] = $slug;
$settings['status'] = $status;
WFCO_Model_Connectors::insert( $settings );
$connector_id = WFCO_Model_Connectors::insert_id();
foreach ( $data as $key => $val ) {
$meta_data = array();
$meta_data['connector_id'] = $connector_id;
$meta_data['meta_key'] = $key;
$meta_data['meta_value'] = maybe_serialize( $val );
WFCO_Model_ConnectorMeta::insert( $meta_data );
}
return $connector_id;
}
/**
* get all connectors saved data for global access
*/
public static function get_connectors_data() {
$temp = array();
$temp_arr = array();
if ( false === self::$saved_data ) {
$response = WFCO_Model_Connectors::get_results( 'SELECT * FROM {table_name}' );
if ( is_array( $response ) && count( $response ) > 0 ) {
$connector_ids = array_column( $response, 'ID' );
$meta = WFCO_Model_ConnectorMeta::get_connectors_meta( $connector_ids );
foreach ( $response as $connector ) {
$temp[ $connector['slug'] ]['id'] = $connector['ID'];
$temp[ $connector['slug'] ]['last_sync'] = $connector['last_sync'];
$temp[ $connector['slug'] ]['status'] = $connector['status'];
$settings_meta = isset( $meta[ $connector['ID'] ] ) ? $meta[ $connector['ID'] ] : [];
$temp_arr[ $connector['slug'] ] = array_merge( $temp[ $connector['slug'] ], $settings_meta );
}
}
self::$saved_data = $temp_arr;
} else {
$temp_arr = self::$saved_data;
}
self::$connectors_saved_data = $temp_arr;
}
public static function get_metakey_value( $all_meta, $meta_key, $primary_id = null, $primary_key_name = null ) {
$value = null;
foreach ( $all_meta as $value1 ) {
if ( ! is_null( $primary_id ) ) {
if ( $value1[ $primary_key_name ] == $primary_id ) {
if ( $meta_key === $value1['meta_key'] ) {
$value = maybe_unserialize( $value1[ $meta_key ] );
break;
}
}
}
if ( $meta_key === $value1['meta_key'] ) {
$value = maybe_unserialize( $value1['meta_value'] );
break;
}
}
return $value;
}
/**
* update connector data
*
* @param array $new_data
*/
public static function update_connector_data( $new_data = array(), $connector_id = 0 ) {
global $wpdb;
$data = array();
$data['last_sync'] = current_time( 'mysql', 1 );
$where['ID'] = $connector_id;
WFCO_Model_Connectors::update( $data, $where );
$sql_query = 'DELETE from {table_name} where connector_id = %d';
$sql_query = $wpdb->prepare( $sql_query, $connector_id ); //phpcs:ignore WordPress.DB.PreparedSQL
WFCO_Model_ConnectorMeta::delete_multiple( $sql_query );
foreach ( $new_data as $key => $val ) {
$meta_data = array();
$meta_data['connector_id'] = $connector_id;
$meta_data['meta_key'] = $key;
$meta_data['meta_value'] = maybe_serialize( $val );
WFCO_Model_ConnectorMeta::insert( $meta_data );
}
}
public static function is_load_admin_assets( $screen_type = 'all' ) {
$screen = get_current_screen();
if ( 'all' === $screen_type ) {
if ( filter_input( INPUT_GET, 'page' ) === 'autonami' ) {
return true;
}
} elseif ( 'all' === $screen_type || 'settings' === $screen_type ) {
if ( filter_input( INPUT_GET, 'page' ) === 'autonami' && filter_input( INPUT_GET, 'tab' ) === 'settings' ) {
return true;
}
}
return apply_filters( 'wfco_enqueue_scripts', false, $screen_type, $screen );
}
public static function array_flatten( $array ) {
if ( ! is_array( $array ) ) {
return false;
}
$result = iterator_to_array( new RecursiveIteratorIterator( new RecursiveArrayIterator( $array ) ), false );
return $result;
}
public static function pr( $arr ) {
echo '<pre>';
print_r( $arr );
echo '</pre>';
}
public static function slugify_classname( $class_name ) {
$new_class_name = self::custom_sanitize_title( $class_name );
$new_class_name = str_replace( '_', '-', $new_class_name );
return $new_class_name;
}
/**
* Custom sanitize title method to avoid conflicts with WordPress hooks on sanitize_title
*
* @param string $title The title to sanitize
* @return string The sanitized title
*/
private static function custom_sanitize_title( $title ) {
$title = remove_accents( $title );
$title = sanitize_title_with_dashes( $title );
return $title;
}
/**
* Recursive Un-serialization based on WP's is_serialized();
*
* @param $val
*
* @return mixed|string
* @see is_serialized()
*/
public static function unserialize_recursive( $val ) {
/**$pattern = "/.*\{(.*)\}/";*/
if ( is_serialized( $val ) ) {
$val = trim( $val );
$ret = maybe_unserialize( $val );
if ( is_array( $ret ) ) {
foreach ( $ret as &$r ) {
$r = self::unserialize_recursive( $r );
}
}
return $ret;
} elseif ( is_array( $val ) ) {
foreach ( $val as &$r ) {
$r = self::unserialize_recursive( $r );
}
return $val;
} else {
return $val;
}
}
public static function get_option() {
return;
}
public static function active_class( $trigger_slug ) {
if ( self::get_current_trigger() === $trigger_slug ) {
return 'current';
}
return '';
}
public static function get_current_trigger() {
if ( 'autonami' === filter_input( INPUT_GET, 'page', FILTER_UNSAFE_RAW ) && filter_input( INPUT_GET, 'status', FILTER_UNSAFE_RAW ) ) {
return filter_input( INPUT_GET, 'status', FILTER_UNSAFE_RAW );
}
return 'all';
}
public static function string2hex( $string ) {
$hex = '';
for ( $i = 0; $i < strlen( $string ); $i ++ ) {
$hex .= dechex( ord( $string[ $i ] ) );
}
return $hex;
}
public static function maybe_filter_boolean_strings( $options ) {
$cloned_option = $options;
foreach ( $options as $key => $value ) {
if ( is_object( $options ) ) {
if ( $value === 'true' || $value === true ) {
$cloned_option->$key = true;
}
if ( $value === 'false' || $value === false ) {
$cloned_option->$key = false;
}
} elseif ( is_array( $options ) ) {
if ( $value === 'true' || $value === true ) {
$cloned_option[ $key ] = true;
}
if ( $value === 'false' || $value === false ) {
$cloned_option[ $key ] = false;
}
}
}
return $cloned_option;
}
public static function is_add_on_exist( $add_on = 'MultiProduct' ) {
$status = false;
if ( class_exists( 'WFCO_' . $add_on ) ) {
$status = true;
}
return $status;
}
public static function get_date_format() {
return get_option( 'date_format', '' ) . ' ' . get_option( 'time_format', '' );
}
public static function between( $needle, $that, $inthat ) {
return self::before( $that, self::after( $needle, $inthat ) );
}
public static function before( $needle, $inthat ) {
return substr( $inthat, 0, strpos( $inthat, $needle ) );
}
public static function after( $needle, $inthat ) {
if ( ! is_bool( strpos( $inthat, $needle ) ) ) {
return substr( $inthat, strpos( $inthat, $needle ) + strlen( $needle ) );
}
}
public static function clean_ascii_characters( $content ) {
if ( '' === $content ) {
return $content;
}
$content = str_replace( '%', '_', $content );
$content = str_replace( '!', '_', $content );
$content = str_replace( '\"', '_', $content );
$content = str_replace( '#', '_', $content );
$content = str_replace( '$', '_', $content );
$content = str_replace( '&', '_', $content );
$content = str_replace( '(', '_', $content );
$content = str_replace( ')', '_', $content );
$content = str_replace( '(', '_', $content );
$content = str_replace( '*', '_', $content );
$content = str_replace( ',', '_', $content );
$content = str_replace( '', '_', $content );
$content = str_replace( '.', '_', $content );
$content = str_replace( '/', '_', $content );
return $content;
}
/**
* Function to get timezone string by checking WordPress timezone settings
* @return mixed|string|void
*/
public static function wc_timezone_string() {
// if site timezone string exists, return it
if ( $timezone = get_option( 'timezone_string' ) ) {
return $timezone;
}
// get UTC offset, if it isn't set then return UTC
if ( 0 === ( $utc_offset = get_option( 'gmt_offset', 0 ) ) ) {
return 'UTC';
}
// get timezone using offset manual
return self::get_timezone_by_offset( $utc_offset );
}
/**
* Function to get timezone string based on specified offset
*
* @param $offset
*
* @return string
*/
public static function get_timezone_by_offset( $offset ) {
switch ( $offset ) {
case '-12':
return 'GMT-12';
break;
case '-11.5':
return 'Pacific/Niue'; // 30 mins wrong
break;
case '-11':
return 'Pacific/Niue';
break;
case '-10.5':
return 'Pacific/Honolulu'; // 30 mins wrong
break;
case '-10':
return 'Pacific/Tahiti';
break;
case '-9.5':
return 'Pacific/Marquesas';
break;
case '-9':
return 'Pacific/Gambier';
break;
case '-8.5':
return 'Pacific/Pitcairn'; // 30 mins wrong
break;
case '-8':
return 'Pacific/Pitcairn';
break;
case '-7.5':
return 'America/Hermosillo'; // 30 mins wrong
break;
case '-7':
return 'America/Hermosillo';
break;
case '-6.5':
case '-6':
return 'America/Belize';
break;
case '-5.5':
return 'America/Belize'; // 30 mins wrong
break;
case '-5':
return 'America/Panama';
break;
case '-4.5':
return 'America/Lower_Princes'; // 30 mins wrong
break;
case '-4':
return 'America/Curacao';
break;
case '-3.5':
return 'America/Paramaribo'; // 30 mins wrong
break;
case '-3':
return 'America/Recife';
break;
case '-2.5':
return 'America/St_Johns';
break;
case '-2':
return 'America/Noronha';
break;
case '-1.5':
return 'Atlantic/Cape_Verde'; // 30 mins wrong
break;
case '-1':
return 'Atlantic/Cape_Verde';
break;
case '+1':
return 'Africa/Luanda';
break;
case '+1.5':
return 'Africa/Mbabane'; // 30 mins wrong
break;
case '+2':
return 'Africa/Harare';
break;
case '+2.5':
return 'Indian/Comoro'; // 30 mins wrong
break;
case '+3':
return 'Asia/Baghdad';
break;
case '+3.5':
return 'Indian/Mauritius'; // 30 mins wrong
break;
case '+4':
return 'Indian/Mauritius';
break;
case '+4.5':
return 'Asia/Kabul';
break;
case '+5':
return 'Indian/Maldives';
break;
case '+5.5':
return 'Asia/Kolkata';
break;
case '+5.75':
return 'Asia/Kathmandu';
break;
case '+6':
return 'Asia/Urumqi';
break;
case '+6.5':
return 'Asia/Yangon';
break;
case '+7':
return 'Antarctica/Davis';
break;
case '+7.5':
return 'Asia/Jakarta'; // 30 mins wrong
break;
case '+8':
return 'Asia/Manila';
break;
case '+8.5':
return 'Asia/Pyongyang';
break;
case '+8.75':
return 'Australia/Eucla';
break;
case '+9':
return 'Asia/Tokyo';
break;
case '+9.5':
return 'Australia/Darwin';
break;
case '+10':
return 'Australia/Brisbane';
break;
case '+10.5':
return 'Australia/Lord_Howe';
break;
case '+11':
return 'Antarctica/Casey';
break;
case '+11.5':
return 'Pacific/Auckland'; // 30 mins wrong
break;
case '+12':
return 'Pacific/Wallis';
break;
case '+12.75':
return 'Pacific/Chatham';
break;
case '+13':
return 'Pacific/Fakaofo';
break;
case '+13.75':
return 'Pacific/Chatham'; // 1 hr wrong
break;
case '+14':
return 'Pacific/Kiritimati';
break;
default:
return 'UTC';
break;
}
}
/**
* Generate random string
*
* @param int $length
*
* @return string
*/
public static function generateRandomString( $length = 5 ) {
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$charactersLength = strlen( $characters );
$randomString = '';
for ( $i = 0; $i < $length; $i ++ ) {
$randomString .= $characters[ rand( 0, $charactersLength - 1 ) ];
}
return $randomString;
}
/**
* Get all merge tags from string
*
* @param $text
*
* @return array|null
*/
public static function get_merge_tags_from_text( $text ) {
$merge_tags = null;
preg_match_all( '/\{{(.*?)\}}/', $text, $more_merge_tags );
if ( is_array( $more_merge_tags[1] ) && count( $more_merge_tags[1] ) > 0 ) {
$merge_tags = $more_merge_tags[1];
}
return $merge_tags;
}
public static function get_single_connector_data( $connector_slug, $meta_key = null ) {
$data_to_return = [];
if ( is_null( $meta_key ) ) {
if ( isset( WFCO_Common::$connectors_saved_data[ $connector_slug ] ) ) {
$data_to_return = WFCO_Common::$connectors_saved_data[ $connector_slug ];
return $data_to_return;
}
}
if ( isset( WFCO_Common::$connectors_saved_data[ $connector_slug ][ $meta_key ] ) ) {
$data_to_return = WFCO_Common::$connectors_saved_data[ $connector_slug ][ $meta_key ];
}
return $data_to_return;
}
public static function get_call_object( $connector_slug, $call_slug ) {
$all_connectors = WFCO_Load_Connectors::get_all_connectors();
return $all_connectors[ $connector_slug ][ $call_slug ];
}
}
}

View File

@@ -0,0 +1,113 @@
<?php
if ( ! class_exists( 'WFCO_Connector_api' ) ) {
#[AllowDynamicProperties]
class WFCO_Connector_api {
private $license = '';
private $connector = '';
private $action = 'find_connector';
private $package = [];
private $api_params = [];
private $api_url = 'https://myaccount.funnelkit.com/';
private $response_data = [];
public function __construct( $license = '', $connector = '', $action = 'find_connector' ) {
if ( '' !== $license ) {
$this->license = trim( $license );
}
if ( '' !== $connector ) {
$this->connector = trim( $connector );
}
if ( '' !== $action ) {
$this->action = trim( $action );
}
$this->api_url = add_query_arg( array(
'wc-api' => 'am-connector',
), $this->api_url );
$this->api_params = [
'connector_api' => 'yes',
'action' => $this->action,
'data' => [],
];
}
public function set_action( $action ) {
$this->action = trim( $action );
return $this;
}
/**
* @param array $data Associative array
* @param bool $reset
*/
public function set_data( $data = [], $reset = false ) {
if ( is_array( $data ) && count( $data ) > 0 ) {
foreach ( $data as $key => $d ) {
$this->api_params['data'][ $key ] = $d;
}
}
return $this;
}
public function get_license() {
return $this->license;
}
public function get_connector() {
return $this->connector;
}
public function get_package() {
return $this->package;
}
public function create_license() {
$this->find_connector();
}
public function find_connector() {
$this->api_params['data']['connector'] = $this->connector;
$this->api_params['data']['license'] = $this->license;
$this->fetch_data();
return $this;
}
private function fetch_data() {
$this->api_params['action'] = $this->action;
$this->api_params['data']['platform'] = home_url();
$request = wp_remote_post( $this->api_url, [
'timeout' => 15,
'sslverify' => false,
'body' => $this->api_params,
] );
if ( ! is_wp_error( $request ) ) {
$this->response_data = json_decode( wp_remote_retrieve_body( $request ), true );
}
if ( ! empty( $this->response_data ) ) {
$this->package = $this->response_data;
}
}
public function get() {
$this->fetch_data();
return $this;
}
}
}

View File

@@ -0,0 +1,27 @@
<?php
if ( ! class_exists( 'WFCO_Connector_Screen_Factory' ) ) {
#[AllowDynamicProperties]
abstract class WFCO_Connector_Screen_Factory {
private static $screens = [];
public static function create( $slug, $data ) {
$type = $data['type'];
self::$screens[ $type ][ $slug ] = new WFCO_Connector_Screen( $slug, $data );
}
public static function get( $screen ) {
return self::$screens[ $screen ];
}
public static function getAll( $type = '' ) {
if ( empty( $type ) ) {
return self::$screens;
}
return isset( self::$screens[ $type ] ) ? self::$screens[ $type ] : [];
}
}
}

View File

@@ -0,0 +1,106 @@
<?php
if ( ! class_exists( 'WFCO_Connector_Screen' ) ) {
#[AllowDynamicProperties]
class WFCO_Connector_Screen {
private $slug = '';
private $image = '';
private $name = '';
private $desc = '';
private $is_active = false;
private $activation_url = '';
private $file = '';
private $connector_class = '';
private $source = '';
private $support = [];
private $type = 'FunnelKit Automations';
private $show_setting_btn = true;
public function __construct( $slug, $data ) {
$this->slug = $slug;
if ( is_array( $data ) && count( $data ) > 0 ) {
foreach ( $data as $property => $val ) {
if ( is_array( $val ) ) {
$this->{$property} = $val;
continue;
}
if ( is_bool( $val ) || in_array( $val, [ 'true', 'false' ], true ) ) {
$this->{$property} = (bool) $val;
continue;
}
$this->{$property} = trim( $val );
}
}
}
public function get_logo() {
return $this->image;
}
public function is_active() {
return $this->is_active;
}
public function is_installed() {
}
public function activation_url() {
return $this->activation_url;
}
public function get_path() {
return $this->file;
}
public function get_class() {
return $this->connector_class;
}
public function get_source() {
return $this->source;
}
public function get_support() {
return $this->support;
}
public function get_slug() {
return $this->slug;
}
public function get_type() {
return $this->type;
}
public function get_name() {
return $this->name;
}
public function get_desc() {
return $this->desc;
}
public function is_activated() {
if ( class_exists( $this->connector_class ) ) {
return true;
}
return false;
}
public function show_setting_btn() {
return $this->show_setting_btn;
}
public function is_present() {
$plugins = get_plugins();
$file = trim( $this->file );
if ( '' !== $this->file && isset( $plugins[ $file ] ) ) {
return true;
}
return false;
}
}
}

View File

@@ -0,0 +1,265 @@
<?php
if ( ! class_exists( 'BWF_CO' ) ) {
#[AllowDynamicProperties]
abstract class BWF_CO {
public static $GET = 1;
public static $POST = 2;
public static $DELETE = 3;
public static $PUT = 4;
public static $PATCH = 5;
/** @var string Connector folder directory */
public $dir = __DIR__;
/** @var string Autonami integration class name */
public $autonami_int_slug = '';
/** @var null Nice name */
public $nice_name = null;
/** @var bool Connector has settings */
public $is_setting = true;
/** @var string Public directory URL */
protected $connector_url = '';
/** @var array Connector keys which are tracked during syncing and update */
protected $keys_to_track = [];
protected $form_req_keys = [];
protected $sync = false;
protected $is_oauth = false;
/** @var bool Connector is available for pro: default true */
public $is_pro = true;
/** @var bool If connector is configured through a direct url */
public $direct_connect = false;
public $is_new = 0;
protected $priority = 10;
/**
* Loads all calls of current connector
*/
public function load_calls() {
$resource_dir = $this->dir . '/calls';
if ( @file_exists( $resource_dir ) ) {
foreach ( glob( $resource_dir . '/class-*.php' ) as $filename ) {
$call_class = require_once( $filename );
if ( ( is_object( $call_class ) || is_string( $call_class ) ) && method_exists( $call_class, 'get_instance' ) ) {
$call_obj = $call_class::get_instance();
$call_obj->set_connector_slug( $this->get_slug() );
WFCO_Load_Connectors::register_calls( $call_obj );
}
}
}
do_action( 'bwfan_' . $this->get_slug() . '_actions_loaded' );
}
public function get_slug() {
return sanitize_title( get_class( $this ) );
}
/**
* Handles the settings form submission
*
* @param $data
* @param string $type
*
* @return $array
*/
public function handle_settings_form( $data, $type = 'save' ) {
$old_data = [];
$new_data = [];
$status = 'failed';
$resp = array(
'status' => $status,
'id' => 0,
'message' => '',
);
/** Validating form settings */
if ( 'sync' !== $type ) {
$is_valid = $this->validate_settings_fields( $data, $type );
if ( false === $is_valid ) {
$resp['message'] = $this->get_connector_messages( 'connector_settings_missing' );
return $resp;
}
}
switch ( $type ) {
case 'save':
$new_data = $this->get_api_data( $data );
if ( is_array( $new_data['api_data'] ) && count( $new_data['api_data'] ) > 0 && isset( $new_data['status'] ) && 'failed' !== $new_data['status'] ) {
$id = WFCO_Common::save_connector_data( $new_data['api_data'], $this->get_slug(), 1 );
$resp['id'] = $id;
$resp['message'] = $this->get_connector_messages( 'connector_saved' );
}
break;
case 'update':
$saved_data = WFCO_Common::$connectors_saved_data;
$old_data = $saved_data[ $this->get_slug() ];
$new_data = $this->get_api_data( $data );
if ( isset( $new_data['status'] ) && 'success' === $new_data['status'] ) {
$resp['message'] = $this->get_connector_messages( 'connector_updated' );
}
break;
case 'sync':
$saved_data = WFCO_Common::$connectors_saved_data;
$old_data = $saved_data[ $this->get_slug() ];
$new_data = $this->get_api_data( $old_data );
if ( isset( $new_data['status'] ) && 'success' === $new_data['status'] ) {
$resp['message'] = $this->get_connector_messages( 'connector_synced' );
}
break;
}
$resp['status'] = $this->get_response_status( $new_data, 'status' );
if ( '' === $resp['message'] && isset( $new_data['message'] ) && '' !== $new_data['message'] ) {
$resp['message'] = $new_data['message'];
}
$resp['data_changed'] = 0;
/** Return for save type case */
if ( 'save' === $type ) {
return $resp;
}
/** Assigning ID */
$resp['id'] = $data['id'];
/** Saving new data */
WFCO_Common::update_connector_data( $new_data['api_data'], $resp['id'] );
/** Tracking if data changed */
$is_data_changed = $this->track_sync_changes( $new_data['api_data'], $old_data );
if ( true === $is_data_changed ) {
do_action( 'change_in_connector_data', $this->get_slug() );
$resp['data_changed'] = 1;
}
return $resp;
}
/**
* Validating connector form settings fields, all required fields should be present with values
*
* @param $data
* @param string $type
*
* @return boolean
*
* @todo empty values need to check
*/
protected function validate_settings_fields( $data, $type = 'save' ) {
$available_keys = array_keys( $data );
if ( 'save' !== $type ) {
$available_keys[] = 'id';
}
$diff = array_diff( $this->form_req_keys, $available_keys );
if ( count( $diff ) > 0 ) {
return false;
}
return true;
}
public function get_connector_messages( $key = 'connector_saved' ) {
$messages = array(
'connector_saved' => __( 'Connector saved successfully', 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'connector_synced' => __( 'Connector synced successfully', 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'connector_updated' => __( 'Connector updated successfully', 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'connector_settings_missing' => __( 'Connector settings missing', 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
);
return ( isset( $messages[ $key ] ) ) ? $messages[ $key ] : '';
}
/**
* Get data from the API call, must required function otherwise call
*
* @param $data
*
* @return array
*/
protected function get_api_data( $data ) {
return array(
'status' => 'failed',
'message' => __( 'Connector forgot to override the method - get_api_data.', 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
);
}
public function get_response_status( $data, $key = 'status' ) {
$value = ( isset( $data[ $key ] ) ) ? $data[ $key ] : '';
$value = ( 'status' === $key && empty( $value ) ) ? 'failed' : $value;
return $value;
}
/**
* Track connector old and new data and return if any data change detected.
*
* @param $new_data
* @param $old_data
*
* @return bool
*/
protected function track_sync_changes( $new_data, $old_data ) {
$has_changes = false;
if ( empty( $this->keys_to_track ) || empty( $new_data ) || empty( $old_data ) ) {
return $has_changes;
}
foreach ( $this->keys_to_track as $key ) {
$str1 = isset( $new_data[ $key ] ) ? $new_data[ $key ] : '';
$str2 = isset( $old_data[ $key ] ) ? $old_data[ $key ] : '';
$str1 = is_array( $str1 ) ? wp_json_encode( $str1 ) : $str1;
$str2 = is_array( $str2 ) ? wp_json_encode( $str2 ) : $str2;
$diff = strcmp( $str1, $str2 );
if ( 0 === $diff ) {
continue;
}
$has_changes = true;
break;
}
return $has_changes;
}
public function get_image() {
return $this->connector_url . '/views/logo.png';
}
public function has_settings() {
return $this->is_setting;
}
public function is_syncable() {
return $this->sync;
}
public function is_oauth() {
return $this->is_oauth;
}
/**
* Get the connector loading priority
*
* @return int|mixed
*/
public function get_priority() {
return $this->priority;
}
}
}

View File

@@ -0,0 +1,54 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
if ( ! class_exists( 'WFCO_Db' ) ) {
/**
* Class WFCO_Db
* @package Autonami
* @author XlPlugins
*/
#[AllowDynamicProperties]
class WFCO_Db {
private static $ins = null;
/**
* WFCO_Db constructor.
*/
public function __construct() {
add_action( 'plugins_loaded', [ $this, 'load_db_classes' ], 8 );
}
/**
* Return the object of current class
*
* @return null|WFCO_Db
*/
public static function get_instance() {
if ( null === self::$ins ) {
self::$ins = new self();
}
return self::$ins;
}
/**
* Include all the DB Table files
*/
public static function load_db_classes() {
$connector_dir = __DIR__ . '/db';
foreach ( glob( $connector_dir . '/class-*.php' ) as $_field_filename ) {
$file_data = pathinfo( $_field_filename );
if ( isset( $file_data['basename'] ) && 'index.php' === $file_data['basename'] ) {
continue;
}
require_once( $_field_filename );
}
}
}
if ( class_exists( 'WFCO_Db' ) ) {
WFCO_Db::get_instance();
}
}

View File

@@ -0,0 +1,206 @@
<?php
if ( ! class_exists( 'WFCO_Load_Connectors' ) ) {
#[AllowDynamicProperties]
class WFCO_Load_Connectors {
/** @var class instance */
private static $ins = null;
/** @var array All connectors with object */
private static $connectors = array();
/** @var array All calls with object */
private static $registered_calls = array();
/** @var array All calls objects group by connectors */
private static $registered_connectors_calls = array();
public function __construct() {
add_action( 'rest_api_init', [ $this, 'load_connectors_rest_call' ], 8 );
add_action( 'current_screen', [ $this, 'load_connectors_admin' ], 8 );
add_action( 'admin_init', [ $this, 'load_connectors_admin_ajax' ], 8 );
}
/**
* Return class instance
*
* @return class|WFCO_Load_Connectors
*/
public static function get_instance() {
if ( null == self::$ins ) {
self::$ins = new self();
}
return self::$ins;
}
/**
* Include all connectors files directly
*
* @return void
*/
public static function load_connectors_direct() {
do_action( 'wfco_load_connectors' );
}
/**
* Include all connectors files on rest endpoints
*
* @return void
*/
public static function load_connectors_rest_call() {
$rest_route = isset( $_GET['rest_route'] ) ? $_GET['rest_route'] : '';
if ( empty( $rest_route ) ) {
$rest_route = $_SERVER['REQUEST_URI'];
}
if ( empty( $rest_route ) ) {
return;
}
if ( strpos( $rest_route, 'autonami/' ) === false && strpos( $rest_route, 'woofunnel_customer/' ) === false && strpos( $rest_route, 'funnelkit-app' ) === false && strpos( $rest_route, 'autonami-app' ) === false && strpos( $rest_route, 'funnelkit-automations' ) === false && strpos( $rest_route, 'autonami-webhook' ) === false && strpos( $rest_route, 'woofunnels/' ) === false && strpos( $rest_route, '/omapp/' ) === false ) {
return;
}
do_action( 'wfco_load_connectors' );
}
/**
* Include all connectors files on admin screen
*
* @return void
*/
public static function load_connectors_admin() {
$screen = get_current_screen();
if ( ! is_object( $screen ) ) {
return;
}
if ( empty( $screen->id ) || ( 'toplevel_page_autonami' !== $screen->id && 'funnelkit-automations_page_autonami-automations' !== $screen->id ) ) {
return;
}
do_action( 'wfco_load_connectors' );
}
/**
* Include all connectors files on admin ajax call
*
* @return void
*/
public static function load_connectors_admin_ajax() {
if ( ! defined( 'DOING_AJAX' ) || ! DOING_AJAX ) {
return;
}
$ajax_action = $_POST['action'] ?? '';
if ( empty( $ajax_action ) ) {
return;
}
$array = [ 'wfco', 'bwfan', 'bwf_' ];
foreach ( $array as $value ) {
if ( strpos( $ajax_action, $value ) !== false ) {
do_action( 'wfco_load_connectors' );
break;
}
}
}
/**
* Register a connector with their object
* Assign to static property $connectors
* Load connector respective calls
*
* @param $class
*/
public static function register( $class ) {
if ( ! class_exists( $class ) && ! method_exists( $class, 'get_instance' ) ) {
return;
}
$temp_ins = $class::get_instance();
if ( ! $temp_ins instanceof BWF_CO ) {
return;
}
$slug = $temp_ins->get_slug();
self::$connectors[ $slug ] = $temp_ins;
$temp_ins->load_calls();
}
/**
* Register a call with their object
* Assign to static property $registered_calls
* Assign to static property $registered_connectors_calls
*
* @param WFCO_Call $call_obj
*/
public static function register_calls( WFCO_Call $call_obj ) {
if ( method_exists( $call_obj, 'get_instance' ) ) {
$slug = $call_obj->get_slug();
$connector_slug = $call_obj->get_connector_slug();
self::$registered_connectors_calls[ $connector_slug ][ $slug ] = self::$registered_calls[ $slug ] = $call_obj;
}
}
/**
* Return all the connectors with their calls objects
*
* @return array
*/
public static function get_all_connectors() {
return self::$registered_connectors_calls;
}
/**
* Returns Instance of single connector
*
* @param $connector
*
* @return BWF_CO
*/
public static function get_connector( $connector ) {
return isset( self::$connectors[ $connector ] ) ? self::$connectors[ $connector ] : null;
}
/**
* Returns all the active connectors i.e. plugin active
*
* @return array
*/
public static function get_active_connectors() {
return self::$connectors;
}
/**
* Return a call object if call slug is passed.
* Return all calls object if no single call slug passed.
*
* @param string $slug
*
* @return array|mixed
*/
public function get_calls( $slug = '' ) {
if ( empty( $slug ) ) {
return self::$registered_calls;
}
if ( isset( self::$registered_calls[ $slug ] ) ) {
return self::$registered_calls[ $slug ];
}
}
/**
* Return a call object based on the given slug.
*
* @param string $slug call slug
*
* @return WFCO_Call | null
*/
public function get_call( $slug ) {
return ( ! empty( $slug ) && isset( self::$registered_calls[ $slug ] ) ) ? self::$registered_calls[ $slug ] : null;
}
}
/**
* Initiate the class as soon as it is included
*/
WFCO_Load_Connectors::get_instance();
}

View File

@@ -0,0 +1,76 @@
<?php
if ( ! class_exists( 'WFCO_Model_ConnectorMeta' ) ) {
class WFCO_Model_ConnectorMeta extends WFCO_Model {
static $primary_key = 'ID';
public static function get_meta( $id, $key ) {
$rows = self::get_connector_meta( $id );
$value = '';
if ( count( $rows ) > 0 && isset( $rows[ $key ] ) ) {
$value = $rows[ $key ];
}
return $value;
}
public static function get_connector_meta( $id ) {
if ( 0 === $id ) {
return [];
}
global $wpdb;
$table = self::_table();
$sql_query = "SELECT * FROM $table WHERE connector_id =%d";
$sql_query = $wpdb->prepare( $sql_query, $id ); //phpcs:ignore WordPress.DB.PreparedSQL
$result = $wpdb->get_results( $sql_query, ARRAY_A ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
$meta = [];
if ( is_array( $result ) && count( $result ) > 0 ) {
foreach ( $result as $meta_values ) {
$key = $meta_values['meta_key'];
$meta[ $key ] = maybe_unserialize( $meta_values['meta_value'] );
}
}
return $meta;
}
private static function _table() {
global $wpdb;
$table_name = strtolower( get_called_class() );
$table_name = str_replace( 'wfco_model_', 'wfco_', $table_name );
return $wpdb->prefix . $table_name;
}
public static function get_connectors_meta( $ids = [] ) {
$meta = [];
if ( empty( $ids ) || ! is_array( $ids ) ) {
return $meta;
}
global $wpdb;
$table = self::_table();
$count = count( $ids );
$placeholders = array_fill( 0, $count, '%d' );
$placeholders = implode( ', ', $placeholders );
/** Fetching connectors meta - single query */
$query = "Select * FROM $table WHERE connector_id IN ($placeholders)";
$query = $wpdb->prepare( $query, $ids ); // WPCS: unprepared SQL OK
$result = self::get_results( $query );
if ( is_array( $result ) && count( $result ) > 0 ) {
foreach ( $result as $meta_values ) {
$meta[ $meta_values['connector_id'] ][ $meta_values['meta_key'] ] = maybe_unserialize( $meta_values['meta_value'] );
}
}
return $meta;
}
}
}

View File

@@ -0,0 +1,28 @@
<?php
if ( ! class_exists( 'WFCO_Model_Connectors' ) ) {
class WFCO_Model_Connectors extends WFCO_Model {
static $primary_key = 'ID';
public static function count_rows( $dependency = null ) {
global $wpdb;
$table_name = self::_table();
$sql = 'SELECT COUNT(*) FROM ' . $table_name;
if ( 'all' !== filter_input( INPUT_GET, 'status', FILTER_UNSAFE_RAW ) ) {
$status = filter_input( INPUT_GET, 'status', FILTER_UNSAFE_RAW );
$status = ( 'active' === $status ) ? 1 : 2;
$sql = $wpdb->prepare( "SELECT COUNT(*) FROM $table_name WHERE status = %d", $status ); //phpcs:ignore WordPress.DB.PreparedSQL
}
return $wpdb->get_var( $sql ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
}
private static function _table() {
global $wpdb;
$table_name = strtolower( get_called_class() );
$table_name = str_replace( 'wfco_model_', 'wfco_', $table_name );
return $wpdb->prefix . $table_name;
}
}
}

View File

@@ -0,0 +1,2 @@
<?php
# Silence is golden.

View File

@@ -0,0 +1,2 @@
<?php
// Silence is golden.

View File

@@ -0,0 +1,134 @@
<?php
/**
* Contact Controller Class
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'BWF_Contacts' ) ) {
/**
* Class BWF_Contacts
*
*/
#[AllowDynamicProperties]
class BWF_Contacts {
/**
* @var static instance
*/
private static $ins;
/**
* public db_operations $db_operations
*/
public $db_operations;
public $child_entities;
public $cached_contact_obj;
/**
* Get the contact details for the email passed if this uid exits other create a new contact with this email
*
* @param $email
*/
public function __construct() {
$this->db_operations = WooFunnels_DB_Operations::get_instance();
$this->get_registerd_child_entities();
$this->cached_contact_obj = [
'cid' => [],
'uid' => [],
'email' => [],
'wp_id' => [],
'phone' => [],
];
}
/**
* @return mixed|void
*/
public static function get_registerd_child_entities() {
$entities = apply_filters( 'bwf_child_entities', array( 'customer' => 'WooFunnels_Customer' ) );
return $entities;
}
/**
* @return BWF_Contacts
*/
public static function get_instance() {
if ( null === self::$ins ) {
self::$ins = new self;
}
return self::$ins;
}
/**
* Get contacts based on different criteria
*/
public function get_contacts( $args = array() ) {
$default_args = array(
'min_creation_date' => '',
'max_creation_date' => '',
);
$args = wp_parse_args( $args, $default_args );
if ( ! empty( $args['min_creation_date'] ) ) {
$args['min_creation_date'] = strtotime( 'midnight', strtotime( sanitize_text_field( $args['min_creation_date'] ) ) );
}
if ( ! empty( $args['max_creation_date'] ) ) {
$args['max_creation_date'] = strtotime( 'midnight', strtotime( sanitize_text_field( $args['max_creation_date'] ) ) );
}
$customers = $this->db_operations->get_contacts( $args );
return $customers;
}
/**
* get contact by given field
*/
public function get_contact_by( $field, $value ) {
if ( 'id' === $field ) {
return new WooFunnels_Contact( '', '', '', $value );
}
if ( 'wpid' === $field ) {
return new WooFunnels_Contact( $value );
}
if ( 'email' === $field ) {
return new WooFunnels_Contact( '', $value );
}
if ( 'phone' === $field ) {
return new WooFunnels_Contact( '', '', $value );
}
if ( 'uid' === $field ) {
return new WooFunnels_Contact( '', '', '', '', $value );
}
}
/**
* Getting date range
*
* @param $range
*
*/
public function get_date_range( $range ) {
$result = array();
$result['start_date'] = max( strtotime( '-20 years' ), strtotime( sanitize_text_field( $range['start_date'] ) ) );
$result['end_date'] = strtotime( 'midnight', current_time( 'timestamp' ) );
if ( ! empty( $range['end_date'] ) ) {
$result['end_date'] = strtotime( 'midnight', strtotime( sanitize_text_field( $range['end_date'] ) ) );
}
return $result;
}
}
}

View File

@@ -0,0 +1,114 @@
<?php
/**
* Customer Controller Class
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'BWF_Customers' ) ) {
/**
* Class BWF_Customers
*/
#[AllowDynamicProperties]
class BWF_Customers {
/**
* public db_operations $db_operations
*/
public $db_operations;
/**
* Get the customer details for the email passed if this email exits other create a new customer with this email
* BWF_Customers constructor.
*/
public function __construct() {
$this->db_operations = WooFunnels_DB_Operations::get_instance();
}
/**
* Get customers based on different criteria
*
* @param array $args
*
* @return array|object|null
*/
public function get_customers( $args = array() ) {
$default_args = array(
'min_order_count' => 0,
'max_order_count' => 999999,
'min_order_value' => 0,
'max_order_value' => 999999999,
'customer_limit' => - 1,
'min_last_order_date' => '',
'max_last_order_date' => '',
'min_creation_date' => '',
'max_creation_date' => '',
);
$args = wp_parse_args( $args, $default_args );
if ( ! empty( $args['min_last_order_date'] ) ) {
$args['min_last_order_date'] = strtotime( 'midnight', strtotime( sanitize_text_field( $args['min_last_order_date'] ) ) );
}
if ( ! empty( $args['max_last_order_date'] ) ) {
$args['max_last_order_date'] = strtotime( 'midnight', strtotime( sanitize_text_field( $args['max_last_order_date'] ) ) );
}
if ( ! empty( $args['min_creation_date'] ) ) {
$args['min_creation_date'] = strtotime( 'midnight', strtotime( sanitize_text_field( $args['min_creation_date'] ) ) );
}
if ( ! empty( $args['max_creation_date'] ) ) {
$args['max_creation_date'] = strtotime( 'midnight', strtotime( sanitize_text_field( $args['max_creation_date'] ) ) );
}
$customers = $this->db_operations->get_customers( $args );
return $customers;
}
/**
* Get customer by given field
*
* @param $field
* @param $value
*
* @return WooFunnels_Customer
*/
public function get_customer_by( $field, $value ) {
$customer = new stdClass();
if ( 'id' === $field ) {
$customer = $this->db_operations->get_customer_by_customer_id( $value );
}
if ( 'cid' === $field ) {
$customer = $this->db_operations->get_customer_by_cid( $value );
}
$cid = $customer->cid;
return bwf_get_customer( $cid );
}
/**
* Getting date range
*
* @param $range
*
* @return array
*/
public function get_date_range( $range ) {
$result = array();
$result['start_date'] = max( strtotime( '-20 years' ), strtotime( sanitize_text_field( $range['start_date'] ) ) );
$result['end_date'] = strtotime( 'midnight', current_time( 'timestamp' ) );
if ( ! empty( $range['end_date'] ) ) {
$result['end_date'] = strtotime( 'midnight', strtotime( sanitize_text_field( $range['end_date'] ) ) );
}
return $result;
}
}
}

View File

@@ -0,0 +1,426 @@
<?php
/**
* Background Updater
*
* @version 1.7.4
*/
defined( 'ABSPATH' ) || exit;
if ( ! class_exists( 'WP_Async_Request', false ) ) {
include_once dirname( dirname( __FILE__ ) ) . '/libraries/wp-async-request.php';
}
if ( ! class_exists( 'WP_Background_Process', false ) ) {
include_once dirname( dirname( __FILE__ ) ) . '/libraries/wp-background-process.php';
}
if ( ! class_exists( 'WooFunnels_Background_Updater' ) ) {
/**
* WooFunnels_Background_Updater Class.
* Based on WC_Background_Updater concept
*/
#[AllowDynamicProperties]
class WooFunnels_Background_Updater extends WP_Background_Process {
const MAX_SAME_OFFSET_THRESHOLD = 5;
protected $prefix = 'bwf_1';
protected $action = 'updater';
/**
* Initiate new background process.
*
* WooFunnels_Background_Updater constructor.
*/
public function __construct() {
parent::__construct();
}
/**
* Schedule cron healthcheck.
*
* @param array $schedules Schedules.
*
* @return array
*/
public function schedule_cron_healthcheck( $schedules ) {
$interval = apply_filters( $this->identifier . '_cron_interval', 5 );
if ( property_exists( $this, 'cron_interval' ) ) {
$interval = apply_filters( $this->identifier . '_cron_interval', $this->cron_interval );
}
// Adds every 5 minutes to the existing schedules.
$schedules[ $this->identifier . '_cron_interval' ] = array(
'interval' => MINUTE_IN_SECONDS * $interval,
/* translators: %d: interval */
'display' => sprintf( __( 'Every %d minutes', 'woocommerce' ), $interval ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
);
return $schedules;
}
/**
* Handle cron healthcheck
*
* Restart the background process if not already running
* and data exists in the queue.
*/
public function handle_cron_healthcheck() {
if ( $this->is_process_running() ) {
// Background process already running.
return;
}
if ( $this->is_queue_empty() ) {
// No data to process.
$this->clear_scheduled_event();
BWF_Logger::get_instance()->log( 'Scheduled event cleared as queue is empty.', 'woofunnels_indexing' );
return;
}
/**
* We are saving the last 5 offset value, due to any specific reason if last 5 offsets are same then it might be the time to kill the process.
*/
$offsets = $this->get_last_offsets();
if ( self::MAX_SAME_OFFSET_THRESHOLD === count( $offsets ) ) {
$unique = array_unique( $offsets );
if ( 1 === count( $unique ) ) {
$this->kill_process();
BWF_Logger::get_instance()->log( sprintf( 'Offset is stuck from last %d cron jobs, terminating the process.', self::MAX_SAME_OFFSET_THRESHOLD ), 'woofunnels_indexing' );
return;
}
}
$this->manage_last_offsets();
BWF_Logger::get_instance()->log( 'Cron started again!!', 'woofunnels_indexing' );
/**
* Everything looks good, lets roll the indexing
*/
$this->handle();
}
/**
* Overriding parent protected function publically to use outside this class
* @return bool
*/
public function is_process_running() {
return parent::is_process_running();
}
/**
* Is queue empty.
*
* @return bool
*/
protected function is_queue_empty() {
global $wpdb;
$table = $wpdb->options;
$column = 'option_name';
if ( is_multisite() ) {
$table = $wpdb->sitemeta;
$column = 'meta_key';
}
$key = $wpdb->esc_like( $this->identifier . '_batch_' ) . '%';
$count = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM {$table} WHERE {$column} LIKE %s", $key ) ); // @codingStandardsIgnoreLine.
return ! ( $count > 0 );
}
public function get_last_offsets() {
return get_option( '_bwf_last_offsets', array() );
}
/**
* Kill process.
*
* Stop processing queue items, clear cronjob and delete all batches.
*/
public function kill_process() {
$this->kill_process_safe();
WooFunnels_Dashboard::$classes['WooFunnels_DB_Updater']->set_upgrade_state( '1' );
}
public function kill_process_safe() {
if ( ! $this->is_queue_empty() ) {
$this->delete_all_batches();
wp_clear_scheduled_hook( $this->cron_hook_identifier );
}
}
/**
* Delete all batches.
*
* @return WooFunnels_Background_Updater
*/
public function delete_all_batches() {
global $wpdb;
$table = $wpdb->options;
$column = 'option_name';
if ( is_multisite() ) {
$table = $wpdb->sitemeta;
$column = 'meta_key';
}
$key = $wpdb->esc_like( $this->identifier . '_batch_' ) . '%';
$wpdb->query( $wpdb->prepare( "DELETE FROM {$table} WHERE {$column} LIKE %s", $key ) ); // @codingStandardsIgnoreLine.
return $this;
}
/**
* Manage last 5 offsets
*/
public function manage_last_offsets() {
$offsets = $this->get_last_offsets();
$current_offset = get_option( '_bwf_offset', 0 );
if ( self::MAX_SAME_OFFSET_THRESHOLD === count( $offsets ) ) {
$offsets = array_map( function ( $key ) use ( $offsets ) {
return isset( $offsets[ $key + 1 ] ) ? $offsets[ $key + 1 ] : 0;
}, array_keys( $offsets ) );
$offsets[ self::MAX_SAME_OFFSET_THRESHOLD - 1 ] = $current_offset;
} else {
$offsets[ count( $offsets ) ] = $current_offset;
}
$this->update_last_offsets( $offsets );
}
public function update_last_offsets( $offsets ) {
update_option( '_bwf_last_offsets', $offsets );
}
/**
* Handle.
*
* Pass each queue item to the task handler, while remaining
* within server memory and time limit constraints.
*/
protected function handle() {
$this->lock_process();
do {
$batch = $this->get_batch();
foreach ( $batch->data as $key => $value ) {
$task = $this->task( $value );
if ( false !== $task ) {
$batch->data[ $key ] = $task;
} else {
unset( $batch->data[ $key ] );
}
if ( $this->batch_limit_exceeded() ) {
// Batch limits reached.
break;
}
}
// Update or delete current batch.
if ( ! empty( $batch->data ) ) {
$this->update( $batch->key, $batch->data );
} else {
$this->delete( $batch->key );
}
} while ( ! $this->batch_limit_exceeded() && ! $this->is_queue_empty() );
$this->unlock_process();
// Start next batch or complete process.
if ( ! $this->is_queue_empty() ) {
$this->dispatch();
} else {
$this->complete();
}
}
/**
* Get batch.
*
* @return stdClass Return the first batch from the queue.
*/
protected function get_batch() {
global $wpdb;
$table = $wpdb->options;
$column = 'option_name';
$key_column = 'option_id';
$value_column = 'option_value';
if ( is_multisite() ) {
$table = $wpdb->sitemeta;
$column = 'meta_key';
$key_column = 'meta_id';
$value_column = 'meta_value';
}
$key = $wpdb->esc_like( $this->identifier . '_batch_' ) . '%';
$query = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$table} WHERE {$column} LIKE %s ORDER BY {$key_column} ASC LIMIT 1", $key ) ); // @codingStandardsIgnoreLine.
$batch = new stdClass();
$batch->key = $query->$column;
$batch->data = array_filter( (array) maybe_unserialize( $query->$value_column ) );
return $batch;
}
/**
* Task
*
* Override this method to perform any actions required on each
* queue item. Return the modified item for further processing
* in the next pass through. Or, return false to remove the
* item from the queue.
*
* @param string $callback Update callback function.
*
* @return string|bool
* @SuppressWarnings(PHPMD.DevelopmentCodeFragment)
* @SuppressWarnings(PHPMD.ElseExpression)
*/
protected function task( $callback ) {
$result = false;
if ( is_callable( $callback ) ) {
BWF_Logger::get_instance()->log( 'Running the callback: ' . print_r( $callback, true ), 'woofunnels_indexing' ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r
$result = (bool) call_user_func( $callback );
if ( $result ) {
/**sleep( 5 );*/
BWF_Logger::get_instance()->log( "Result: $result Need to run again the callback: " . print_r( $callback, true ), 'woofunnels_indexing' ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r
} else {
BWF_Logger::get_instance()->log( "Result: $result Finished running the callback: " . print_r( $callback, true ), 'woofunnels_indexing' ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r
}
} else {
BWF_Logger::get_instance()->log( "Result: $result Could not find the callback: " . print_r( $callback, true ), 'woofunnels_indexing' ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r
}
return $result ? $callback : false;
}
/**
* See if the batch limit has been exceeded.
*
* @return bool
*/
protected function batch_limit_exceeded() {
return $this->time_exceeded() || $this->memory_exceeded();
}
/**
* Memory exceeded
*
* Ensures the batch process never exceeds 90%
* of the maximum WordPress memory.
*
* @return bool
*/
protected function memory_exceeded() {
$memory_limit = $this->get_memory_limit() * 0.9; // 90% of max memory
$current_memory = memory_get_usage( true );
$return = false;
if ( $current_memory >= $memory_limit ) {
$return = true;
}
return apply_filters( $this->identifier . '_memory_exceeded', $return );
}
/**
* Get memory limit.
*
* @return int
*/
protected function get_memory_limit() {
if ( function_exists( 'ini_get' ) ) {
$memory_limit = ini_get( 'memory_limit' );
} else {
// Sensible default.
$memory_limit = '128M';
}
if ( ! $memory_limit || - 1 === intval( $memory_limit ) ) {
// Unlimited, set to 32GB.
$memory_limit = '32G';
}
return wp_convert_hr_to_bytes( $memory_limit );
}
/**
* Complete
*
* Override if applicable, but ensure that the below actions are
* performed, or, call parent::complete().
*/
protected function complete() {
update_option( '_bwf_offset', 0 );
BWF_Logger::get_instance()->log( 'Background scanning completed for indexing order and creating updating contacts and customers.', 'woofunnels_indexing' );
do_action( 'bwf_order_index_completed' );
parent::complete();
}
/**
* Is the updater running?
*
* @return boolean
*/
public function is_updating() {
return false === $this->is_queue_empty();
}
public function maybe_re_dispatch_background_process() {
if ( 3 !== absint( WooFunnels_Dashboard::$classes['WooFunnels_DB_Updater']->get_upgrade_state() ) ) {
return;
}
if ( $this->is_queue_empty() ) {
return;
}
if ( $this->is_process_running() ) {
return;
}
/**
* We are saving the last 5 offset value, due to any specific reason if last 5 offsets are same then it might be the time to kill the process.
*/
$offsets = $this->get_last_offsets();
if ( self::MAX_SAME_OFFSET_THRESHOLD === count( $offsets ) ) {
$unique = array_unique( $offsets );
if ( 1 === count( $unique ) ) {
$this->kill_process();
BWF_Logger::get_instance()->log( sprintf( 'Offset is stuck from last %d attempts, terminating the process.', self::MAX_SAME_OFFSET_THRESHOLD ), 'woofunnels_indexing' );
return;
}
}
$this->manage_last_offsets();
$this->dispatch();
}
/**
* Schedule fallback event.
*/
protected function schedule_event() {
if ( ! wp_next_scheduled( $this->cron_hook_identifier ) ) {
wp_schedule_event( time() + 10, $this->cron_interval_identifier, $this->cron_hook_identifier );
}
}
}
}

View File

@@ -0,0 +1,971 @@
<?php
/**
* Contact Class
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'WooFunnels_Contact' ) ) {
/**
* Class WooFunnels_Contact
*
*
*/
#[AllowDynamicProperties]
class WooFunnels_Contact {
/**
* @var WooFunnels_DB_Operations
*/
public $db_operations;
/**
* public id $id
*/
public $id;
/**
* public ud $uid
*/
public $uid;
/**
* public email $email
*/
public $email;
/**
* public wp_id $wp_id
*/
public $wp_id;
/**
* public meta $meta
*/
public $meta;
/**
* public customer $customer
*/
public $children;
/**
* @var mixed $db_contact
*/
public $db_contact;
/**
* @var bool $blank_values_update
*/
public $blank_values_update = false;
public $is_subscribed = false;
/**
* Get the contact details for the email passed if this email exits other create a new contact with this email
*
* @param string|int $wp_id WordPress User ID
* @param string $email email
* @param string $phone contact number
* @param string|int $cid contact id,
* @param string $uid Unique ID
*/
public function __construct( $wp_id = '', $email = '', $phone = '', $cid = '', $uid = '' ) {
/** Set blank properties */
$this->set_blank_props();
$this->email = $email;
$this->wp_id = $wp_id;
/** If CID given */
if ( ! empty( $cid ) && absint( $cid ) > 0 ) {
$this->db_contact = $this->get_contact_by_id( absint( $cid ) );
$db_obj = $this->validate_and_set_obj( $this->db_contact );
if ( false !== $db_obj ) {
return;
}
}
/** If WP ID given */
if ( ! empty( $wp_id ) && absint( $wp_id ) > 0 ) {
$this->db_contact = $this->get_contact_by_wpid( absint( $wp_id ) );
$db_obj = $this->validate_and_set_obj( $this->db_contact );
if ( false !== $db_obj ) {
return;
}
}
/** If EMAIL given */
if ( ! empty( $email ) && is_email( $email ) ) {
$this->db_contact = $this->get_contact_by_email( trim( $email ) );
$db_obj = $this->validate_and_set_obj( $this->db_contact );
if ( false !== $db_obj ) {
return;
}
}
/** If PHONE given */
if ( ! empty( $phone ) ) {
$this->db_contact = $this->get_contact_by_phone( trim( $phone ) );
$db_obj = $this->validate_and_set_obj( $this->db_contact );
if ( false !== $db_obj ) {
return;
}
}
/** If UID given */
if ( ! empty( $uid ) ) {
$this->db_contact = $this->get_contact_by_uid( trim( $uid ) );
$this->validate_and_set_obj( $this->db_contact );
}
}
public function set_blank_props() {
$this->db_operations = WooFunnels_DB_Operations::get_instance();
if ( ! isset( $this->children ) ) {
$this->children = new stdClass();
}
if ( ! isset( $this->meta ) ) {
$this->meta = new stdClass();
}
$this->db_contact = new stdClass();
}
/**
* Get contact by id i.e. cid
*
* @param $cid
*
* @return mixed
*/
public function get_contact_by_id( $cid ) {
$cached_obj = $this->get_cache_obj( 'cid', $cid );
if ( false !== $cached_obj ) {
return $cached_obj;
}
$output = $this->db_operations->get_contact_by_contact_id( $cid );
$this->set_cache_object( 'cid', $cid, $output );
return $output;
}
/**
* Get contact cache object
*
* @param $type
* @param $value
*
* @return false|mixed
*/
public function get_cache_obj( $type, $value ) {
$obj = BWF_Contacts::get_instance();
$value = sanitize_key( $value );
if ( isset( $obj->cached_contact_obj[ $type ] ) && isset( $obj->cached_contact_obj[ $type ][ $value ] ) ) {
return $obj->cached_contact_obj[ $type ][ $value ];
}
return false;
}
/**
* Set contact cache object
*
* @param $type
* @param $value
* @param $output
*/
public function set_cache_object( $type, $value, $output ) {
$obj = BWF_Contacts::get_instance();
$value = sanitize_key( $value );
if ( ! isset( $obj->cached_contact_obj[ $type ] ) ) {
$obj->cached_contact_obj[ $type ] = [];
}
$obj->cached_contact_obj[ $type ][ $value ] = $output;
}
public function validate_and_set_obj( $obj ) {
if ( ! is_object( $obj ) || ! isset( $obj->id ) ) {
return false;
}
$this->id = $obj->id;
$this->email = $this->db_contact->email;
$this->wp_id = $this->db_contact->wpid;
$this->set_obj_meta();
return true;
}
public function set_obj_meta() {
if ( ! isset( $this->id ) || empty( $this->id ) ) {
return;
}
$contact_meta = $this->db_operations->get_contact_metadata( $this->id );
foreach ( is_array( $contact_meta ) ? $contact_meta : array() as $meta ) {
$this->meta->{$meta->meta_key} = maybe_unserialize( $meta->meta_value );
}
}
/**
* Get contact by wp_id
*
* @param $wp_id
*
* @return mixed
*/
public function get_contact_by_wpid( $wp_id ) {
$cached_obj = $this->get_cache_obj( 'wp_id', $wp_id );
if ( false !== $cached_obj ) {
return $cached_obj;
}
$output = $this->db_operations->get_contact_by_wpid( $wp_id );
$this->set_cache_object( 'wp_id', $wp_id, $output );
return $output;
}
/**
* Get contact by email
*
* @param $email
*
* @return mixed
*/
public function get_contact_by_email( $email ) {
$cached_obj = $this->get_cache_obj( 'email', $email );
if ( false !== $cached_obj ) {
return $cached_obj;
}
$output = $this->db_operations->get_contact_by_email( $email );
$this->set_cache_object( 'email', $email, $output );
return $output;
}
/**
* Get contact by phone
*
* @param $phone
*
* @return mixed
*/
public function get_contact_by_phone( $phone ) {
$cached_obj = $this->get_cache_obj( 'phone', $phone );
if ( false !== $cached_obj ) {
return $cached_obj;
}
$output = $this->db_operations->get_contact_by_phone( $phone );
$this->set_cache_object( 'phone', $phone, $output );
return $output;
}
public function get_contact_by_uid( $uid ) {
$cached_obj = $this->get_cache_obj( 'uid', $uid );
if ( false !== $cached_obj ) {
return $cached_obj;
}
$output = $this->db_operations->get_contact( $uid );
$this->set_cache_object( 'uid', $uid, $output );
return $output;
}
/**
* Implementing magic function for calling other contact's actor(like customer) functions
*
* @param $name
* @param $args
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*
* @return mixed
*/
public function __call( $name, $args ) {
$keys_arr = explode( '_', $name );
$action = ( is_array( $keys_arr ) && count( $keys_arr ) > 0 ) ? $keys_arr[0] : '';
$child = ( is_array( $keys_arr ) && count( $keys_arr ) > 1 ) ? $keys_arr[1] : '';
$function = str_replace( $child . '_', '', $name );
$child_entities = BWF_Contacts::get_registerd_child_entities();
if ( 'set_child' === $function && ! isset( $this->children->{$child} ) ) {
if ( isset( $child_entities[ $child ] ) ) {
$object_child = $child_entities[ $child ];
$this->children->{$child} = new $object_child( $this );
}
} elseif ( isset( $this->children ) && ! empty( $this->children ) && ! empty( $child ) && isset( $this->children->{$child} ) && 'set_child' !== $function ) {
$result = '';
if ( is_array( $args ) && count( $args ) > 0 ) {
$result = $this->children->{$child}->{$function}( $args[0] );
}
if ( ! is_array( $args ) || ( is_array( $args ) && 0 === count( $args ) ) ) {
$result = $this->children->{$child}->{$function}();
}
if ( 'get' === $action ) {
return $result;
}
} elseif ( ! isset( $this->children->{$child} ) ) {
BWF_Logger::get_instance()->log( "Magic Function $name is not defined for child function: $function", 'woofunnels_indexing' );
}
}
/**
* Get marketing status
*/
public function get_marketing_status() {
return $this->get_status();
}
/**
* Get marketing status
*/
public function get_status() {
$status = ( isset( $this->status ) && '' !== $this->status ) ? $this->status : '';
$db_status = ( isset( $this->db_contact->status ) && '' !== $this->db_contact->status ) ? $this->db_contact->status : '';
return '' !== $status ? $status : $db_status;
}
/**
* Get meta value for a given meta key from current contact object
*
* @param string $meta_key meta key to get value against
* @param bool $is_primary_column_check whether to check primary properties or not
*
* @return mixed|string
*/
public function get_meta( $meta_key, $is_primary_column_check = true ) {
if ( $is_primary_column_check ) {
$primary_columns = $this->get_primary_properties();
if ( in_array( $meta_key, $primary_columns, true ) ) {
return call_user_func( array( $this, 'get_' . $meta_key ) );
}
}
if ( isset( $this->meta->{$meta_key} ) ) {
return maybe_unserialize( $this->meta->{$meta_key} );
}
return '';
}
/**
* @param $meta_key
* @param $meta_value
*/
public function set_meta( $meta_key, $meta_value ) {
$this->meta->{$meta_key} = $meta_value;
}
/**
* @param $meta_key
*/
public function unset_meta( $meta_key ) {
if ( isset( $this->meta ) && isset( $this->meta->{$meta_key} ) ) {
unset( $this->meta->{$meta_key} );
}
}
public function get_primary_properties() {
return array(
'id',
'email',
'wpid',
'uid',
'email',
'f_name',
'l_name',
'creation_date',
'contact_no',
'country',
'state',
'timezone',
'type',
'source',
'points',
'last_modified',
'status',
'tags',
'lists'
);
}
/**
* Set contact first name
*
* @param $f_name
*/
public function set_f_name( $f_name ) {
if ( true === $this->blank_values_update ) {
$this->f_name = $f_name;
if ( ! empty( $this->f_name ) ) {
$this->f_name = trim( $this->f_name );
}
return;
}
$this->f_name = empty( $f_name ) ? $this->get_f_name() : $f_name;
if ( ! empty( $this->f_name ) ) {
$this->f_name = trim( $this->f_name );
}
}
/**
* Get contact first name
*/
public function get_f_name() {
$f_name = ( isset( $this->f_name ) ) ? $this->f_name : null;
if ( ! empty( $f_name ) ) {
$f_name = trim( $f_name );
}
$db_f_name = ( isset( $this->db_contact->f_name ) ) ? $this->db_contact->f_name : '';
if ( ! empty( $db_f_name ) ) {
$db_f_name = trim( $db_f_name );
}
return is_null( $f_name ) ? $db_f_name : $f_name;
}
/**
* Set contact last name
*
* @param $l_name
*/
public function set_l_name( $l_name ) {
if ( true === $this->blank_values_update ) {
$this->l_name = $l_name;
if ( ! empty( $this->l_name ) ) {
$this->l_name = trim( $this->l_name );
}
return;
}
$this->l_name = empty( $l_name ) ? $this->get_l_name() : $l_name;
if ( ! empty( $this->l_name ) ) {
$this->l_name = trim( $this->l_name );
}
}
/**
* Get contact last name
*/
public function get_l_name() {
$l_name = ( isset( $this->l_name ) ) ? $this->l_name : null;
if ( ! empty( $l_name ) ) {
$l_name = trim( $l_name );
}
$db_l_name = ( isset( $this->db_contact->l_name ) ) ? $this->db_contact->l_name : '';
if ( ! empty( $db_l_name ) ) {
$db_l_name = trim( $db_l_name );
}
return is_null( $l_name ) ? $db_l_name : $l_name;
}
/**
* Set contact tags
*
* @param string[] $tags
*/
public function set_tags( $tags ) {
if ( ! is_array( $tags ) ) {
return;
}
$this->tags = wp_json_encode( array_map( 'strval', $tags ) );
}
/**
* Get contact tags
*/
public function get_tags() {
$tags = ( isset( $this->tags ) && ! empty( $this->tags ) ) ? json_decode( $this->tags, true ) : null;
$db_tags = ( isset( $this->db_contact->tags ) && ! empty( $this->db_contact->tags ) ) ? json_decode( $this->db_contact->tags, true ) : null;
$db_tags = ! is_array( $db_tags ) ? [] : $db_tags;
return ! is_array( $tags ) ? $db_tags : $tags;
}
/**
* Set contact lists
*
* @param string[] $lists
*/
public function set_lists( $lists ) {
if ( ! is_array( $lists ) ) {
return;
}
$this->lists = wp_json_encode( array_map( 'strval', $lists ) );
}
/**
* Get contact lists
*/
public function get_lists() {
$lists = ( isset( $this->lists ) && ! empty( $this->lists ) ) ? json_decode( $this->lists, true ) : null;
$db_lists = ( isset( $this->db_contact->lists ) && ! empty( $this->db_contact->lists ) ) ? json_decode( $this->db_contact->lists, true ) : null;
$db_lists = ! is_array( $db_lists ) ? [] : $db_lists;
return ! is_array( $lists ) ? $db_lists : $lists;
}
/**
* Set contact created date
*
* @param $date
*/
public function set_last_modified( $date ) {
$this->last_modified = empty( $date ) ? $this->get_last_modified() : $date;
}
/**
* Get contact fname
*/
public function get_last_modified() {
$last_mod = ( isset( $this->last_modified ) && ! empty( $this->last_modified ) ) ? $this->last_modified : '';
$db_last_modified = ( isset( $this->db_contact->last_modified ) && ! empty( $this->db_contact->last_modified ) ) ? $this->db_contact->last_modified : '';
return empty( $last_mod ) ? $db_last_modified : $last_mod;
}
/**
* Set contact created date
*
* @param $date
*/
public function set_creation_date( $date ) {
$this->creation_date = empty( $date ) ? $this->get_creation_date() : $date;
}
/**
* Get contact created date
*/
public function get_creation_date() {
$creation_date = ( isset( $this->creation_date ) && ! empty( $this->creation_date ) ) ? $this->creation_date : '';
$db_creation_date = ( isset( $this->db_contact->creation_date ) && ! empty( $this->db_contact->creation_date ) ) ? $this->db_contact->creation_date : current_time( 'mysql' );
return empty( $creation_date ) ? $db_creation_date : $creation_date;
}
public function set_type( $type ) {
$this->type = empty( $type ) ? $this->get_type() : $type;
}
/**
* Get type the contact belongs to
* @return string
*/
public function get_type() {
$type = ( isset( $this->type ) && ! empty( $this->type ) ) ? $this->type : '';
$db_type = ( isset( $this->db_contact->type ) && ! empty( $this->db_contact->type ) ) ? $this->db_contact->type : '';
return empty( $type ) ? $db_type : $type;
}
public function set_source( $source ) {
$this->source = empty( $source ) ? $this->get_source() : $source;
}
/**
* Get source the contact generated from
* @return string
*/
public function get_source() {
$source = ( isset( $this->source ) && ! empty( $this->source ) ) ? $this->source : '';
$db_source = ( isset( $this->db_contact->source ) && ! empty( $this->db_contact->source ) ) ? $this->db_contact->source : '';
return empty( $source ) ? $db_source : $source;
}
public function set_points( $points ) {
$this->points = empty( $points ) ? 0 : $points;
}
/**
* Get points the contact have
* @return integer
*/
public function get_points() {
return ( isset( $this->points ) && intval( $this->points ) > 0 ) ? intval( $this->points ) : 0;
}
/**
* Saves the data in the properties.
* This method is responsible for any db operation inside the contact table and sibling tables
* Updating contact table with set data
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.DevelopmentCodeFragment)
*
*/
public function save() {
$contact = array();
$get_primary_properties = $this->get_primary_properties();
foreach ( $get_primary_properties as $property ) {
$contact[ $property ] = call_user_func( array( $this, 'get_' . $property ) );
if ( 'tags' === $property || 'lists' === $property ) {
$contact[ $property ] = wp_json_encode( $contact[ $property ] );
}
}
$contact['last_modified'] = current_time( 'mysql' );
if ( $this->get_id() > 0 ) {
/** Existing contact */
$contact['id'] = $this->get_id();
/** Check if UID empty */
if ( empty( $this->get_uid() ) ) {
$contact['uid'] = md5( $this->email . $this->wp_id . time() );
$this->set_uid( $contact['uid'] );
}
$this->db_operations->update_contact( $contact );
} elseif ( empty( $this->get_id() ) ) {
$contact['uid'] = md5( $this->email . $this->wp_id . time() );
$contact['wpid'] = $this->get_wpid() > 0 ? $this->get_wpid() : 0;
$this->set_uid( $contact['uid'] );
$contact_id = $this->db_operations->insert_contact( $contact );
$this->id = $contact_id;
}
/** Run subscribe action */
if ( true === $this->is_subscribed ) {
do_action( 'bwfcrm_after_contact_subscribed', $this );
$this->is_subscribed = false;
}
/** Purge Cache */
$this->purge_contact_from_cache();
if ( isset( $this->children ) && ! empty( $this->children ) ) {
foreach ( $this->children as $child_actor ) {
$child_actor->set_cid( $this->get_id() );
$child_actor->save();
}
}
}
/**
* Get contact id
* @SuppressWarnings(PHPMD.ShortVariable)
*/
public function get_id() {
$id = ( isset( $this->id ) && $this->id > 0 ) ? $this->id : 0;
$db_id = ( isset( $this->db_contact->id ) && ( $this->db_contact->id > 0 ) ) ? $this->db_contact->id : 0;
return ( $id > 0 ) ? $id : $db_id;
}
/**
* Set contact id
*
* @param $id
*/
public function set_id( $id ) {
$this->id = empty( $id ) ? $this->get_id() : $id;
}
/**
* Get contact wp_id
*/
public function get_wpid() {
return ( isset( $this->wp_id ) && intval( $this->wp_id ) > 0 ) ? intval( $this->wp_id ) : 0;
}
/**
* Set contact wp id
*
* @param $wp_id
*/
public function set_wpid( $wp_id ) {
$this->wp_id = intval( $wp_id );
}
/**
* Purge contact sql object from cache
*/
public function purge_contact_from_cache() {
$obj = BWF_Contacts::get_instance();
$cid = sanitize_key( $this->get_id() );
$email = sanitize_key( $this->get_email() );
$phone = sanitize_key( $this->get_contact_no() );
$wp_id = sanitize_key( $this->get_wpid() );
$uid = sanitize_key( $this->get_uid() );
/** cid */
if ( isset( $obj->cached_contact_obj['cid'] ) && isset( $obj->cached_contact_obj['cid'][ $cid ] ) ) {
unset( $obj->cached_contact_obj['cid'][ $cid ] );
}
/** email */
if ( isset( $obj->cached_contact_obj['email'] ) && isset( $obj->cached_contact_obj['email'][ $email ] ) ) {
unset( $obj->cached_contact_obj['email'][ $email ] );
}
/** phone */
if ( isset( $obj->cached_contact_obj['phone'] ) && isset( $obj->cached_contact_obj['phone'][ $phone ] ) ) {
unset( $obj->cached_contact_obj['phone'][ $phone ] );
}
/** wp id */
if ( isset( $obj->cached_contact_obj['wp_id'] ) && isset( $obj->cached_contact_obj['wp_id'][ $wp_id ] ) ) {
unset( $obj->cached_contact_obj['wp_id'][ $wp_id ] );
}
/** uid */
if ( isset( $obj->cached_contact_obj['uid'] ) && isset( $obj->cached_contact_obj['uid'][ $uid ] ) ) {
unset( $obj->cached_contact_obj['uid'][ $uid ] );
}
}
/**
* Get contact email
*/
public function get_email() {
$email = ( isset( $this->email ) && ! empty( $this->email ) ) ? $this->email : '';
if ( ! empty( $email ) ) {
$email = trim( $email );
}
$db_email = ( isset( $this->db_contact->email ) && ! empty( $this->db_contact->email ) ) ? $this->db_contact->email : '';
if ( ! empty( $db_email ) ) {
$db_email = trim( $db_email );
}
return empty( $email ) ? $db_email : $email;
}
/**
* Set contact email
*
* @param $email
*/
public function set_email( $email ) {
$this->email = empty( $email ) ? $this->get_email() : $email;
if ( ! empty( $this->email ) ) {
$this->email = trim( $this->email );
}
}
public function get_contact_no() {
$contact_no = ( isset( $this->contact_no ) ) ? $this->contact_no : null;
$db_contact_no = ( isset( $this->db_contact->contact_no ) ) ? $this->db_contact->contact_no : '';
return is_null( $contact_no ) ? $db_contact_no : $contact_no;
}
/**
* Get contact uid
*/
public function get_uid() {
$uid = ( isset( $this->uid ) && ! empty( $this->uid ) ) ? $this->uid : '';
$db_uid = ( isset( $this->db_contact->uid ) && ! empty( $this->db_contact->uid ) ) ? $this->db_contact->uid : '';
return empty( $uid ) ? $db_uid : $uid;
}
/**
* Set contact uid
*
* @param $uid
*/
public function set_uid( $uid ) {
$this->uid = empty( $uid ) ? $this->get_uid() : $uid;
}
/**
* Get meta value for a given meta key from DB
*/
public function get_contact_meta( $meta_key ) {
return $this->db_operations->get_contact_meta_value( $this->get_id(), $meta_key );
}
/**
* Set meta value for a given meta key
*
* @param $meta_key
* @param $meta_value
*
* @return mixed
*/
public function update_meta( $meta_key, $meta_value ) {
return $this->db_operations->update_contact_meta( $this->get_id(), $meta_key, $meta_value );
}
/**
* Updating contact meta table with set data
*/
public function save_meta() {
$this->db_operations->save_contact_meta( $this->id, $this->meta );
$contact = [];
$contact['id'] = $this->get_id();
$contact['last_modified'] = current_time( 'mysql' );
$this->db_operations->update_contact( $contact );
}
/**
* Set marketing status
*
* @param $status
*/
public function set_marketing_status( $status ) {
$this->set_status( $status );
}
/**
* Set marketing status
*
* @param $status
*/
public function set_status( $status ) {
/** If cid 0 */
if ( 0 === absint( $this->get_id() ) ) {
/** New contact */
/** Check if status is subscribed */
if ( 1 === absint( $status ) ) {
/** run do action contact subscribed */
$this->is_subscribed = true;
}
} else {
$old_status = $this->get_status();
if ( 1 !== absint( $old_status ) && 1 === absint( $status ) ) {
/** run do action contact subscribed */
$this->is_subscribed = true;
}
}
$this->status = ( '' === $status ) ? $this->get_status() : $status;
}
/**
* Set contact country
*
* @param $country
*/
public function set_country( $country ) {
if ( true === $this->blank_values_update ) {
$this->country = $country;
return;
}
$this->country = empty( $country ) ? $this->get_country() : $country;
}
/**
* Get contact country
*/
public function get_country() {
$country = ( isset( $this->country ) ) ? $this->country : null;
$db_country = ( isset( $this->db_contact->country ) ) ? $this->db_contact->country : '';
return is_null( $country ) ? $db_country : $country;
}
/**
* Set contact timezone
*
* @param $timezone
*/
public function set_timezone( $timezone ) {
if ( true === $this->blank_values_update ) {
$this->timezone = $timezone;
return;
}
$this->timezone = empty( $timezone ) ? $this->get_timezone() : $timezone;
}
/**
* Get contact timezone
*
* @return string
*/
public function get_timezone() {
$timezone = ( isset( $this->timezone ) ) ? $this->timezone : null;
$db_timezone = ( isset( $this->db_contact->timezone ) ) ? $this->db_contact->timezone : '';
return is_null( $timezone ) ? $db_timezone : $timezone;
}
/**
* Set contact number
*
* @param $contact_no
*/
public function set_contact_no( $contact_no ) {
if ( true === $this->blank_values_update ) {
$this->contact_no = $contact_no;
return;
}
$this->contact_no = empty( $contact_no ) ? $this->get_contact_no() : $contact_no;
}
/**
* Set contact state
*
* @param $state
*/
public function set_state( $state ) {
if ( true === $this->blank_values_update ) {
$this->state = $state;
return;
}
$this->state = empty( $state ) ? $this->get_state() : $state;
}
/**
* Get contact state
*/
public function get_state() {
$state = ( isset( $this->state ) ) ? $this->state : null;
$db_state = ( isset( $this->db_contact->state ) ) ? $this->db_contact->state : '';
return is_null( $state ) ? $db_state : $state;
}
/**
* Deleting a meta key from contact meta table
*
* @param $meta_key
*/
public function delete_meta( $meta_key ) {
$this->db_operations->delete_contact_meta( $this->id, $meta_key );
}
}
}

View File

@@ -0,0 +1,428 @@
<?php
/**
* WooFunnels Contacts Background Updater
*
* @version 1.7.4
*/
defined( 'ABSPATH' ) || exit;
if ( ! class_exists( 'WP_Async_Request', false ) ) {
include_once dirname( dirname( __FILE__ ) ) . '/libraries/wp-async-request.php';
}
if ( ! class_exists( 'WP_Background_Process', false ) ) {
include_once dirname( dirname( __FILE__ ) ) . '/libraries/wp-background-process.php';
}
if ( ! class_exists( 'WooFunnels_Contacts_Background_Updater' ) ) {
/**
* WooFunnels_Background_Updater Class.
* Based on WC_Background_Updater concept
*/
#[AllowDynamicProperties]
class WooFunnels_Contacts_Background_Updater extends WP_Background_Process {
const MAX_SAME_OFFSET_THRESHOLD = 5;
/**
* Initiate new background process.
*
* WooFunnels_Background_Updater constructor.
*/
public function __construct() {
// Uses unique prefix per blog so each blog has separate queue.
$this->prefix = 'bwf_' . get_current_blog_id();
$this->action = 'contact_updater';
parent::__construct();
}
/**
* Schedule cron healthcheck.
*
* @param array $schedules Schedules.
*
* @return array
*/
public function schedule_cron_healthcheck( $schedules ) {
$interval = apply_filters( $this->identifier . '_cron_interval', 5 );
if ( property_exists( $this, 'cron_interval' ) ) {
$interval = apply_filters( $this->identifier . '_cron_interval', $this->cron_interval );
}
// Adds every 5 minutes to the existing schedules.
$schedules[ $this->identifier . '_cron_interval' ] = array(
'interval' => MINUTE_IN_SECONDS * $interval,
/* translators: %d: interval */
'display' => sprintf( __( 'Every %d minutes', 'woocommerce' ), $interval ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
);
return $schedules;
}
/**
* Handle cron healthcheck
*
* Restart the background process if not already running
* and data exists in the queue.
*/
public function handle_cron_healthcheck() {
if ( $this->is_process_running() ) {
// Background process already running.
return;
}
if ( $this->is_queue_empty() ) {
// No data to process.
$this->clear_scheduled_event();
BWF_Logger::get_instance()->log( 'Scheduled event cleared as queue is empty.', 'woofunnels_contacts_indexing' );
return;
}
/**
* We are saving the last 5 offset value, due to any specific reason if last 5 offsets are same then it might be the time to kill the process.
*/
$offsets = $this->get_last_offsets();
if ( self::MAX_SAME_OFFSET_THRESHOLD === count( $offsets ) ) {
$unique = array_unique( $offsets );
if ( 1 === count( $unique ) ) {
$this->kill_process();
BWF_Logger::get_instance()->log( sprintf( 'Offset is stuck from last %d cron jobs, terminating the process.', self::MAX_SAME_OFFSET_THRESHOLD ), 'woofunnels_contacts_indexing' );
return;
}
}
$this->manage_last_offsets();
BWF_Logger::get_instance()->log( 'Cron started again!!', 'woofunnels_contacts_indexing' );
/**
* Everything looks good, lets roll the indexing
*/
$this->handle();
}
/**
* Overriding parent protected function publically to use outside this class
* @return bool
*/
public function is_process_running() {
return parent::is_process_running();
}
/**
* Is queue empty.
*
* @return bool
*/
protected function is_queue_empty() {
global $wpdb;
$table = $wpdb->options;
$column = 'option_name';
if ( is_multisite() ) {
$table = $wpdb->sitemeta;
$column = 'meta_key';
}
$key = $wpdb->esc_like( $this->identifier . '_batch_' ) . '%';
$count = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM {$table} WHERE {$column} LIKE %s", $key ) ); // @codingStandardsIgnoreLine.
return ! ( $count > 0 );
}
public function get_last_offsets() {
return get_option( '_bwf_contacts_last_offsets', array() );
}
/**
* Kill process.
*
* Stop processing queue items, clear cronjob and delete all batches.
*/
public function kill_process() {
$this->kill_process_safe();
WooFunnels_Dashboard::$classes['WooFunnels_DB_Updater']->set_upgrade_state( '1' );
}
public function kill_process_safe() {
if ( ! $this->is_queue_empty() ) {
$this->delete_all_batches();
wp_clear_scheduled_hook( $this->cron_hook_identifier );
}
}
/**
* Delete all batches.
*
* @return WooFunnels_Contacts_Background_Updater
*/
public function delete_all_batches() {
global $wpdb;
$table = $wpdb->options;
$column = 'option_name';
if ( is_multisite() ) {
$table = $wpdb->sitemeta;
$column = 'meta_key';
}
$key = $wpdb->esc_like( $this->identifier . '_batch_' ) . '%';
$wpdb->query( $wpdb->prepare( "DELETE FROM {$table} WHERE {$column} LIKE %s", $key ) ); // @codingStandardsIgnoreLine.
return $this;
}
/**
* Manage last 5 offsets
*/
public function manage_last_offsets() {
$offsets = $this->get_last_offsets();
$current_offset = get_option( '_bwf_contacts_offset', 0 );
if ( self::MAX_SAME_OFFSET_THRESHOLD === count( $offsets ) ) {
$offsets = array_map( function ( $key ) use ( $offsets ) {
return isset( $offsets[ $key + 1 ] ) ? $offsets[ $key + 1 ] : 0;
}, array_keys( $offsets ) );
$offsets[ self::MAX_SAME_OFFSET_THRESHOLD - 1 ] = $current_offset;
} else {
$offsets[ count( $offsets ) ] = $current_offset;
}
$this->update_last_offsets( $offsets );
}
public function update_last_offsets( $offsets ) {
update_option( '_bwf_contacts_last_offsets', $offsets );
}
/**
* Handle.
*
* Pass each queue item to the task handler, while remaining
* within server memory and time limit constraints.
*/
protected function handle() {
$this->lock_process();
do {
$batch = $this->get_batch();
foreach ( $batch->data as $key => $value ) {
$task = $this->task( $value );
if ( false !== $task ) {
$batch->data[ $key ] = $task;
} else {
unset( $batch->data[ $key ] );
}
if ( $this->batch_limit_exceeded() ) {
// Batch limits reached.
break;
}
}
// Update or delete current batch.
if ( ! empty( $batch->data ) ) {
$this->update( $batch->key, $batch->data );
} else {
$this->delete( $batch->key );
}
} while ( ! $this->batch_limit_exceeded() && ! $this->is_queue_empty() );
$this->unlock_process();
// Start next batch or complete process.
if ( ! $this->is_queue_empty() ) {
$this->dispatch();
} else {
$this->complete();
}
}
/**
* Get batch.
*
* @return stdClass Return the first batch from the queue.
*/
protected function get_batch() {
global $wpdb;
$table = $wpdb->options;
$column = 'option_name';
$key_column = 'option_id';
$value_column = 'option_value';
if ( is_multisite() ) {
$table = $wpdb->sitemeta;
$column = 'meta_key';
$key_column = 'meta_id';
$value_column = 'meta_value';
}
$key = $wpdb->esc_like( $this->identifier . '_batch_' ) . '%';
$query = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$table} WHERE {$column} LIKE %s ORDER BY {$key_column} ASC LIMIT 1", $key ) ); // @codingStandardsIgnoreLine.
$batch = new stdClass();
$batch->key = $query->$column;
$batch->data = array_filter( (array) maybe_unserialize( $query->$value_column ) );
return $batch;
}
/**
* Task
*
* Override this method to perform any actions required on each
* queue item. Return the modified item for further processing
* in the next pass through. Or, return false to remove the
* item from the queue.
*
* @param string $callback Update callback function.
*
* @return string|bool
* @SuppressWarnings(PHPMD.DevelopmentCodeFragment)
* @SuppressWarnings(PHPMD.ElseExpression)
*/
protected function task( $callback ) {
$result = false;
if ( is_callable( $callback ) ) {
BWF_Logger::get_instance()->log( 'Running the callback: ' . print_r( $callback, true ), 'woofunnels_contacts_indexing' ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r
$result = (bool) call_user_func( $callback );
if ( $result ) {
/**sleep( 5 );*/
BWF_Logger::get_instance()->log( "Result: $result Need to run again the callback: " . print_r( $callback, true ), 'woofunnels_contacts_indexing' ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r
} else {
BWF_Logger::get_instance()->log( "Result: $result Finished running the callback: " . print_r( $callback, true ), 'woofunnels_contacts_indexing' ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r
}
} else {
BWF_Logger::get_instance()->log( "Result: $result Could not find the callback: " . print_r( $callback, true ), 'woofunnels_contacts_indexing' ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r
}
return $result ? $callback : false;
}
/**
* See if the batch limit has been exceeded.
*
* @return bool
*/
protected function batch_limit_exceeded() {
return $this->time_exceeded() || $this->memory_exceeded();
}
/**
* Memory exceeded
*
* Ensures the batch process never exceeds 90%
* of the maximum WordPress memory.
*
* @return bool
*/
protected function memory_exceeded() {
$memory_limit = $this->get_memory_limit() * 0.9; // 90% of max memory
$current_memory = memory_get_usage( true );
$return = false;
if ( $current_memory >= $memory_limit ) {
$return = true;
}
return apply_filters( $this->identifier . '_memory_exceeded', $return );
}
/**
* Get memory limit.
*
* @return int
*/
protected function get_memory_limit() {
if ( function_exists( 'ini_get' ) ) {
$memory_limit = ini_get( 'memory_limit' );
} else {
// Sensible default.
$memory_limit = '128M';
}
if ( ! $memory_limit || - 1 === intval( $memory_limit ) ) {
// Unlimited, set to 32GB.
$memory_limit = '32G';
}
return wp_convert_hr_to_bytes( $memory_limit );
}
/**
* Complete
*
* Override if applicable, but ensure that the below actions are
* performed, or, call parent::complete().
*/
protected function complete() {
update_option( '_bwf_contacts_offset', 0 );
BWF_Logger::get_instance()->log( 'Background scanning completed for indexing contacts and creating updating contacts and customers.', 'woofunnels_contacts_indexing' );
delete_option( '_bwf_last_offsets' );
do_action( 'bwf_contacts_index_completed' );
parent::complete();
}
/**
* Is the updater running?
*
* @return boolean
*/
public function is_updating() {
return false === $this->is_queue_empty();
}
public function maybe_re_dispatch_background_process() {
if ( 3 !== absint( WooFunnels_Dashboard::$classes['WooFunnels_DB_Updater']->get_upgrade_state() ) ) {
return;
}
if ( $this->is_queue_empty() ) {
return;
}
if ( $this->is_process_running() ) {
return;
}
/**
* We are saving the last 5 offset value, due to any specific reason if last 5 offsets are same then it might be the time to kill the process.
*/
$offsets = $this->get_last_offsets();
if ( self::MAX_SAME_OFFSET_THRESHOLD === count( $offsets ) ) {
$unique = array_unique( $offsets );
if ( 1 === count( $unique ) ) {
$this->kill_process();
BWF_Logger::get_instance()->log( sprintf( 'Offset is stuck from last %d attempts, terminating the process.', self::MAX_SAME_OFFSET_THRESHOLD ), 'woofunnels_contacts_indexing' );
return;
}
}
$this->manage_last_offsets();
$this->dispatch();
}
/**
* Schedule fallback event.
*/
protected function schedule_event() {
if ( ! wp_next_scheduled( $this->cron_hook_identifier ) ) {
wp_schedule_event( time() + 10, $this->cron_interval_identifier, $this->cron_hook_identifier );
}
}
}
}

View File

@@ -0,0 +1,116 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Class WooFunnels_Create_DB_Tables
*/
if ( ! class_exists( 'WooFunnels_Create_DB_Tables' ) ) {
#[AllowDynamicProperties]
class WooFunnels_Create_DB_Tables {
/**
* instance of class
* @var null
*/
private static $ins = null;
/**
* Charector collation
*
* @since 2.0
*
* @var string
*/
protected $charset_collate;
/**
* @var bool
*/
protected $last_created_table = array();
/**
* WooFunnels_DB_Tables constructor.
*/
public function __construct() {
global $wpdb;
if ( $wpdb->has_cap( 'collation' ) ) {
$this->charset_collate = $wpdb->get_charset_collate();
}
}
/**
* @return WooFunnels_Create_DB_Tables|null
*/
public static function get_instance() {
if ( null === self::$ins ) {
self::$ins = new self;
}
return self::$ins;
}
/**
* @hooked over `admin_head`
* This method create new tables in database except core table
*/
public function create() {
require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
$current_table_list = get_option( '_bwf_db_table_list', array( 'tables' => array(), 'version' => '0.0.0' ) );
$tables = apply_filters( 'bwf_add_db_table_schema', array(), $current_table_list );
global $wpdb;
if ( is_array( $tables ) && count( $tables ) > 0 ) {
foreach ( $tables as $table ) {
$schema = $table['schema'];
$schema = str_replace( array( '{table_prefix}', '{table_collate}' ), array( $wpdb->prefix, $this->charset_collate ), $schema );
dbDelta( $schema );
/**
* Handle unique key error
* if table exists and try re-attempt to create table
*/
$table_name = $wpdb->prefix . $table['name'];
$esc_unique_key = "ALTER TABLE {$table_name} ADD UNIQUE KEY";
if ( ! empty( $wpdb->last_error ) && ( strpos( $wpdb->last_query, $esc_unique_key ) === false ) ) {
BWF_Logger::get_instance()->log( "bwf failed create table {$table['name']}: " . print_r( $wpdb->last_error, true ), 'woofunnel-failed-actions', 'buildwoofunnels', true ); //phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r
} else {
$this->last_created_table[] = $table['name'];
$current_table_list['tables'][] = $table['name'];
}
}
$current_table_list['version'] = BWF_DB_VERSION;
if ( isset( $current_table_list['tables'] ) && is_array( $current_table_list['tables'] ) ) {
$current_table_list['tables'] = array_values( array_unique( $current_table_list['tables'] ) );
}
update_option( '_bwf_db_table_list', $current_table_list, true );
} else {
if ( isset( $current_table_list['tables'] ) && is_array( $current_table_list['tables'] ) ) {
/**
* Check if array of table has duplicate values
*/
$current = array_values( array_unique( $current_table_list['tables'] ) );
if ( sizeof( $current ) !== sizeof( $current_table_list['tables'] ) ) {
$current_table_list['tables'] = $current;
update_option( '_bwf_db_table_list', $current_table_list, true );
}
}
}
}
/**
* get tables list which is created in current version
* @return array|bool
*/
public function maybe_table_created_current_version() {
return $this->last_created_table;
}
}
}

View File

@@ -0,0 +1,400 @@
<?php
/**
* Customer Class
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'WooFunnels_Customer' ) ) {
/**
* Class WooFunnels_Customer
*/
#[AllowDynamicProperties]
class WooFunnels_Customer {
/**
* public db_operations $db_operations
*/
public $db_operations;
/**
* public id $id
*/
public $id;
/**
* public cid $cid
*/
public $cid;
/**
* public contact $contact
*/
public $contact;
/**
* @var $db_customer
*/
public $db_customer;
/**
* Get the customer details for the contact object passed if this contact id exits otherwise create a new customer
* WooFunnels_Customer constructor.
*
* @param $cid
*
*/
public function __construct( $contact ) {
$this->db_operations = WooFunnels_DB_Operations::get_instance();
$this->cid = $contact->get_id();
$this->contact = $contact;
if ( empty( $this->cid ) || ( $this->cid < 1 ) ) {
return;
}
$this->db_customer = $this->get_customer_by_cid( $this->cid );
if ( isset( $this->db_customer->id ) && $this->db_customer->id > 0 ) {
$this->id = $this->db_customer->id;
}
}
/**
* Get customer by cid
*
* @param $wpid
*
* @return mixed
*/
public function get_customer_by_cid( $cid ) {
return $this->db_operations->get_customer_by_cid( $cid );
}
/**
* Get customer created date
*/
public function get_creation_date() {
$creation_date = ( isset( $this->creation_date ) && ! empty( $this->creation_date ) ) ? $this->creation_date : '';
$db_creation_date = ( isset( $this->db_customer->creation_date ) && ( $this->db_customer->creation_date > 0 ) ) ? $this->db_customer->creation_date : current_time( 'mysql' );
return empty( $creation_date ) ? $db_creation_date : $creation_date;
}
/**
* Set customer last order date
*
* @param $date
*/
public function set_l_order_date( $date ) {
$this->l_order_date = empty( $date ) ? $this->get_l_order_date() : $date;
}
/**
* Get customer last order date
*/
public function get_l_order_date() {
$order_date = ( isset( $this->l_order_date ) && ! empty( $this->l_order_date ) ) ? $this->l_order_date : '';
$db_data = ( isset( $this->db_customer->l_order_date ) && ! empty( $this->db_customer->l_order_date ) ) ? $this->db_customer->l_order_date : '0000-00-00';
return empty( $order_date ) ? $db_data : $order_date;
}
/**
* Set customer last order date
*
* @param $date
*/
public function set_f_order_date( $date ) {
$this->f_order_date = empty( $date ) ? $this->get_f_order_date() : $date;
}
/**
* Get customer last order date
*/
public function get_f_order_date() {
$order_date = ( isset( $this->f_order_date ) && ! empty( $this->f_order_date ) ) ? $this->f_order_date : '';
$db_data = ( isset( $this->db_customer->f_order_date ) && ! empty( $this->db_customer->f_order_date ) ) ? $this->db_customer->f_order_date : '0000-00-00';
return empty( $order_date ) ? $db_data : $order_date;
}
/**
* Set total order count
*
* @param $count
*/
public function set_total_order_count( $count ) {
$this->total_order_count = ( $count >= 0 ) ? $count : $this->get_total_order_count();
}
/**
* Get total order count
*/
public function get_total_order_count() {
$total_order = ( isset( $this->total_order_count ) && ! empty( $this->total_order_count ) ) ? $this->total_order_count : 0;
$db_data = ( isset( $this->db_customer->total_order_count ) && ! empty( $this->db_customer->total_order_count ) ) ? $this->db_customer->total_order_count : 0;
return empty( $total_order ) ? $db_data : $total_order;
}
/**
* Set total order value
*
* @param $value
*/
public function set_total_order_value( $value ) {
$this->total_order_value = ( $value >= 0 ) ? $value : $this->get_total_order_value();
}
/**
* Get total order value
*/
public function get_total_order_value() {
$total_order_value = ( isset( $this->total_order_value ) && $this->total_order_value >= 0 ) ? $this->total_order_value : false;
$db_data = ( isset( $this->db_customer->total_order_value ) && ! empty( $this->db_customer->total_order_value ) ) ? $this->db_customer->total_order_value : 0;
return false !== $total_order_value ? $total_order_value : $db_data;
}
/**
* Set customer AOV
*
* @param $value
*/
public function set_aov( $value ) {
$this->aov = $value;
}
/**
* Get customer AOV
*
* @return int
*/
public function get_aov() {
$aov = ( isset( $this->aov ) && ! empty( $this->aov ) ) ? $this->aov : 0;
$db_data = ( isset( $this->db_customer->aov ) && ! empty( $this->db_customer->aov ) ) ? $this->db_customer->aov : 0;
return empty( $aov ) ? $db_data : $aov;
}
/**
* Set purchased products
*
* @param $products
*/
public function set_purchased_products( $products ) {
$this->purchased_products = empty( $products ) ? $this->get_purchased_products() : $products;
}
/**
* Get purchased products
*
*/
public function get_purchased_products() {
$products = ( isset( $this->purchased_products ) && ! empty( $this->purchased_products ) ) ? $this->purchased_products : array();
$db_products = isset( $this->db_customer->purchased_products ) ? $this->db_customer->purchased_products : array();
if ( ! empty( $db_products ) && ! is_array( $db_products ) ) {
$db_products = json_decode( $db_products, true );
}
if ( ! empty( $products ) && ! is_array( $products ) ) {
$products = json_decode( $products, true );
}
$arr = empty( $products ) ? $db_products : $products;
if ( is_array( $arr ) && count( $arr ) > 0 ) {
$arr = array_map( 'intval', $arr );
}
return $arr;
}
/**
* Set purchased product categories
*
* @param $cats
*/
public function set_purchased_products_cats( $cats ) {
$this->purchased_products_cats = empty( $cats ) ? $this->get_purchased_products_cats() : $cats;
}
/**
* Get purchased product categories
*
*/
public function get_purchased_products_cats() {
$purchased_products_cats = ( isset( $this->purchased_products_cats ) && ! empty( $this->purchased_products_cats ) ) ? $this->purchased_products_cats : array();
$db_purchased_products_cats = isset( $this->db_customer->purchased_products_cats ) ? $this->db_customer->purchased_products_cats : array();
if ( ! empty( $db_purchased_products_cats ) && ! is_array( $db_purchased_products_cats ) ) {
$db_purchased_products_cats = json_decode( $db_purchased_products_cats, true );
}
if ( ! empty( $purchased_products_cats ) && ! is_array( $purchased_products_cats ) ) {
$purchased_products_cats = json_decode( $purchased_products_cats, true );
}
$arr = empty( $purchased_products_cats ) ? $db_purchased_products_cats : $purchased_products_cats;
if ( is_array( $arr ) && count( $arr ) > 0 ) {
$arr = array_map( 'intval', $arr );
}
return $arr;
}
/**
* Set purchased product tags
*
* @param $tags
*/
public function set_purchased_products_tags( $tags ) {
$this->purchased_products_tags = empty( $tags ) ? $this->get_purchased_products_tags() : $tags;
}
/**
* Get purchased product tags
*
*/
public function get_purchased_products_tags() {
$purchased_products_tags = ( isset( $this->purchased_products_tags ) && ! empty( $this->purchased_products_tags ) ) ? $this->purchased_products_tags : array();
$db_purchased_products_tags = isset( $this->db_customer->purchased_products_tags ) ? $this->db_customer->purchased_products_tags : array();
if ( ! empty( $db_purchased_products_tags ) && ! is_array( $db_purchased_products_tags ) ) {
$db_purchased_products_tags = json_decode( $db_purchased_products_tags, true );
}
if ( ! empty( $purchased_products_tags ) && ! is_array( $purchased_products_tags ) ) {
$purchased_products_tags = json_decode( $purchased_products_tags, true );
}
$arr = empty( $purchased_products_tags ) ? $db_purchased_products_tags : $purchased_products_tags;
if ( is_array( $arr ) && count( $arr ) > 0 ) {
$arr = array_map( 'intval', $arr );
}
return $arr;
}
/**
* Set used coupons
*
* @param $state
*/
public function set_used_coupons( $coupons ) {
$this->used_coupons = empty( $coupons ) ? $this->get_used_coupons() : $coupons;
}
/**
* Get customer used coupons
*/
public function get_used_coupons() {
$coupons = isset( $this->used_coupons ) ? $this->used_coupons : array();
$db_coupons = isset( $this->db_customer->used_coupons ) ? $this->db_customer->used_coupons : array();
if ( ! empty( $coupons ) && ! is_array( $coupons ) ) {
$coupons = json_decode( $coupons, true );
}
if ( ! empty( $db_coupons ) && ! is_array( $db_coupons ) ) {
$db_coupons = json_decode( $db_coupons, true );
}
return ! empty( $coupons ) ? $coupons : $db_coupons;
}
/**
* Set customer created date
*
* @param $date
*/
public function set_creation_date( $date ) {
$this->creation_date = $date;
}
/**
* Updating customer table with set data
* @SuppressWarnings(PHPMD.BooleanArgumentFlag)
*/
public function save() {
$customer = array();
$customer['l_order_date'] = $this->get_l_order_date();
$customer['f_order_date'] = $this->get_f_order_date();
$customer['total_order_count'] = $this->get_total_order_count();
$customer['total_order_value'] = $this->get_total_order_value();
$customer['aov'] = ( $customer['total_order_value'] > 0 ) ? $customer['total_order_value'] / absint( $customer['total_order_count'] ) : $customer['total_order_value'];
$purchased_products = $this->get_purchased_products();
$purchased_products = array_map( 'strval', $purchased_products );
$customer['purchased_products'] = wp_json_encode( $purchased_products );
$purchased_products_cats = $this->get_purchased_products_cats();
$purchased_products_cats = array_map( 'strval', $purchased_products_cats );
$customer['purchased_products_cats'] = wp_json_encode( $purchased_products_cats );
$purchased_products_tags = $this->get_purchased_products_tags();
$purchased_products_tags = array_map( 'strval', $purchased_products_tags );
$customer['purchased_products_tags'] = wp_json_encode( $purchased_products_tags );
$customer['used_coupons'] = wp_json_encode( $this->get_used_coupons() );
if ( ( $this->get_id() > 0 ) ) {
$customer['id'] = $this->get_id();
$this->db_operations->update_customer( $customer );
} elseif ( empty( $this->get_id() ) ) {
$customer['cid'] = $this->get_cid();
$this->id = $this->db_operations->insert_customer( $customer );
}
}
/**
* Get customer id
*/
public function get_id() {
$id = ( isset( $this->id ) && $this->id > 0 ) ? $this->id : 0;
$db_id = ( isset( $this->db_customer->id ) && ( $this->db_customer->id > 0 ) ) ? $this->db_customer->id : 0;
return ( $id > 0 ) ? $id : $db_id;
}
/**
* Set customer last order date
*
* @param $date
*/
public function set_id( $id ) {
$this->id = empty( $id ) ? $this->id : $id;
}
/**
* Get customer cid
*/
public function get_cid() {
$cid = ( isset( $this->cid ) && ! empty( $this->cid ) ) ? $this->cid : '';
$db_cid = ( isset( $this->db_customer->cid ) && ( $this->db_customer->cid > 0 ) ) ? $this->db_customer->cid : 0;
return empty( $cid ) ? $db_cid : $cid;
}
/**
* Set customer last order date
*
* @param $date
*/
public function set_cid( $cid ) {
$this->cid = empty( $cid ) ? $this->get_cid() : $cid;
}
/**
* Get customer by id
*
* @param $customer_id
*
* @return mixed
*/
public function get_customer_by_customer_id( $customer_id ) {
return $this->db_operations->get_customer_by_customer_id( $customer_id );
}
}
}

View File

@@ -0,0 +1,544 @@
<?php
/**
* WooFunnels customer and contact DB operations
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'WooFunnels_DB_Operations' ) ) {
/**
* Class WooFunnels_DB_Operations
*/
#[AllowDynamicProperties]
class WooFunnels_DB_Operations {
/**
* @var $ins
*/
public static $ins;
/**
* @var $contact_tbl
*/
public $contact_tbl;
/**
* @var $customer_tbl
*/
public $customer_tbl;
public $cache_query = [];
public $cache_meta_query = false;
public $cache_field_query = false;
/**
* WooFunnels_DB_Operations constructor.
*/
public function __construct() {
global $wpdb;
$this->contact_tbl = $wpdb->prefix . 'bwf_contact';
$this->contact_meta_tbl = $wpdb->prefix . 'bwf_contact_meta';
$this->customer_tbl = $wpdb->prefix . 'bwf_wc_customers';
}
/**
* @return WooFunnels_DB_Operations
*/
public static function get_instance() {
if ( null === self::$ins ) {
self::$ins = new self;
}
return self::$ins;
}
/**
* Inserting a new row in bwf_contact table
*
* @param $customer
*
* @return int
* @SuppressWarnings(PHPMD.DevelopmentCodeFragment)
*/
public function insert_contact( $contact ) {
if ( isset( $contact['id'] ) ) {
unset( $contact['id'] );
}
global $wpdb;
$inserted = $wpdb->insert( $this->contact_tbl, $contact ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
$lastId = 0;
if ( $inserted ) {
$lastId = $wpdb->insert_id;
}
if ( $wpdb->last_error !== '' ) {
BWF_Logger::get_instance()->log( 'Get last error in insert_contact: ' . print_r( $wpdb->last_error, true ), 'woofunnels_indexing' ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r
}
return $lastId;
}
/**
* Updating a contact
*
* @param $contact
*
* @return array|object|null
* @SuppressWarnings(PHPMD.DevelopmentCodeFragment)
*/
public function update_contact( $contact ) {
global $wpdb;
$update_data = array();
foreach ( is_array( $contact ) ? $contact : array() as $key => $value ) {
$update_data[ $key ] = $value;
}
$wpdb->update( $this->contact_tbl, $update_data, array( 'id' => $contact['id'] ) ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
if ( $wpdb->last_error !== '' ) {
BWF_Logger::get_instance()->log( "Get last error in update_customer for cid: {$contact['id']} " . print_r( $wpdb->last_error, true ), 'woofunnels_indexing' ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r
}
}
/**
* Getting contacts
*
* @return array|object|null
*/
public function get_all_contacts_count() {
global $wpdb;
$sql = "SELECT COUNT(id) FROM `$this->contact_tbl`";
return $wpdb->get_var( $sql ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
}
/**
* Getting contacts based on given criteria
*
* @param $args
*
* @return array|object|null
*/
public function get_contacts( $args ) {
global $wpdb;
$query = array();
$query['select'] = 'SELECT * ';
$query['from'] = "FROM {$this->contact_tbl} AS contact";
$query['where'] = ' WHERE 1=1 ';
if ( ! empty( $args['min_creation_date'] ) ) {
$query['where'] .= "AND contact.creation_date >= '" . gmdate( 'Y-m-d H:i:s', $args['min_creation_date'] ) . "'"; //phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
}
if ( ! empty( $args['max_creation_date'] ) ) {
$query['where'] .= "AND contact.creation_date < '" . gmdate( 'Y-m-d H:i:s', $args['max_creation_date'] ) . "'"; //phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
}
if ( - 1 !== $args['contact_limit'] ) {
$query['limit'] = "LIMIT {$args['contact_limit']}";
}
$query = implode( ' ', $query );
return $wpdb->get_results( $query ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
}
protected function get_set_cached_response( $sql, $get = 'row' ) {
global $wpdb;
if ( 'row' === $get ) {
$result = $wpdb->get_row( $sql ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
} elseif ( 'var' === $get ) {
$result = $wpdb->get_var( $sql ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
} elseif ( 'col' === $get ) {
$result = $wpdb->get_col( $sql ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
} else {
$result = $wpdb->get_results( $sql ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
}
return $result;
}
/**
* Get contact for given uid id if it exists
*/
public function get_contact( $uid ) {
global $wpdb;
$sql = "SELECT * FROM `$this->contact_tbl` WHERE `uid` = %s";
$sql = $wpdb->prepare( $sql, $uid );
return $this->get_set_cached_response( $sql );
}
/**
* Get contact for given wpid id if it exists
*/
public function get_contact_by_wpid( $wp_id ) {
global $wpdb;
$sql = "SELECT * FROM `$this->contact_tbl` WHERE `wpid` = %d";
$sql = $wpdb->prepare( $sql, $wp_id );
return $this->get_set_cached_response( $sql );
}
/**
* Get contact for given email id if it exists
*/
public function get_contact_by_email( $email ) {
global $wpdb;
$sql = "SELECT * FROM `$this->contact_tbl` WHERE `email` = %s";
$sql = $wpdb->prepare( $sql, $email );
return $this->get_set_cached_response( $sql );
}
/**
* Get contact by given phone number
*
* @param $phone
*
* @return array|object|void|null
*/
public function get_contact_by_phone( $phone ) {
global $wpdb;
$sql = "SELECT * FROM `$this->contact_tbl` WHERE `contact_no` = %s";
$sql = $wpdb->prepare( $sql, $phone );
return $this->get_set_cached_response( $sql );
}
/**
* Get contact for given contact id if it exists
*/
public function get_contact_by_contact_id( $contact_id ) {
global $wpdb;
$sql = "SELECT * FROM `$this->contact_tbl` WHERE `id` = %d";
$sql = $wpdb->prepare( $sql, $contact_id );
return $this->get_set_cached_response( $sql );
}
/**
* Get all contact meta key value for a given contact id
*
* @param $contact_id
*
* @return array|object|null
*/
public function get_contact_metadata( $contact_id ) {
global $wpdb;
$sql = "SELECT `meta_key`, `meta_value` FROM `$this->contact_meta_tbl` WHERE `contact_id` = %d";
$sql = $wpdb->prepare( $sql, $contact_id );
if ( true === $this->cache_meta_query ) {
// extra caching when variable is set, used in actions like FKA broadcast
if ( isset( $this->cache_query['meta'] ) && isset( $this->cache_query['meta'][ $contact_id ] ) ) {
return $this->cache_query['meta'][ $contact_id ];
}
if ( ! isset( $this->cache_query['meta'] ) ) {
$this->cache_query['meta'] = [];
}
$this->cache_query['meta'][ $contact_id ] = $this->get_set_cached_response( $sql, 'results' );
return $this->cache_query['meta'][ $contact_id ];
}
return $this->get_set_cached_response( $sql, 'results' );
}
/**
* @param $contact_id
* @param $contact_meta
*/
public function save_contact_meta( $contact_id, $contact_meta ) {
global $wpdb;
foreach ( is_object( $contact_meta ) ? $contact_meta : array() as $meta_key => $meta_value ) {
$meta_exists = false;
$meta_value = ( is_array( $meta_value ) ) ? maybe_serialize( $meta_value ) : $meta_value;
if ( $this->meta_id_exists( $contact_id, $meta_key ) ) {
$meta_exists = true;
//phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
$wpdb->update( $this->contact_meta_tbl, array(
'meta_value' => $meta_value, //phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
), array(
'meta_key' => $meta_key, //phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
'contact_id' => $contact_id,
), array(
'%s', // meta_value
), array( '%s', '%s' ) );
}
if ( ! $meta_exists ) {
$contact_meta = array(
'contact_id' => $contact_id,
'meta_key' => $meta_key, //phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
'meta_value' => $meta_value, //phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
);
$wpdb->insert( $this->contact_meta_tbl, $contact_meta ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
}
}
}
/**
* @param $contact_id
* @param $meta_key
*/
public function meta_id_exists( $contact_id, $meta_key ) {
global $wpdb;
$sql = "SELECT `meta_id` FROM `$this->contact_meta_tbl` WHERE `contact_id` = '$contact_id' AND `meta_key` = '$meta_key'";
$meta_id = $wpdb->get_var( $sql ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
return ( ! empty( $meta_id ) && $meta_id > 0 ) ? true : false;
}
/**
* @param $contact_id
* @param $meta_key
* @param $meta_value
*
* @return int
*/
public function update_contact_meta( $contact_id, $meta_key, $meta_value ) {
global $wpdb;
$db_meta_value = $this->get_contact_meta_value( $contact_id, $meta_key );
if ( is_array( $meta_value ) || is_object( $meta_value ) ) {
$meta_value_ids = empty( $db_meta_value ) ? array() : json_decode( $db_meta_value, true );
if ( false === is_array( $meta_value_ids ) ) {
$meta_value_ids = [];
}
if ( false === is_array( $meta_value ) ) {
$meta_value = [];
}
$meta_value = wp_json_encode( array_unique( array_merge( $meta_value_ids, $meta_value ) ) );
}
$meta_exists = false;
if ( $this->meta_id_exists( $contact_id, $meta_key ) ) {
$meta_exists = true;
//phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
$wpdb->update( $this->contact_meta_tbl, array(
'meta_value' => $meta_value, //phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
), array(
'meta_key' => $meta_key, //phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
'contact_id' => $contact_id,
), array(
'%s', // meta_value
), array( '%s', '%s' ) );
}
if ( ! $meta_exists ) {
$contact_meta = array(
'contact_id' => $contact_id,
'meta_key' => $meta_key, //phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
'meta_value' => $meta_value, //phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
);
$inserted = $wpdb->insert( $this->contact_meta_tbl, $contact_meta );//phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
$last_id = 0;
if ( $inserted ) {
$last_id = $wpdb->insert_id;
}
return $last_id;
}
}
/**
* Get contact meta for a given contact id and meta key
*
* @param $contact_id
*
* @return string|null
*/
public function get_contact_meta_value( $contact_id, $meta_key ) {
global $wpdb;
$sql = "SELECT `meta_value` FROM `$this->contact_meta_tbl` WHERE `contact_id` = %d AND `meta_key` = %s";
$sql = $wpdb->prepare( $sql, $contact_id, $meta_key );
return $this->get_set_cached_response( $sql, 'var' );
}
/**
* Inserting a new row in bwf_customer table
*
* @param $customer
*
* @return int
* @SuppressWarnings(PHPMD.DevelopmentCodeFragment)
*/
public function insert_customer( $customer ) {
global $wpdb;
$customer_data = array(
'cid' => $customer['cid'],
'l_order_date' => $customer['l_order_date'],
'f_order_date' => $customer['f_order_date'],
'total_order_count' => $customer['total_order_count'],
'total_order_value' => $customer['total_order_value'],
'aov' => $customer['aov'],
'purchased_products' => $customer['purchased_products'],
'purchased_products_cats' => $customer['purchased_products_cats'],
'purchased_products_tags' => $customer['purchased_products_tags'],
'used_coupons' => $customer['used_coupons'],
);
$inserted = $wpdb->insert( $this->customer_tbl, $customer_data ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
$lastId = 0;
if ( $inserted ) {
$lastId = $wpdb->insert_id;
}
if ( $wpdb->last_error !== '' ) {
BWF_Logger::get_instance()->log( 'Get last error in insert_customer: ' . print_r( $wpdb->last_error, true ), 'woofunnels_indexing' ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r
}
return $lastId;
}
/**
* Updating a customer
*
* @param $customer
*
* @return array|object|null
* @SuppressWarnings(PHPMD.DevelopmentCodeFragment)
*/
public function update_customer( $customer ) {
global $wpdb;
$update_data = array();
foreach ( is_array( $customer ) ? $customer : array() as $key => $value ) {
$update_data[ $key ] = $value;
}
$wpdb->update( $this->customer_tbl, $update_data, array( 'id' => $customer['id'] ) ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
if ( $wpdb->last_error !== '' ) {
BWF_Logger::get_instance()->log( "Get last error in update_customer for cid: {$customer['cid']} " . print_r( $wpdb->last_error, true ), 'woofunnels_indexing' ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r
}
}
/**
* Getting customers based on given criteria
*
* @param $args
*
* @return array|object|null
*/
public function get_customers( $args ) {
global $wpdb;
$query = array();
$query['select'] = 'SELECT * ';
$query['from'] = "FROM {$this->customer_tbl} AS customer";
$query['where'] = '';
$query['where'] = ' WHERE 1=1 ';
$query['where'] .= '
AND customer.total_order_count >= ' . $args['min_order_count'] . '
AND customer.total_order_count < ' . $args['max_order_count'] . '
AND customer.total_order_value >= ' . $args['min_order_value'] . '
AND customer.total_order_value < ' . $args['max_order_value'] . '
';
if ( ! empty( $args['min_last_order_date'] ) ) {
$query['where'] .= "
AND customer.l_order_date >= '" . gmdate( 'Y-m-d H:i:s', $args['min_last_order_date'] ) . "'
";
}
if ( ! empty( $args['max_last_order_date'] ) ) {
$query['where'] .= "
AND customer.l_order_date < '" . gmdate( 'Y-m-d H:i:s', $args['max_last_order_date'] ) . "'
";
}
if ( ! empty( $args['min_creation_date'] ) ) {
$query['where'] .= "
AND customer.creation_date >= '" . gmdate( 'Y-m-d H:i:s', $args['min_creation_date'] ) . "'";
}
if ( ! empty( $args['max_creation_date'] ) ) {
$query['where'] .= "
AND customer.creation_date < '" . gmdate( 'Y-m-d H:i:s', $args['max_creation_date'] ) . "'";
}
if ( - 1 !== $args['customer_limit'] ) {
$query['limit'] = "LIMIT {$args['customer_limit']}";
}
$query = implode( ' ', $query );
$customers = $wpdb->get_results( $query ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
return $customers;
}
/**
* Get customer for given uid id if it exists
*/
public function get_customer( $uid ) {
global $wpdb;
$sql = "SELECT * FROM `$this->customer_tbl` WHERE `uid` = %s";
$sql = $wpdb->prepare( $sql, $uid );
return $this->get_set_cached_response( $sql );
}
/**
* Get customer for given cid id if it exists
*/
public function get_customer_by_cid( $cid ) {
global $wpdb;
$sql = "SELECT * FROM `$this->customer_tbl` WHERE `cid` = %d";
$sql = $wpdb->prepare( $sql, $cid );
return $this->get_set_cached_response( $sql );
}
/**
* Get customer for given customer id if it exists
*/
public function get_customer_by_customer_id( $customer_id ) {
global $wpdb;
$sql = "SELECT * FROM `$this->customer_tbl` WHERE `id` = %d";
$sql = $wpdb->prepare( $sql, $customer_id );
return $this->get_set_cached_response( $sql );
}
/**
* Deleting a meta key from contact meta table
*
* @param $cid
* @param $meta_key
*/
public function delete_contact_meta( $cid, $meta_key ) {
global $wpdb;
if ( $this->meta_id_exists( $cid, $meta_key ) ) {
//phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
$wpdb->delete( $this->contact_meta_tbl, array(
'contact_id' => $cid,
'meta_key' => $meta_key, //phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
) );
}
}
}
WooFunnels_DB_Operations::get_instance();
}

View File

@@ -0,0 +1,135 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'WooFunnels_DB_Tables' ) ) {
/**
* Class WooFunnels_DB_Tables
*/
#[AllowDynamicProperties]
class WooFunnels_DB_Tables {
/**
* instance of class
* @var null
*/
private static $ins = null;
/**
* WooFunnels_DB_Tables constructor.
*/
public function __construct() {
add_filter( 'bwf_add_db_table_schema', array( $this, 'create_db_tables' ), 10, 2 );
}
/**
* @return WooFunnels_DB_Tables|null
*/
public static function get_instance() {
if ( null === self::$ins ) {
self::$ins = new self;
}
return self::$ins;
}
/**
* Add bwf_contact table
*
* Warning: check if it exists first, which could cause SQL errors.
*/
public function create_db_tables( $args, $tables ) {
if ( $tables['version'] !== BWF_DB_VERSION || ! in_array( 'bwf_contact', $tables['tables'], true ) ) {
$args[] = [
'name' => 'bwf_contact',
'schema' => "CREATE TABLE `{table_prefix}bwf_contact` (
`id` int(12) unsigned NOT NULL AUTO_INCREMENT,
`wpid` int(12) NOT NULL,
`uid` varchar(35) NOT NULL DEFAULT '',
`email` varchar(100) NOT NULL,
`f_name` varchar(100),
`l_name` varchar(100),
`contact_no` varchar(20),
`country` char(2),
`state` varchar(100),
`timezone` varchar(50) DEFAULT '',
`type` varchar(20) DEFAULT 'lead',
`source` varchar(100) DEFAULT '',
`points` bigint(20) unsigned NOT NULL DEFAULT '0',
`tags` longtext,
`lists` longtext,
`last_modified` DateTime NOT NULL,
`creation_date` DateTime NOT NULL,
`status` tinyint unsigned NOT NULL DEFAULT 1,
PRIMARY KEY (`id`),
KEY `id` (`id`),
KEY `wpid` (`wpid`),
KEY `uid` (`uid`),
KEY `contact_no` (`contact_no`),
KEY `last_modified` (`last_modified`),
KEY `creation_date` (`creation_date`),
KEY `status` (`status`),
UNIQUE KEY `email` (`email`)
) {table_collate};",
];
}
if ( $tables['version'] !== BWF_DB_VERSION || ! in_array( 'bwf_contact_meta', $tables['tables'], true ) ) {
$args[] = [
'name' => 'bwf_contact_meta',
'schema' => "CREATE TABLE `{table_prefix}bwf_contact_meta` (
`meta_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`contact_id` bigint(20) unsigned NOT NULL DEFAULT '0',
`meta_key` varchar(50) DEFAULT NULL,
`meta_value` longtext,
PRIMARY KEY (`meta_id`)
) {table_collate};",
];
}
if ( $tables['version'] !== BWF_DB_VERSION || ! in_array( 'bwf_wc_customers', $tables['tables'], true ) ) {
$args[] = [
'name' => 'bwf_wc_customers',
'schema' => "CREATE TABLE `{table_prefix}bwf_wc_customers` (
`id` int(12) unsigned NOT NULL AUTO_INCREMENT,
`cid` int(12) NOT NULL,
`l_order_date` DateTime NOT NULL,
`f_order_date` DateTime NOT NULL,
`total_order_count` int(7) unsigned NOT NULL,
`total_order_value` double NOT NULL,
`aov` double NOT NULL,
`purchased_products` longtext,
`purchased_products_cats` longtext,
`purchased_products_tags` longtext,
`used_coupons` longtext,
PRIMARY KEY (`id`),
KEY `id` (`id`),
UNIQUE KEY `cid` (`cid`)
) {table_collate};",
];
}
if ( $tables['version'] !== BWF_DB_VERSION || ! in_array( 'wfco_report_views', $tables['tables'], true ) ) {
$args[] = [
'name' => 'wfco_report_views',
'schema' => "CREATE TABLE `{table_prefix}wfco_report_views` (
id bigint(20) unsigned NOT NULL auto_increment,
date date NOT NULL,
no_of_sessions int(11) NOT NULL DEFAULT '1',
object_id bigint(20) DEFAULT '0',
type tinyint(2) NOT NULL COMMENT '1 - Abandonment 2 - Landing visited 3 - Landing converted 4 - Aero visited 5- Thank you visited 6 - NextMove 7 - Funnel session 8-Optin visited 9-Optin converted 10- Optin thank you visited 11- Optin thank you converted' DEFAULT '1',
PRIMARY KEY (id),
KEY date (date),
KEY object_id (object_id),
KEY type (type)
) {table_collate};",
];
}
return $args;
}
}
WooFunnels_DB_Tables::get_instance();
}

View File

@@ -0,0 +1,251 @@
{
"AF": "Afghanistan",
"AX": "\u00c5land Islands",
"AL": "Albania",
"DZ": "Algeria",
"AS": "American Samoa",
"AD": "Andorra",
"AO": "Angola",
"AI": "Anguilla",
"AQ": "Antarctica",
"AG": "Antigua and Barbuda",
"AR": "Argentina",
"AM": "Armenia",
"AW": "Aruba",
"AU": "Australia",
"AT": "Austria",
"AZ": "Azerbaijan",
"BS": "Bahamas",
"BH": "Bahrain",
"BD": "Bangladesh",
"BB": "Barbados",
"BY": "Belarus",
"PW": "Belau",
"BE": "Belgium",
"BZ": "Belize",
"BJ": "Benin",
"BM": "Bermuda",
"BT": "Bhutan",
"BO": "Bolivia",
"BQ": "Bonaire, Saint Eustatius and Saba",
"BA": "Bosnia and Herzegovina",
"BW": "Botswana",
"BV": "Bouvet Island",
"BR": "Brazil",
"IO": "British Indian Ocean Territory",
"BN": "Brunei",
"BG": "Bulgaria",
"BF": "Burkina Faso",
"BI": "Burundi",
"KH": "Cambodia",
"CM": "Cameroon",
"CA": "Canada",
"CV": "Cape Verde",
"KY": "Cayman Islands",
"CF": "Central African Republic",
"TD": "Chad",
"CL": "Chile",
"CN": "China",
"CX": "Christmas Island",
"CC": "Cocos (Keeling) Islands",
"CO": "Colombia",
"KM": "Comoros",
"CG": "Congo (Brazzaville)",
"CD": "Congo (Kinshasa)",
"CK": "Cook Islands",
"CR": "Costa Rica",
"HR": "Croatia",
"CU": "Cuba",
"CW": "Cura\u00e7ao",
"CY": "Cyprus",
"CZ": "Czech Republic",
"DK": "Denmark",
"DJ": "Djibouti",
"DM": "Dominica",
"DO": "Dominican Republic",
"EC": "Ecuador",
"EG": "Egypt",
"SV": "El Salvador",
"GQ": "Equatorial Guinea",
"ER": "Eritrea",
"EE": "Estonia",
"ET": "Ethiopia",
"FK": "Falkland Islands",
"FO": "Faroe Islands",
"FJ": "Fiji",
"FI": "Finland",
"FR": "France",
"GF": "French Guiana",
"PF": "French Polynesia",
"TF": "French Southern Territories",
"GA": "Gabon",
"GM": "Gambia",
"GE": "Georgia",
"DE": "Germany",
"GH": "Ghana",
"GI": "Gibraltar",
"GR": "Greece",
"GL": "Greenland",
"GD": "Grenada",
"GP": "Guadeloupe",
"GU": "Guam",
"GT": "Guatemala",
"GG": "Guernsey",
"GN": "Guinea",
"GW": "Guinea-Bissau",
"GY": "Guyana",
"HT": "Haiti",
"HM": "Heard Island and McDonald Islands",
"HN": "Honduras",
"HK": "Hong Kong",
"HU": "Hungary",
"IS": "Iceland",
"IN": "India",
"ID": "Indonesia",
"IR": "Iran",
"IQ": "Iraq",
"IE": "Ireland",
"IM": "Isle of Man",
"IL": "Israel",
"IT": "Italy",
"CI": "Ivory Coast",
"JM": "Jamaica",
"JP": "Japan",
"JE": "Jersey",
"JO": "Jordan",
"KZ": "Kazakhstan",
"KE": "Kenya",
"KI": "Kiribati",
"KW": "Kuwait",
"KG": "Kyrgyzstan",
"LA": "Laos",
"LV": "Latvia",
"LB": "Lebanon",
"LS": "Lesotho",
"LR": "Liberia",
"LY": "Libya",
"LI": "Liechtenstein",
"LT": "Lithuania",
"LU": "Luxembourg",
"MO": "Macao",
"MG": "Madagascar",
"MW": "Malawi",
"MY": "Malaysia",
"MV": "Maldives",
"ML": "Mali",
"MT": "Malta",
"MH": "Marshall Islands",
"MQ": "Martinique",
"MR": "Mauritania",
"MU": "Mauritius",
"YT": "Mayotte",
"MX": "Mexico",
"FM": "Micronesia",
"MD": "Moldova",
"MC": "Monaco",
"MN": "Mongolia",
"ME": "Montenegro",
"MS": "Montserrat",
"MA": "Morocco",
"MZ": "Mozambique",
"MM": "Myanmar",
"NA": "Namibia",
"NR": "Nauru",
"NP": "Nepal",
"NL": "Netherlands",
"NC": "New Caledonia",
"NZ": "New Zealand",
"NI": "Nicaragua",
"NE": "Niger",
"NG": "Nigeria",
"NU": "Niue",
"NF": "Norfolk Island",
"KP": "North Korea",
"MK": "North Macedonia",
"MP": "Northern Mariana Islands",
"NO": "Norway",
"OM": "Oman",
"PK": "Pakistan",
"PS": "Palestinian Territory",
"PA": "Panama",
"PG": "Papua New Guinea",
"PY": "Paraguay",
"PE": "Peru",
"PH": "Philippines",
"PN": "Pitcairn",
"PL": "Poland",
"PT": "Portugal",
"PR": "Puerto Rico",
"QA": "Qatar",
"RE": "Reunion",
"RO": "Romania",
"RU": "Russia",
"RW": "Rwanda",
"ST": "S\u00e3o Tom\u00e9 and Pr\u00edncipe",
"BL": "Saint Barth\u00e9lemy",
"SH": "Saint Helena",
"KN": "Saint Kitts and Nevis",
"LC": "Saint Lucia",
"SX": "Saint Martin (Dutch part)",
"MF": "Saint Martin (French part)",
"PM": "Saint Pierre and Miquelon",
"VC": "Saint Vincent and the Grenadines",
"WS": "Samoa",
"SM": "San Marino",
"SA": "Saudi Arabia",
"SN": "Senegal",
"RS": "Serbia",
"SC": "Seychelles",
"SL": "Sierra Leone",
"SG": "Singapore",
"SK": "Slovakia",
"SI": "Slovenia",
"SB": "Solomon Islands",
"SO": "Somalia",
"ZA": "South Africa",
"GS": "South Georgia\/Sandwich Islands",
"KR": "South Korea",
"SS": "South Sudan",
"ES": "Spain",
"LK": "Sri Lanka",
"SD": "Sudan",
"SR": "Suriname",
"SJ": "Svalbard and Jan Mayen",
"SZ": "Swaziland",
"SE": "Sweden",
"CH": "Switzerland",
"SY": "Syria",
"TW": "Taiwan",
"TJ": "Tajikistan",
"TZ": "Tanzania",
"TH": "Thailand",
"TL": "Timor-Leste",
"TG": "Togo",
"TK": "Tokelau",
"TO": "Tonga",
"TT": "Trinidad and Tobago",
"TN": "Tunisia",
"TR": "Turkey",
"TM": "Turkmenistan",
"TC": "Turks and Caicos Islands",
"TV": "Tuvalu",
"UG": "Uganda",
"UA": "Ukraine",
"AE": "United Arab Emirates",
"GB": "United Kingdom",
"US": "United States",
"UM": "United States (US) Minor Outlying Islands",
"UY": "Uruguay",
"UZ": "Uzbekistan",
"VU": "Vanuatu",
"VA": "Vatican",
"VE": "Venezuela",
"VN": "Vietnam",
"VG": "Virgin Islands (British)",
"VI": "Virgin Islands (US)",
"WF": "Wallis and Futuna",
"EH": "Western Sahara",
"YE": "Yemen",
"ZM": "Zambia",
"ZW": "Zimbabwe"
}

View File

@@ -0,0 +1,278 @@
<?php
/**
* Contact functions
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Providing a contact object
*
* @param $email
* @param $wp_id
*
* @return WooFunnels_Contact|WooFunnels_Customer
*/
if ( ! function_exists( 'bwf_get_contact' ) ) {
function bwf_get_contact( $wp_id, $email ) {
return new WooFunnels_Contact( $wp_id, $email );
}
}
if ( ! function_exists( 'bwf_create_update_contact' ) ) {
/**
* Creating updating contact and customer table
* On offer accepted, on order status change and on order indexing
*
* @param $order_id
* @param $products
* @param $total
* @param false $force
*
* @return int|void
*/
function bwf_create_update_contact( $order_id, $products, $total, $force = false ) {
$order = wc_get_order( $order_id );
if ( ! $order instanceof WC_Order ) {
return;
}
$wp_id = $order->get_customer_id();
$wp_email = '';
if ( $wp_id > 0 ) {
$wp_user = get_user_by( 'id', $wp_id );
$wp_email = ( $wp_user instanceof WP_User ) ? $wp_user->user_email : '';
}
$email = empty( $wp_email ) ? $order->get_billing_email() : $wp_email;
if ( empty( $email ) ) {
return;
}
$bwf_contact = bwf_get_contact( $wp_id, $email );
$bwf_email = isset( $bwf_contact->db_contact->email ) ? $bwf_contact->db_contact->email : '';
$bwf_wpid = isset( $bwf_contact->db_contact->wpid ) ? $bwf_contact->db_contact->wpid : 0;
if ( $wp_id > 0 && ( $bwf_wpid !== $wp_id ) ) {
$bwf_contact->set_wpid( $wp_id );
}
if ( ( empty( $bwf_email ) && ! empty( $email ) ) || ( ! empty( $wp_email ) && ( $bwf_email !== $email ) ) ) {
$bwf_contact->set_email( $email );
}
if ( true === $force ) {
bwf_create_update_contact_object( $bwf_contact, $order );
}
bwf_contact_maybe_update_creation_date( $bwf_contact, $order );
bwf_create_update_customer( $bwf_contact, $order, $order_id, $products, $total );
if ( true === $force ) {
do_action( 'bwf_normalize_contact_meta_before_save', $bwf_contact, $order_id, $order );
}
$bwf_contact->save();
if ( true === $force ) {
do_action( 'bwf_normalize_contact_meta_after_save', $bwf_contact, $order_id, $order );
}
$cid = $bwf_contact->get_id();
$order->update_meta_data( '_woofunnel_cid', $cid );
$order->save_meta_data();
return $cid;
}
}
/**
* @param WooFunnels_Contact $bwf_contact
* @param WC_order $order
*/
if ( ! function_exists( 'bwf_contact_maybe_update_creation_date' ) ) {
function bwf_contact_maybe_update_creation_date( $bwf_contact, $order ) {
$get_creation_date = $bwf_contact->get_creation_date();
if ( empty( $get_creation_date ) || $get_creation_date === '0000-00-00' || ( ! empty( $get_creation_date ) && $order->get_date_created() instanceof DateTime && ( strtotime( $get_creation_date ) > $order->get_date_created()->getTimestamp() ) ) ) {
$bwf_contact->set_creation_date( $order->get_date_created()->format( 'Y-m-d H:i:s' ) );
}
}
}
if ( ! function_exists( 'bwf_create_update_contact_object' ) ) {
/**
* Called on login, & checkout order processed
*
* @param $bwf_contact WooFunnels_Contact
* @param $order WC_Order
*
* @return mixed
*/
function bwf_create_update_contact_object( $bwf_contact, $order ) {
$wp_id = $order->get_customer_id();
/** If false then update the fields only when empty */
$force = ( true === WooFunnels_DB_Updater::$indexing ) ? false : true;
$wp_f_name = '';
$wp_l_name = '';
if ( $wp_id > 0 ) {
$wp_user = get_user_by( 'id', $wp_id );
$wp_f_name = ( $wp_user instanceof WP_User ) ? $wp_user->user_firstname : '';
$wp_l_name = ( $wp_user instanceof WP_User ) ? $wp_user->user_lastname : '';
}
$f_name = $order->get_billing_first_name();
$l_name = $order->get_billing_last_name();
$f_name = empty( $f_name ) ? $wp_f_name : $f_name;
$l_name = empty( $l_name ) ? $wp_l_name : $l_name;
$update_name = apply_filters( 'bwf_update_contact_name', true, $bwf_contact );
if ( ! empty( $f_name ) ) {
$should_skip_update = ( false === $force || false === $update_name ) && ! empty( $bwf_contact->get_f_name() );
if ( ! $should_skip_update ) {
$bwf_contact->set_f_name( $f_name );
}
}
if ( ! empty( $l_name ) ) {
$should_skip_update = ( false === $force || false === $update_name ) && ! empty( $bwf_contact->get_l_name() );
if ( ! $should_skip_update ) {
$bwf_contact->set_l_name( $l_name );
}
}
/** New contact */
if ( '' === $bwf_contact->get_status() ) {
if ( class_exists( 'BWFAN_Core' ) ) {
/** Check if consent value is 1 */
$marketing_status = $order->get_meta( 'marketing_status' );
if ( 1 === intval( $marketing_status ) ) {
$bwf_contact->set_status( 1 );
} else {
$bwf_contact->set_status( 0 );
}
} else {
$bwf_contact->set_status( 1 );
}
}
$order_country = $order->get_billing_country();
if ( ! empty( $order_country ) && 2 === strlen( $order_country ) ) {
$order_country = ( false === $force && ! empty( $bwf_contact->get_country() ) ) ? '' : $order_country;
$bwf_contact->set_country( $order_country );
}
$order_state = $order->get_billing_state();
if ( ! empty( $order_country ) && ! empty( $order_state ) ) {
$state = bwf_get_states( $order_country, $order_state );
$state = ( false === $force && ! empty( $bwf_contact->get_state() ) ) ? '' : $state;
$bwf_contact->set_state( $state );
}
$bwf_contact->set_type( 'customer' );
$contact_no = $order->get_billing_phone();
if ( empty( $contact_no ) && method_exists( $order, 'get_shipping_phone' ) ) {
$contact_no = $order->get_shipping_phone();
}
$timezone = bwf_get_timezone_from_order( $order );
if ( ! empty( $contact_no ) ) {
$contact_no = ( false === $force && ! empty( $bwf_contact->get_contact_no() ) ) ? '' : $contact_no;
/** Appending country code in phone number if not added */
if ( class_exists( 'BWFAN_Phone_Numbers' ) && ! empty( $contact_no ) && ! empty( $bwf_contact->get_country() ) ) {
$contact_no = BWFAN_Phone_Numbers::add_country_code( $contact_no, $bwf_contact->get_country() );
}
$bwf_contact->set_contact_no( $contact_no );
}
if ( ! empty( $timezone ) ) {
$timezone = ( false === $force && ! empty( $bwf_contact->get_timezone() ) ) ? '' : $timezone;
$bwf_contact->set_timezone( $timezone );
}
if ( empty( $bwf_contact->get_source() ) ) {
$bwf_contact->set_source( 'wc_order' );
}
return $bwf_contact;
}
}
if ( ! function_exists( 'bwf_get_timezone_from_order' ) ) {
/**
* @param $order WC_Order
*
* @return array|mixed|string
*/
function bwf_get_timezone_from_order( $order ) {
if ( ! $order instanceof WC_Order ) {
return '';
}
$may_be_timezone = BWF_WC_Compatibility::get_order_data( $order, '_wfacp_timezone' );
/** If set in order meta */
if ( ! empty( $may_be_timezone ) && true === bwf_if_valid_timezone( $may_be_timezone ) ) {
return $may_be_timezone;
}
/** Check for country */
$country = $order->get_billing_country();
ob_start();
include dirname( __DIR__ ) . '/contact/data/contries-timzone.json'; //phpcs:ignore WordPressVIPMinimum.Files.IncludingNonPHPFile.IncludingNonPHPFile
$list = ob_get_clean();
$list = json_decode( $list, true );
if ( ! is_array( $list ) || ! array_key_exists( $country, $list ) ) {
return '';
}
if ( ! isset( $list[ $country ] ) || ! isset( $list[ $country ]['timezone'] ) || count( $list[ $country ]['timezone'] ) === 0 ) {
return '';
}
return $list[ $country ]['timezone'][0];
}
}
if ( ! function_exists( 'bwf_if_valid_timezone' ) ) {
/**
* @param $timezone
*
* @return bool
*/
function bwf_if_valid_timezone( $timezone ) {
if ( empty( $timezone ) ) {
return false;
}
$zones = timezone_identifiers_list();
return in_array( $timezone, $zones, true );
}
}
if ( ! function_exists( 'bwf_get_countries_data' ) ) {
/** countries data
* @return mixed|null
*/
function bwf_get_countries_data() {
ob_start();
include dirname( __DIR__ ) . '/contact/data/countries.json'; //phpcs:ignore WordPressVIPMinimum.Files.IncludingNonPHPFile.IncludingNonPHPFile
$countries_data = ob_get_clean();
$countries = json_decode( $countries_data, true );
return $countries;
}
}

View File

@@ -0,0 +1,408 @@
<?php
/**
* Customer functions
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Providing a new customer object
*
* @param $contact
*
* @return WooFunnels_Customer
*/
function bwf_get_customer( $contact ) {
return new WooFunnels_Customer( $contact );
}
/**
* @param $bwf_contact
* @param $order WC_Order
* @param $order_id
* @param $products - only in case of upstroke upsell orders
* @param $total
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
if ( ! function_exists( 'bwf_create_update_customer' ) ) {
function bwf_create_update_customer( $bwf_contact, $order, $order_id, $products, $total ) {
if ( ! $order instanceof WC_Order ) {
return;
}
/** Registering customer as child entities to contact for using its object */
$bwf_contact->set_customer_child();
$indexed = BWF_WC_Compatibility::get_order_meta( $order, '_woofunnel_custid' );
if ( ! $indexed && ( ! is_array( $products ) || ( is_array( $products ) && count( $products ) < 1 ) ) ) { //Non-batching un-indexed order
$bwf_contact->set_customer_total_order_count( $bwf_contact->get_customer_total_order_count() + 1 );
}
$total_change = false;
$new_total = 0;
if ( ( $total > 0 && $indexed ) ) {
/** Offer accepted and parent order already indexed and batching is on */
$new_total = $total - $order->get_total_refunded();
$total_change = true;
} elseif ( ! $indexed ) {
/** new order checkout, payment status paid */
$new_total = $order->get_total() - $order->get_total_refunded();
$total_change = true;
}
if ( $total_change && $new_total >= 0 ) {
/** Convert to base currency */
$fixed_order_spent = BWF_Plugin_Compatibilities::get_fixed_currency_price_reverse( $new_total, BWF_WC_Compatibility::get_order_currency( $order ) );
$db_total_order_spent = $bwf_contact->get_customer_total_order_value();
$fixed_order_spent = $fixed_order_spent + $db_total_order_spent;
$bwf_contact->set_customer_total_order_value( $fixed_order_spent );
}
/**BWF_Logger::get_instance()->log( "Order id: $order_id, Indexed: $indexed, New Total: $new_total, TotalChange: $total_change, Total: $total, OrderTotal: {$order->get_total()}, DatePaid: {$order->get_date_paid()}", "customer_batch" );*/
$product_ids = $cat_ids = $tag_ids = array();
$subscription_renewal = BWF_WC_Compatibility::get_order_meta( $order, '_subscription_renewal' );
if ( empty( $subscription_renewal ) ) { //Don't scan a subscription renewal order for products, cats and tags
$is_batching = false;
$db_products = $bwf_contact->get_customer_purchased_products();
$db_cats = $bwf_contact->get_customer_purchased_products_cats();
$db_tags = $bwf_contact->get_customer_purchased_products_tags();
$cat_ids = $db_cats;
$tag_ids = $db_tags;
if ( is_array( $products ) && count( $products ) > 0 ) { //batching on current offer package products and parent order is already been indexed
$is_batching = true;
foreach ( $products as $product_id ) {
if ( ! in_array( $product_id, $db_products, true ) && ! in_array( $product_id, $product_ids, true ) && $product_id > 0 ) {
array_push( $product_ids, $product_id );
}
$product = wc_get_product( $product_id );
if ( $product->is_type( 'variation' ) ) {
$product_id = $product->get_parent_id();
if ( ! in_array( $product_id, $product_ids, true ) && ! in_array( $product_id, $db_products, true ) && $product_id > 0 ) {
array_push( $product_ids, $product_id );
}
}
$updated_tags_cats = bwf_update_cats_and_tags( $product_id, $cat_ids, $tag_ids );
$cat_ids = $updated_tags_cats['cats'];
$tag_ids = $updated_tags_cats['tags'];
}
}
if ( false === $is_batching ) {
foreach ( $order->get_items() as $item ) {
$product = $item->get_product();
if ( $product instanceof WC_Product ) {
$product_id = $product->get_id();
if ( ! in_array( $product_id, $product_ids, true ) && ! in_array( $product_id, $db_products, true ) && $product_id > 0 ) {
array_push( $product_ids, $product_id );
}
if ( $product->is_type( 'variation' ) ) {
$product_id = $product->get_parent_id();
if ( ! in_array( $product_id, $product_ids, true ) && ! in_array( $product_id, $db_products, true ) && $product_id > 0 ) {
array_push( $product_ids, $product_id );
}
}
$updated_tags_cats = bwf_update_cats_and_tags( $product_id, $cat_ids, $tag_ids );
$cat_ids = $updated_tags_cats['cats'];
$tag_ids = $updated_tags_cats['tags'];
}
}
$db_used_coupons = $bwf_contact->get_customer_used_coupons();
$order_coupons = BWF_WC_Compatibility::get_used_coupons( $order );
if ( count( $order_coupons ) > 0 && ( count( array_diff( $order_coupons, $db_used_coupons ) ) > 0 || count( $db_used_coupons ) < 1 ) ) {
$final_coupons = array_unique( array_merge( $db_used_coupons, $order_coupons ) );
sort( $final_coupons );
$bwf_contact->set_customer_used_coupons( $final_coupons );
}
}
if ( is_array( $product_ids ) && count( $product_ids ) > 0 && ( count( array_diff( $product_ids, $db_products ) ) > 0 || count( $db_products ) < 1 ) ) {
$final_products = bwf_get_array_unique_integers( $db_products, $product_ids );
$bwf_contact->set_customer_purchased_products( $final_products );
}
if ( count( $cat_ids ) > 0 && ( count( array_diff( $cat_ids, $db_cats ) ) > 0 || count( $db_cats ) < 1 ) ) {
$final_cats = bwf_get_array_unique_integers( $db_cats, $cat_ids );
$bwf_contact->set_customer_purchased_products_cats( $final_cats );
}
if ( count( $tag_ids ) > 0 && ( count( array_diff( $tag_ids, $db_tags ) ) > 0 || count( $db_tags ) < 1 ) ) {
$final_tags = bwf_get_array_unique_integers( $db_tags, $tag_ids );
$bwf_contact->set_customer_purchased_products_tags( $final_tags );
}
}
$bwf_l_order_date = $bwf_contact->get_customer_l_order_date();
$bwf_f_order_date = $bwf_contact->get_customer_f_order_date();
$order_created_date = $order->get_date_created()->date( 'Y-m-d H:i:s' );
if ( empty( $bwf_l_order_date ) || $bwf_l_order_date < $order_created_date ) {
$bwf_contact->set_customer_l_order_date( $order_created_date );
}
if ( empty( $bwf_f_order_date ) || $bwf_f_order_date === '0000-00-00' || $bwf_f_order_date === '0000-00-00 00:00:00' || $bwf_f_order_date > $order_created_date ) {
$bwf_contact->set_customer_f_order_date( $order_created_date );
}
$cid = $bwf_contact->get_id();
$bwf_contact->set_customer_cid( $cid );
$order->update_meta_data( '_woofunnel_custid', $cid );
$order->save_meta_data();
}
}
/**
* Setting category ids and tag ids
*
* @param $product_ids
* @param $product_id
*/
if ( ! function_exists( 'bwf_update_cats_and_tags' ) ) {
function bwf_update_cats_and_tags( $product_id, $cat_ids, $tag_ids ) {
$product_obj = wc_get_product( $product_id );
if ( ! $product_obj instanceof WC_Product ) {
return array(
'cats' => [],
'tags' => [],
);
}
/** Terms */
$product_cats = $product_obj->get_category_ids();
$product_tags = $product_obj->get_tag_ids();
$cat_ids = ( is_array( $product_cats ) ) ? array_merge( $cat_ids, $product_cats ) : [];
$tag_ids = ( is_array( $product_tags ) ) ? array_merge( $tag_ids, $product_tags ) : [];
$cat_ids = ( is_array( $cat_ids ) ) ? array_unique( $cat_ids ) : [];
$tag_ids = ( is_array( $tag_ids ) ) ? array_unique( $tag_ids ) : [];
return array(
'cats' => $cat_ids,
'tags' => $tag_ids,
);
}
}
/**
* Updating refunded amount in customer meta
*
* @param $order_id
* @param $amount
*/
if ( ! function_exists( 'bwf_update_customer_refunded' ) ) {
function bwf_update_customer_refunded( $order_id, $refund_amount ) {
$order = wc_get_order( $order_id );
$custid = BWF_WC_Compatibility::get_order_meta( $order, '_woofunnel_custid' );
if ( empty( $custid ) || 0 === $custid ) {
return;
}
$cid = BWF_WC_Compatibility::get_order_meta( $order, '_woofunnel_cid' );
$meta_key = '_bwf_customer_refunded';
$bwf_refunded = BWF_WC_Compatibility::get_order_meta( $order, $meta_key );
$bwf_refunded = empty( $bwf_refunded ) ? 0 : $bwf_refunded;
$bwf_contacts = BWF_Contacts::get_instance();
$bwf_contact = $bwf_contacts->get_contact_by( 'id', $cid );
$bwf_contact->set_customer_child();
$customer_total = $bwf_contact->get_customer_total_order_value();
$order_total = $order->get_total();
BWF_Logger::get_instance()->log( "Processing a refund for amount $refund_amount and order id: $order_id Order Total: $order_total, cid: $cid BWF Refunded: $bwf_refunded", 'woofunnels_indexing' );
if ( $refund_amount <= ( $order_total - $bwf_refunded ) ) {
/** Convert to base currency */
$refund_amount = BWF_Plugin_Compatibilities::get_fixed_currency_price_reverse( $refund_amount, BWF_WC_Compatibility::get_order_currency( $order ) );
$customer_total -= $refund_amount;
if ( $customer_total < 0 ) {
$customer_total = 0;
}
$bwf_contact->set_customer_total_order_value( $customer_total );
bwf_contact_maybe_update_creation_date( $bwf_contact, $order );
$bwf_contact->save();
$bwf_refunded += $refund_amount;
BWF_Logger::get_instance()->log( "Refund amount $refund_amount is reduced from customer meta 'total_value' for contact id: $cid Reduced total is: $customer_total ", 'woofunnels_indexing' );
}
$order->update_meta_data( $meta_key, $bwf_refunded );
$order->save_meta_data();
}
}
/**
* Reducing customer total spent on order cancelled
*
* @param $order_id
*/
if ( ! function_exists( 'bwf_reduce_customer_total_on_cancel' ) ) {
function bwf_reduce_customer_total_on_cancel( $order_id ) {
$order = wc_get_order( $order_id );
$custid = BWF_WC_Compatibility::get_order_meta( $order, '_woofunnel_custid' );
if ( empty( $custid ) ) {
return;
}
$cid = BWF_WC_Compatibility::get_order_meta( $order, '_woofunnel_cid' );
$meta_key = '_bwf_customer_refunded';
$bwf_refunded = BWF_WC_Compatibility::get_order_meta( $order, $meta_key );
$bwf_refunded = empty( $bwf_refunded ) ? 0 : $bwf_refunded;
$bwf_contacts = BWF_Contacts::get_instance();
$bwf_contact = $bwf_contacts->get_contact_by( 'id', $cid );
$order_total = $order->get_total();
$bwf_contact->set_customer_child();
$customer_total = $bwf_contact->get_customer_total_order_value();
$remaining_total = $order_total - $bwf_refunded;
BWF_Logger::get_instance()->log( "Processing a cancellation for order_id: $order_id, BWF Refunded: $bwf_refunded, Order Total: $order_total, Remaining order total: $remaining_total, Customer total: $customer_total", 'woofunnels_indexing' );
/** Convert to base currency */
$remaining_total = BWF_Plugin_Compatibilities::get_fixed_currency_price_reverse( $remaining_total, BWF_WC_Compatibility::get_order_currency( $order ) );
$customer_total -= $remaining_total;
if ( $customer_total < 0 ) {
$customer_total = 0;
}
$bwf_contact->set_customer_total_order_value( $customer_total );
bwf_contact_maybe_update_creation_date( $bwf_contact, $order );
$bwf_contact->save();
$order->update_meta_data( $meta_key, $order_total );
$order->save_meta_data();
BWF_Logger::get_instance()->log( "Order $order_id is cancelled for contact id: $cid. Reduced total is: $customer_total ", 'woofunnels_indexing' );
}
}
/**
* Return the total order amount
*
* @param $order WC_Order
*
* @return int
*/
if ( ! function_exists( 'bwf_get_order_total' ) ) {
function bwf_get_order_total( $order ) {
$total = 0;
if ( ! $order instanceof WC_Order ) {
return $total;
}
$total = $order->get_total() - $order->get_total_refunded();
$total = BWF_Plugin_Compatibilities::get_fixed_currency_price_reverse( $total, BWF_WC_Compatibility::get_order_currency( $order ) );
return $total;
}
}
/**
* Return the Order product items ids
*
* @param $order WC_Order
*
* @return array
*/
if ( ! function_exists( 'bwf_get_order_product_ids' ) ) {
function bwf_get_order_product_ids( $order ) {
$product_ids = [];
if ( ! $order instanceof WC_Order ) {
return $product_ids;
}
$products = $order->get_items();
if ( ! is_array( $products ) || count( $products ) === 0 ) {
return $product_ids;
}
$product_arr = [];
foreach ( $products as $val ) {
if ( ! $val instanceof WC_Order_Item_Product ) {
continue;
}
$product_id = $val->get_product_id();
$variation_id = $val->get_variation_id();
if ( $variation_id > 0 ) {
$product_id = $variation_id;
}
$product_arr[] = $product_id;
}
return $product_arr;
}
}
/**
* Return the Order product items categories and terms ids
*
* @param $order WC_Order
*
* @return array
*/
if ( ! function_exists( 'bwf_get_order_product_terms' ) ) {
function bwf_get_order_product_terms( $order ) {
$product_ids = [];
if ( ! $order instanceof WC_Order ) {
return $product_ids;
}
$products = $order->get_items();
if ( ! is_array( $products ) || ( is_array( $products ) && count( $products ) === 0 ) ) {
return $product_ids;
}
$order_cats = $order_tags = [];
$product_cats = false;
$product_tags = false;
foreach ( $products as $val ) {
if ( ! $val instanceof WC_Order_Item_Product ) {
continue;
}
/** @todo we can save this product obj as object cache so that can be used */
$product_obj = $val->get_product();
if ( ! $product_obj instanceof WC_Product ) {
continue;
}
/** Terms */
$product_cats = $product_obj->get_category_ids();
$product_tags = $product_obj->get_tag_ids();
$order_cats = ( is_array( $product_cats ) ) ? array_merge( $order_cats, $product_cats ) : [];
$order_tags = ( is_array( $product_tags ) ) ? array_merge( $order_tags, $product_tags ) : [];
}
$order_cats = ( is_array( $product_cats ) ) ? array_unique( $order_cats ) : [];
$order_tags = ( is_array( $product_tags ) ) ? array_unique( $order_tags ) : [];
return array(
'cats' => $order_cats,
'tags' => $order_tags,
);
}
}
/**
* Combine 2 arrays and return unique integer array values
*
* @param $arr
*
* @return mixed
*/
if ( ! function_exists( 'bwf_get_array_unique_integers' ) ) {
function bwf_get_array_unique_integers( $array1 = [], $array2 = [] ) {
$arr = array_unique( array_merge( $array1, $array2 ) );
sort( $arr );
$arr = array_map( 'intval', $arr );
return $arr;
}
}

View File

@@ -0,0 +1,129 @@
<?php
//Updating contact and customer tables functions in background
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
define( 'BWF_THRESHOLD_ORDERS', 0 ); //defining it more than 0 means you want the background to run only on "n" orders
define( 'BWF_ORDERS_PER_BATCH', 20 ); //defining it means how many orders to process per batch operation
/*** Updating customer tables ***/
if ( ! function_exists( 'bwf_create_update_contact_customer' ) ) {
/**
*
* @return bool|string
*/
function bwf_create_update_contact_customer() {
global $wpdb;
add_action( 'shutdown', [ WooFunnels_Dashboard::$classes['WooFunnels_DB_Updater'], 'capture_fatal_error' ] );
/**
* get the offset and the threshold of max orders to process
*/
$offset = get_option( '_bwf_offset', 0 );
$get_threshold_order = get_option( '_bwf_order_threshold', BWF_THRESHOLD_ORDERS );
$paid_statuses = implode( ',', array_map( function ( $status ) {
return "'wc-$status'";
}, wc_get_is_paid_statuses() ) );
if ( 0 === $get_threshold_order ) {
if ( ! BWF_WC_Compatibility::is_hpos_enabled() ) {
$query = $wpdb->prepare( "SELECT COUNT(p.ID) FROM {$wpdb->posts} AS p LEFT JOIN {$wpdb->postmeta} AS pm ON ( p.ID = pm.post_id AND pm.meta_key = '_woofunnel_cid') LEFT JOIN {$wpdb->postmeta} AS pm2 ON (p.ID = pm2.post_id) WHERE 1=1 AND pm.post_id IS NULL AND ( pm2.meta_key = '_billing_email' AND pm2.meta_value != '' ) AND p.post_type = %s AND p.post_status IN ({$paid_statuses})
ORDER BY p.post_date DESC", 'shop_order' );
} else {
$order_table = $wpdb->prefix . 'wc_orders';
$order_meta_table = $wpdb->prefix . 'wc_orders_meta';
$query = $wpdb->prepare( "SELECT COUNT(p.id) FROM {$order_table} AS p LEFT JOIN {$order_meta_table} AS pm ON ( p.id = pm.order_id AND pm.meta_key = '_woofunnel_cid') WHERE 1=1 AND pm.order_id IS NULL AND p.billing_email != '' AND
p.type = %s AND p.status IN ({$paid_statuses})
ORDER BY p.date_created_gmt DESC", 'shop_order' );
}
$query_results = $wpdb->get_var( $query ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
$get_threshold_order = $query_results;
update_option( '_bwf_order_threshold', $get_threshold_order );
}
/**************** PROCESS BATCH STARTS ************/
$numberposts = ( ( $offset > 0 ) && ( ( $get_threshold_order / $offset ) < 2 ) && ( ( $get_threshold_order % $offset ) < BWF_ORDERS_PER_BATCH ) ) ? ( $get_threshold_order % $offset ) : BWF_ORDERS_PER_BATCH;
if ( ! BWF_WC_Compatibility::is_hpos_enabled() ) {
$query = $wpdb->prepare( "SELECT p.ID FROM {$wpdb->posts} AS p LEFT JOIN {$wpdb->postmeta} AS pm ON ( p.ID = pm.post_id AND pm.meta_key = '_woofunnel_cid') LEFT JOIN {$wpdb->postmeta} AS pm2 ON (p.ID = pm2.post_id) WHERE 1=1 AND pm.post_id IS NULL AND ( pm2.meta_key = '_billing_email' AND pm2.meta_value != '' ) AND p.post_type = %s AND p.post_status IN ({$paid_statuses})
ORDER BY p.post_date DESC LIMIT 0, %d", 'shop_order', $numberposts );
} else {
$order_table = $wpdb->prefix . 'wc_orders';
$order_meta_table = $wpdb->prefix . 'wc_orders_meta';
$query = $wpdb->prepare( "SELECT p.id as ID FROM {$order_table} AS p LEFT JOIN {$order_meta_table} AS pm ON ( p.id = pm.order_id AND pm.meta_key = '_woofunnel_cid') WHERE 1=1 AND pm.order_id IS NULL AND p.billing_email != '' AND
p.type = %s AND p.status IN ({$paid_statuses})
ORDER BY p.date_created_gmt DESC LIMIT 0, %d", 'shop_order', $numberposts );
}
$query_results = $wpdb->get_results( $query ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
if ( empty( $query_results ) || ! is_array( $query_results ) ) {
return false;
}
$order_ids = array_map( function ( $query_instance ) {
return $query_instance->ID;
}, $query_results );
/**
* IF offset reached the threshold or no unindexed orders found, its time to terminate the batch process.
*/
if ( $offset >= $get_threshold_order || count( $order_ids ) < 1 ) {
BWF_Logger::get_instance()->log( 'Terminated on ' . $get_threshold_order, 'woofunnels_indexing' );
remove_action( 'shutdown', [ WooFunnels_Dashboard::$classes['WooFunnels_DB_Updater'], 'capture_fatal_error' ] );
return false;
}
/**
* @SuppressWarnings(PHPMD.DevelopmentCodeFragment)
*/
$retrieved_count = count( $order_ids );
BWF_Logger::get_instance()->log( "These $retrieved_count orders are retrieved: " . implode( ',', $order_ids ), 'woofunnels_indexing' ); //phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r
WooFunnels_DB_Updater::$indexing = true;
remove_all_actions( 'woocommerce_update_order' );
foreach ( $order_ids as $order_id ) {
WooFunnels_Dashboard::$classes['WooFunnels_DB_Updater']->set_order_id_in_process( $order_id );
bwf_create_update_contact( $order_id, array(), 0, true );
$offset ++;
update_option( '_bwf_offset', $offset );
}
WooFunnels_DB_Updater::$indexing = null;
/**************** PROCESS BATCH ENDS ************/
BWF_Logger::get_instance()->log( "bwf_create_update_contact_customer function returned. Offset: $offset, Order Count: $get_threshold_order ", 'woofunnels_indexing' );
remove_action( 'shutdown', [ WooFunnels_Dashboard::$classes['WooFunnels_DB_Updater'], 'capture_fatal_error' ] );
return 'bwf_create_update_contact_customer';
}
}
/*
* CONTACTS DATABASE STARTS
*/
if ( ! function_exists( 'bwf_contacts_v1_0_init_db_setup' ) ) {
function bwf_contacts_v1_0_init_db_setup() {
return 'bwf_contacts_v1_0_init_db_setup';
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -0,0 +1,2 @@
<?php
// Silence is golden.

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -0,0 +1,218 @@
<?php
if ( ! function_exists( 'bwf_get_remote_rest_args' ) ) {
/**
* Get wp remote post arguments
*
* @param $data
* @param $method
*
* @return mixed|void
*/
function bwf_get_remote_rest_args( $data = '', $method = 'POST' ) {
return apply_filters( 'bwf_get_remote_rest_args', [
'method' => $method,
'body' => $data,
'timeout' => 0.01,
'sslverify' => false,
] );
}
}
if ( ! function_exists( 'bwf_clean' ) ) {
/**
* Sanitize the given string or array
*
* @param $var
*
* @return array|mixed|string
*/
function bwf_clean( $var ) {
if ( is_array( $var ) ) {
return array_map( 'bwf_clean', $var );
}
return is_scalar( $var ) ? sanitize_text_field( $var ) : $var;
}
}
if ( ! function_exists( 'bwf_get_states' ) ) {
/**
* Get states nice name from country and state slugs
*
* @param $country
* @param $state
*
* @return mixed|string
*/
function bwf_get_states( $country = '', $state = '' ) {
$country_states = apply_filters( 'bwf_get_states', include WooFunnel_Loader::$ultimate_path . 'helpers/states.php' );
if ( empty( $state ) ) {
return '';
}
if ( empty( $country ) ) {
return $state;
}
if ( ! isset( $country_states[ $country ] ) ) {
return $state;
}
if ( ! isset( $country_states[ $country ][ $state ] ) ) {
return $state;
}
return $country_states[ $country ][ $state ];
}
}
if ( ! function_exists( 'bwf_get_fonts_list' ) ) {
/**
* get the list of all the registered fonts
* we have 3 modes here, 'standard', 'name_only','name_key' and 'all'
*
* @param string $mode
*
* @return array|int[]|mixed|string[]
*/
function bwf_get_fonts_list( $mode = 'standard' ) {
$fonts = [];
$font_path = WooFunnel_Loader::$ultimate_path . '/helpers/fonts.json';
$google_fonts = json_decode( file_get_contents( $font_path ), true ); //phpcs:ignore WordPressVIPMinimum.Performance.FetchingRemoteData.FileGetContentsUnknown
$web_fonts = ( $mode !== 'all' ) ? array_keys( $google_fonts ) : $google_fonts;
if ( $mode === 'all' || $mode === 'name_only' ) {
return $web_fonts;
}
/**
* if the name_key mode
*/
if ( $mode === 'name_key' ) {
foreach ( $web_fonts as $web_font_family ) {
if ( $web_font_family !== 'Open Sans' ) {
$fonts[ $web_font_family ] = $web_font_family;
}
}
return $fonts;
}
/**
* if standard mode
*/
$fonts[] = array(
'id' => 'default',
'name' => __( 'Default', 'woofunnels' ) // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
);
foreach ( $web_fonts as $web_font_family ) {
if ( $web_font_family !== 'Open Sans' ) {
$fonts[] = array(
'id' => $web_font_family,
'name' => $web_font_family,
);
}
}
return $fonts;
}
}
/**
* Converts a string (e.g. 'yes' or 'no' , 'true') to a bool.
*
* @param $string
*
* @return bool
*/
if ( ! function_exists( 'bwf_string_to_bool' ) ) {
function bwf_string_to_bool( $string ) {
return is_bool( $string ) ? $string : ( 'yes' === strtolower( $string ) || 1 === $string || 'true' === strtolower( $string ) || '1' === $string );
}
}
if ( ! function_exists( 'bwf_clear_queries' ) ) {
/**
* Dev
* Make WPDB queries empty
* @return void
*/
function bwf_clear_queries() {
global $wpdb;
$wpdb->queries = [];
}
}
if ( ! function_exists( 'bwf_save_queries' ) ) {
/**
* Dev
* Save DB calls from WPDB class object
*
* @param $file_name
* @param $folder_name
* @param $reference
*
* @return void
*/
function bwf_save_queries( $file_name = 'general', $folder_name = 'funnelkit', $reference = 'DB Call' ) {
global $wpdb;
if ( empty( $wpdb->queries ) || ! is_array( $wpdb->queries ) ) {
return;
}
$queries = [];
foreach ( $wpdb->queries as $q ) {
$queries[] = [ $q[0], $q[2] ];
}
$message = print_r( $queries, true );
$file_name = sanitize_title( $file_name );
$logger_obj = BWF_Logger::get_instance();
add_filter( 'bwf_logs_allowed', 'bwf_return_true', 99999 );
if ( ! empty( $reference ) ) {
$logger_obj->log( $reference, $file_name, $folder_name );
}
$logger_obj->log( $message, $file_name, $folder_name );
remove_filter( 'bwf_logs_allowed', 'bwf_return_true', 99999 );
}
}
if ( ! function_exists( 'bwf_return_true' ) ) {
/**
* @return bool
*/
function bwf_return_true() {
return true;
}
}
if ( ! function_exists( 'bwf_generate_random_bytes' ) ) {
/**
* Generate random bytes for the given count
*
* @param $count
*
* @return string
*/
function bwf_generate_random_bytes( $count ) {
$output = '';
$state = microtime();
if ( function_exists( 'getmypid' ) ) {
$state .= getmypid();
}
if ( strlen( $output ) < $count ) {
$output = '';
for ( $i = 0; $i < $count; $i += 16 ) {
$state = md5( microtime() . $state );
$output .= md5( $state, true );
}
$output = substr( $output, 0, $count );
}
return $output;
}
}

View File

@@ -0,0 +1,259 @@
<?php
/**
* Class to control breadcrumb and its behaviour accross the buildwoofunnels
* @author buildwoofunnels
*/
if ( ! class_exists( 'BWF_Admin_Breadcrumbs' ) ) {
#[AllowDynamicProperties]
class BWF_Admin_Breadcrumbs {
private static $ins = null;
/**
* @var array nodes use to contain all the nodes
*/
public static $nodes = [];
/**
* @var array ref used to contain refs to pass to the urls
*/
public static $ref = [];
/**
* Insert a single node into the property
*
* @param $config [] of the node getting registered
*/
public static function register_node( $config ) {
self::$nodes[] = wp_parse_args( $config, [ 'class' => '', 'link' => '', 'text' => '' ] );
}
/**
* Insert a referral property so that we can populate the referral across all urls.
*
* @param $key
* @param $val
*/
public static function register_ref( $key, $val ) {
self::$ref[ $key ] = $val;
}
/**
* Render HTML for all the registered nodes
*/
public static function render() {
if ( empty( self::$nodes ) ) {
return '';
}
$last_item = end( self::$nodes );
?>
<ul>
<li class="<?php echo esc_attr( $last_item['class'] ) ?>">
<?php echo wp_kses_post( $last_item['text'] ); ?>
</li>
</ul>
<?php
}
/**
* rearrange all the collected nodes and maybe print them
*
* @param false $return_nodes should just return nodes or print
*
* @return array|false
*/
public static function render_top_bar( $return_nodes = false ) {
if ( empty( self::$nodes ) ) {
return false;
}
if ( ! is_array( self::$nodes ) || count( self::$nodes ) == 0 ) {
return false;
}
self::$nodes = array_filter( self::$nodes, function ( $v ) {
if ( isset( $v['text'] ) && ! empty( $v['text'] ) ) {
return true;
}
} );
if ( ! is_array( self::$nodes ) || count( self::$nodes ) == 0 ) {
return false;
}
if ( true === $return_nodes ) {
return self::$nodes;
}
$count = count( self::$nodes );
$h = 0;
foreach ( self::$nodes as $menu ) {
if ( ! isset( $menu['text'] ) || empty( $menu['text'] ) ) {
continue;
}
$h ++;
echo '<span>';
if ( $count !== $h && isset( $menu['link'] ) && ! empty( $menu['link'] ) ) {
echo '<a href="' . esc_url($menu['link']) . '">' . $menu['text'] . '</a>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
} else {
echo $menu['text']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
echo '</span>';
}
return self::$nodes;
}
/**
* Add the registered referral to the url passed
* ref should contain the query param as key and value as value
*
* @param $url URL to add refs to
*
* @return string modified url
*/
public static function maybe_add_refs( $url ) {
if ( empty( self::$ref ) ) {
return $url;
}
return add_query_arg( self::$ref, $url );
}
public static function render_sticky_bar() {
?>
<style>
/* Sticky Bar */
.bwf-header-bar {
background: #fff;
box-sizing: border-box;
border-bottom: 1px solid #fff;
padding: 0 0 0 20px;
min-height: 56px;
position: fixed;
width: 100%;
top: 32px;
z-index: 1001;
display: flex;
align-items: center;
box-shadow: 0 0px 10px 0 #c8c8c8
}
.bwf-header-bar > img {
max-width: 24px
}
.bwf-bar-navigation {
font-size: 16px;
padding-left: 15px;
display: flex
}
.bwf-bar-navigation > span {
padding-right: 25px;
position: relative
}
.bwf-bar-navigation > span a {
text-decoration: none;
font-weight: normal
}
.bwf-bar-navigation > span:after {
content: "\f345";
font-family: 'dashicons';
font-size: 15px;
position: absolute;
right: 4px;
top: 1px
}
.bwf-bar-navigation > span:last-child:after {
content: ""
}
.bwf-bar-quick-links {
display: flex;
flex-direction: row;
align-items: center;
position: fixed;
right: 0;
top: 32px;
height: 56px
}
.bwf-bar-quick-links a.bwf-bar-link {
display: block;
font-size: 13px;
height: 56px;
text-decoration: none;
text-align: center;
padding: 0 10px;
min-width: 70px;
transition: all 0.4s ease;
-webkit-transition: all 0.4s ease;
box-sizing: border-box
}
.bwf-bar-quick-links a.bwf-bar-link:hover {
background: #f0f0f0
}
.bwf-bar-quick-links a * {
display: block;
margin: 0 auto;
padding: 0;
float: none;
color: #757575
}
.bwf-bar-quick-links a i {
font-size: 20px;
color: #757575;
margin-top: 8px
}
.wrap.bwf-funnel-common {
padding: 60px 0 0 20px;
margin: 0 20px 0 0
}
.bwf-header-bar .bwf-breadcrub-svg-icon {
max-width: 35px;
}
</style>
<div class="bwf-header-bar">
<img class="bwf-breadcrub-svg-icon" src="<?php echo esc_url( plugin_dir_url( WooFunnel_Loader::$ultimate_path ) . 'woofunnels/assets/img/bwf-icon-white-bg.svg' ); ?>"/>
<div class="bwf-bar-navigation">
<?php
global $submenu;
if ( array_key_exists( 'bwf_dashboard', $submenu ) ) {
echo '<span><a href="' . esc_url(admin_url( 'admin.php?page=bwf_dashboard' )) . '">FunnelKit</a></span> ';
}
if ( method_exists( 'BWF_Admin_Breadcrumbs', 'render_top_bar' ) ) {
BWF_Admin_Breadcrumbs::render_top_bar();
}
?>
</div>
<div class="bwf-bar-quick-links">
<a class="bwf-bar-link" href="https://funnelkit.com/documentation/" target="_blank">
<i class="dashicons dashicons-format-chat"></i>
<span>Docs</span>
</a>
<a class="bwf-bar-link" href="https://funnelkit.com/support/" target="_blank">
<i class="dashicons dashicons-businessman"></i>
<span>Support</span>
</a>
</div>
</div>
<?php
}
}
}

View File

@@ -0,0 +1,553 @@
<?php
/**
* Class to control Settings and its behaviour across the buildwoofunnels
* @author buildwoofunnels
*/
if ( ! class_exists( 'BWF_Admin_General_Settings' ) ) {
#[AllowDynamicProperties]
class BWF_Admin_General_Settings {
private static $ins = null;
private $options = array();
public function __construct() {
add_filter( 'woofunnels_global_settings', function ( $menu ) {
array_push( $menu, array(
'title' => __( 'General', 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'slug' => 'woofunnels_general_settings',
'link' => apply_filters( 'bwf_general_settings_link', 'javascript:void(0)' ),
'priority' => 5,
) );
return $menu;
} );
add_action( 'wp_ajax_bwf_general_settings_update', [ $this, 'update_general_settings' ] );
add_action( 'init', array( $this, 'maybe_flush_rewrite_rules' ), 101 );
add_action( 'admin_head', array( $this, 'hide_from_menu' ) );
add_filter( 'admin_title', array( $this, 'maybe_change_title' ), 99 );
add_filter( 'woofunnels_global_settings_fields', array( $this, 'add_settings_fields_array' ), 99 );
add_action( 'bwf_global_save_settings_woofunnels_general_settings', array( $this, 'update_global_settings_fields' ), 99 );
}
/**
* Get the instance of the BWF_Admin_General_Settings class
*
* @return BWF_Admin_General_Settings The instance of the class
*/
public static function get_instance() {
if ( null === self::$ins ) {
self::$ins = new self;
}
return self::$ins;
}
public function maybe_flush_rewrite_rules() {
$is_required_rewrite = get_option( 'bwf_needs_rewrite', 'no' );
if ( 'yes' === $is_required_rewrite ) {
flush_rewrite_rules(); // phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.flush_rewrite_rules_flush_rewrite_rules
WooFunnels_Dashboard::get_all_templates();
update_option( 'bwf_needs_rewrite', 'no', true );
}
}
public function add_settings_fields_array( $fields ) {
$fields['woofunnels_general_settings'] = $this->all_fields();
return $fields;
}
public function __callback() {
/** Registering Settings in top bar */
if ( class_exists( 'BWF_Admin_Breadcrumbs' ) ) {
BWF_Admin_Breadcrumbs::register_node( [ 'text' => 'Settings' ] );
}
BWF_Admin_Breadcrumbs::render_sticky_bar();
?>
<div class="wrap bwf-funnel-common">
<h1 class="wp-heading-inline"><?php esc_html_e( 'Settings', 'woofunnels' ); // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch ?></h1>
<?php
$admin_settings = BWF_Admin_Settings::get_instance();
$admin_settings->render_tab_html( 'woofunnels_general_settings' );
$i = 0;
?>
<div id="bwf_general_settings_vue_wrap" class="bwf-hide" v-bind:class="`1`===is_initialized?'bwf-show':''">
<div class="bwf-vue-custom-msg" v-if="'' != errorMsg"><p v-html="errorMsg"></p></div>
<div class="bwf-tabs-view-vertical bwf-widget-tabs">
<div class="bwf-tabs-wrapper">
<div class="bwf-tab-title" data-tab="<?php $i ++;
echo esc_attr($i); ?>" role="tab">
<?php esc_html_e( 'Permalinks', 'woofunnels' ); // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch ?>
</div>
<div class="bwf-tab-title" data-tab="<?php $i ++;
echo esc_attr($i); ?>" role="tab">
<?php esc_html_e( 'Facebook Pixel', 'woofunnels' ); // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch ?>
</div>
<div class="bwf-tab-title" data-tab="<?php $i ++;
echo esc_attr($i); ?>" role="tab">
<?php esc_html_e( 'Google Analytics', 'woofunnels' ); // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch ?>
</div>
<?php if ( apply_filters( 'bwf_enable_ecommerce_integration_gad', false ) ) { ?>
<div class="bwf-tab-title" data-tab="<?php $i ++;
echo esc_attr($i); ?>" role="tab">
<?php esc_html_e( 'Google Ads', 'woofunnels' ); // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch ?>
</div>
<?php }
if ( apply_filters( 'bwf_enable_ecommerce_integration_pinterest', false ) ) { ?>
<div class="bwf-tab-title" data-tab="<?php $i ++;
echo esc_attr($i); ?>" role="tab">
<?php esc_html_e( 'Pinterest', 'woofunnels' ); // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch ?>
</div>
<?php }
if ( apply_filters( 'bwf_enable_ecommerce_integration_tiktok', false ) ) { ?>
<div class="bwf-tab-title" data-tab="<?php $i ++;
echo esc_attr($i); ?>" role="tab">
<?php esc_html_e( 'TikTok', 'woofunnels' ); // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch ?>
</div>
<?php }
if ( apply_filters( 'bwf_enable_ecommerce_integration_snapchat', false ) ) { ?>
<div class="bwf-tab-title" data-tab="<?php $i ++;
echo esc_attr($i); ?>" role="tab">
<?php esc_html_e( 'Snapchat', 'woofunnels' ); // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch ?>
</div>
<?php } ?>
</div>
<div class="bwf-tabs-content-wrapper">
<div class="bwf_setting_inner">
<form class="bwf_forms_wrap">
<fieldset>
<vue-form-generator :schema="schema" :model="model" :options="formOptions"></vue-form-generator>
</fieldset>
<div style="display: none" id="modal-general-settings_success" data-iziModal-icon="icon-home">
</div>
</form>
<div class="bwf_form_button">
<span class="bwf_loader_global_save spinner" style="float: left;"></span>
<button v-on:click.self="onSubmit" class="bwf_save_btn_style"><?php esc_html_e( 'Save Changes', 'woofunnels' ); // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch ?></button>
</div>
</div>
</div>
</div>
</div>
</div>
<?php
}
public function default_general_settings() {
return apply_filters( 'bwf_general_settings_default_config', array(
'tiktok_pixel' => '',
'is_tiktok_add_to_cart_bump' => '',
'tiktok_add_to_cart_event' => '',
'tiktok_initiate_checkout_event' => '',
'is_tiktok_purchase_event' => array(),
'pint_key' => '',
'is_pint_lead_op' => array(),
'is_pint_add_to_cart_bump' => '',
'is_pint_custom_bump' => '',
'is_pint_page_view_lp' => array(),
'is_pint_page_view_op' => array(),
'is_pint_pageview_event' => array(),
'is_pint_page_view_global' => '',
'pint_is_page_view' => '',
'pint_add_to_cart_event' => '',
'pint_initiate_checkout_event' => '',
'is_pint_purchase_event' => array(),
'is_pint_custom_events' => '',
'pint_variable_as_simple' => '',
'pint_content_id_type' => '0',
'pint_content_id_prefix' => '',
'pint_content_id_suffix' => '',
'pint_exclude_from_total' => array(),
'gad_key' => '',
'gad_conversion_label' => '',
'gad_lead_conversion_label' => '',
'gad_addtocart_checkout_conversion_label' => '',
'gad_addtocart_bump_conversion_label' => '',
'gad_addtocart_global_conversion_label' => '',
'is_gad_page_view_global' => '',
'is_gad_view_item_global' => '',
'is_gad_page_view_lp' => array(),
'is_gad_page_view_op' => array(),
'is_gad_lead_op' => array(),
'is_gad_add_to_cart_bump' => '',
'is_gad_custom_bump' => '',
'google_ads_is_page_view' => '',
'google_ads_add_to_cart_event' => '',
'is_gad_pageview_event' => array(),
'is_gad_purchase_event' => array(),
'is_gad_custom_events' => '',
'google_ads_variable_as_simple' => '',
'google_ads_content_id_type' => '0',
'google_ads_content_id_prefix' => '',
'google_ads_content_id_suffix' => '',
'gad_exclude_from_total' => array(),
'ga_key' => '',
'is_ga_page_view_global' => '',
'is_ga_view_item_global' => '',
'is_ga_page_view_lp' => array(),
'is_ga_page_view_op' => array(),
'is_ga_lead_op' => array(),
'google_ua_is_page_view' => '',
'google_ua_add_to_cart_event' => '',
'google_ua_initiate_checkout_event' => '',
'google_ua_add_payment_info_event' => '',
'is_ga_purchase_page_view' => array(),
'is_ga_purchase_event' => array(),
'is_ga_custom_events' => '',
'google_ua_variable_as_simple' => '',
'google_ua_content_id_type' => '0',
'google_ua_content_id_prefix' => '',
'google_ua_content_id_suffix' => '',
'ga_exclude_from_total' => array(),
'fb_pixel_key' => '',
'conversion_api_access_token' => '',
'is_fb_conv_enable_test' => array(),
'conversion_api_test_event_code' => '',
'is_fb_conversion_api_log' => array(),
'is_fb_page_view_global' => '',
'is_fb_page_product_content_global' => '',
'is_fb_page_view_lp' => array(),
'is_fb_page_view_op' => array(),
'is_fb_lead_op' => array(),
'is_fb_add_to_cart_bump' => '',
'is_fb_custom_bump' => '',
'label_section_head_fb' => '',
'pixel_is_page_view' => '',
'pixel_initiate_checkout_event' => '',
'pixel_add_to_cart_event' => '',
'pixel_add_payment_info_event' => '',
'is_fb_purchase_page_view' => array(),
'is_fb_purchase_event' => array(),
'enable_general_event' => array(),
'general_event_name' => 'GeneralEvent',
'is_fb_custom_events' => '',
'is_fb_enable_content' => [],
'pixel_variable_as_simple' => '',
'pixel_content_id_type' => '0',
'pixel_content_id_prefix' => '',
'pixel_content_id_suffix' => '',
'exclude_from_total' => array(),
'is_fb_advanced_event' => array(),
'is_tiktok_advanced_event' => array(),
'default_selected_builder' => '',
'track_utms' => "1",
'snapchat_pixel' => '',
'is_snapchat_page_view_global' => '',
'is_snapchat_page_view_lp' => array(),
'is_snapchat_page_view_op' => array(),
'is_snapchat_add_to_cart_bump' => '',
'label_section_head_snapchat' => '',
'snapchat_is_page_view' => '',
'snapchat_add_to_cart_event' => '',
'snapchat_initiate_checkout_event' => '',
'snapchat_add_payment_info_event' => '',
'is_snapchat_purchase_event' => array(),
'snapchat_variable_as_simple' => '',
'is_fb_add_to_cart_global' => '',
'is_ga_add_to_cart_global' => '',
'is_gad_add_to_cart_global' => '',
'is_snapchat_add_to_cart_global' => '',
'is_tiktok_page_view_global' => '',
'is_tiktok_page_view_lp' => array(),
'is_tiktok_page_view_op' => array(),
'is_tiktok_pageview_event' => array(),
'tiktok_is_page_view' => '',
'tiktok_variable_as_simple' => '',
'is_tiktok_add_to_cart_global' => '',
'is_pint_add_to_cart_global' => '',
'is_pint_page_visit_global' => '',
'track_traffic_source' => [], //for backcompat, not calling anywhere
'ga_track_traffic_source' => [], //for backcompat, not calling anywhere
'is_ga_add_to_cart_bump' => '',
'is_ga_custom_bump' => '',
'custom_aud_opt_conf' => [],
'allow_theme_css' => array( 'wfacp_checkout' ),
'bwf_enable_notification' => true,
'bwf_notification_frequency' => array( 'weekly', 'monthly' ),
'bwf_notification_user_selector' => array(),
'bwf_external_user' => array(),
'bwf_notification_time' => [
'hours' => '10',
'minutes' => '00',
'ampm' => 'am'
],
) );
}
public function get_option( $key = 'all' ) {
if ( empty( $this->options ) ) {
$this->setup_options();
}
if ( 'all' === $key ) {
return $this->options;
}
return isset( $this->options[ $key ] ) ? $this->options[ $key ] : false;
}
public function setup_options() {
$db_options = get_option( 'bwf_gen_config', [] );
$db_options = ( ! empty( $db_options ) && is_array( $db_options ) ) ? array_map( function ( $val ) {
return is_scalar( $val ) ? html_entity_decode( $val ) : $val;
}, $db_options ) : array();
$this->options = wp_parse_args( $db_options, $this->default_general_settings() );
return $this->options;
}
public function maybe_add_js() {
wp_enqueue_script( 'bwf-general-settings', plugin_dir_url( WooFunnel_Loader::$ultimate_path ) . 'woofunnels/assets/js/bwf-general-settings.js', [], BWF_VERSION );
wp_enqueue_style( 'bwf-general-settings', plugin_dir_url( WooFunnel_Loader::$ultimate_path ) . 'woofunnels/assets/css/bwf-general-settings.css', array(), BWF_VERSION );
wp_localize_script( 'bwf-general-settings', 'bwfAdminGen', $this->get_localized_data() );
}
public function get_localized_data() {
$localized_data = [
'nonce_general_settings' => wp_create_nonce( 'bwf_general_settings_update' ),
'texts' => array(
'settings_success' => __( 'Changes saved', 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'permalink_help_text' => __( 'Leave empty to remove slug completely from url', 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
),
'globalOptionsFields' => array(
'options' => $this->filter_admin_options( $this->get_option() ),
'legends_texts' => array(
'fb' => __( 'Facebook Pixel', 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'ga' => __( 'Google Analytics', 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'gad' => __( 'Google Ads', 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'pint' => __( 'Pinterest', 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'permalinks' => __( 'Permalinks', 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'tiktok' => __( 'Tiktok', 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'snapchat' => __( 'Snapchat', 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
),
'fields' => $this->all_fields()
)
];
$localized_data['is_pinterest_enabled'] = ( true === apply_filters( 'bwf_enable_ecommerce_integration_pinterest', false ) ) ? 1 : 0;
$localized_data['is_tiktok_enabled'] = ( true === apply_filters( 'bwf_enable_ecommerce_integration_tiktok', false ) ) ? 1 : 0;
$localized_data['is_snapchat_enabled'] = ( true === apply_filters( 'bwf_enable_ecommerce_integration_snapchat', false ) ) ? 1 : 0;
$localized_data['is_gad_enabled'] = ( true === apply_filters( 'bwf_enable_ecommerce_integration_gad', false ) ) ? 1 : 0;
$localized_data['is_pixel_enabled'] = ( true === apply_filters( 'bwf_enable_ecommerce_integration_pixel', false ) ) ? 1 : 0;
$localized_data['is_ga_enabled'] = ( true === apply_filters( 'bwf_enable_ecommerce_integration_ga', false ) ) ? 1 : 0;
$localized_data['if_fb_checkout_enabled'] = ( true === apply_filters( 'bwf_enable_ecommerce_integration_fb_checkout', false ) ) ? 1 : 0;
$localized_data['if_fb_purchase_enabled'] = ( true === apply_filters( 'bwf_enable_ecommerce_integration_fb_purchase', false ) ) ? 1 : 0;
$localized_data['if_ga_checkout_enabled'] = ( true === apply_filters( 'bwf_enable_ecommerce_integration_ga_checkout', false ) ) ? 1 : 0;
$localized_data['if_ga_purchase_enabled'] = ( true === apply_filters( 'bwf_enable_ecommerce_integration_ga_purchase', false ) ) ? 1 : 0;
$localized_data['if_gad_checkout_enabled'] = ( true === apply_filters( 'bwf_enable_ecommerce_integration_gad_checkout', false ) ) ? 1 : 0;
$localized_data['if_gad_purchase_enabled'] = ( true === apply_filters( 'bwf_enable_ecommerce_integration_gad_purchase', false ) ) ? 1 : 0;
$localized_data['if_pint_checkout_enabled'] = ( true === apply_filters( 'bwf_enable_ecommerce_integration_pint_checkout', false ) ) ? 1 : 0;
$localized_data['if_pint_purchase_enabled'] = ( true === apply_filters( 'bwf_enable_ecommerce_integration_pint_purchase', false ) ) ? 1 : 0;
$localized_data['if_tiktok_checkout_enabled'] = ( true === apply_filters( 'bwf_enable_ecommerce_integration_tiktok_checkout', false ) ) ? 1 : 0;
$localized_data['if_tiktok_purchase_enabled'] = ( true === apply_filters( 'bwf_enable_ecommerce_integration_tiktok_purchase', false ) ) ? 1 : 0;
$localized_data['if_snapchat_checkout_enabled'] = ( true === apply_filters( 'bwf_enable_ecommerce_integration_snapchat_checkout', false ) ) ? 1 : 0;
$localized_data['if_snapchat_purchase_enabled'] = ( true === apply_filters( 'bwf_enable_ecommerce_integration_snapchat_purchase', false ) ) ? 1 : 0;
$localized_data['if_landing_enabled'] = ( true === apply_filters( 'bwf_enable_ecommerce_integration_landing', false ) ) ? 1 : 0;
$localized_data['if_optin_enabled'] = ( true === apply_filters( 'bwf_enable_ecommerce_integration_optin', false ) ) ? 1 : 0;
$localized_data['if_ga4_enabled'] = ( true === apply_filters( 'bwf_enable_ga4', false ) ) ? 1 : 0;
$checkout_page_slug = 'checkout';
$checkout_id = function_exists( 'wc_get_page_id' ) ? wc_get_page_id( 'checkout' ) : 0;
if ( $checkout_id > - 1 ) {
$checkout_page = get_post( $checkout_id );
if ( $checkout_page instanceof WP_Post ) {
$checkout_page_slug = $checkout_page->post_name;
}
}
$localized_data['checkout_page_slug'] = $checkout_page_slug;
$localized_data['permalink_structure'] = get_option( 'permalink_structure' );
$localized_data['errors'] = array(
'checkout_slug' => sprintf( __( 'Error: The permalink "%s" is reserved by Native WooCommerce Checkout Page. Try another permalink.', 'woofunnels' ), $checkout_page_slug ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch, WordPress.WP.I18n.MissingTranslatorsComment
'empty_base' => sprintf( __( 'Error: The current Permalinks settings does not allow blank values. Switch Permalink settings to \'Post name\'. <a href="%s">Click Here To Change</a>', 'woofunnels' ), admin_url( 'options-permalink.php' ) ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch, WordPress.WP.I18n.MissingTranslatorsComment
);
return $localized_data;
}
public function get_localized_bwf_data() {
$localized_data = [];
$checkout_page_slug = 'checkout';
$checkout_id = function_exists( 'wc_get_page_id' ) ? wc_get_page_id( 'checkout' ) : 0;
if ( $checkout_id > - 1 ) {
$checkout_page = get_post( $checkout_id );
if ( $checkout_page instanceof WP_Post ) {
$checkout_page_slug = $checkout_page->post_name;
}
}
$localized_data['checkout_page_slug'] = $checkout_page_slug;
$localized_data['permalink_structure'] = get_option( 'permalink_structure' );
$localized_data['errors'] = array(
'checkout_slug' => sprintf( __( 'Error: The permalink "%s" is reserved by Native WooCommerce Checkout Page. Try another permalink.', 'woofunnels' ), $checkout_page_slug ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch, WordPress.WP.I18n.MissingTranslatorsComment
'empty_base' => sprintf( __( 'Error: The current Permalinks settings does not allow blank values. Switch Permalink settings to \'Post name\'. <a href="%s">Click Here To Change</a>', 'woofunnels' ), admin_url( 'options-permalink.php' ) ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch, WordPress.WP.I18n.MissingTranslatorsComment
);
$localized_data['pro_status'] = [];
$License = WooFunnels_licenses::get_instance();
if ( is_object( $License ) && is_array( $License->plugins_list ) && count( $License->plugins_list ) ) {
foreach ( $License->plugins_list as $license ) {
if ( in_array( $license['product_file_path'], array( '7b31c172ac2ca8d6f19d16c4bcd56d31026b1bd8', '913d39864d876b7c6a17126d895d15322e4fd2e8' ), true ) ) {
continue;
}
$license_data = [];
if ( isset( $license['_data'] ) && isset( $license['_data']['data_extra'] ) ) {
$license_data = $license['_data']['data_extra'];
if ( isset( $license_data['api_key'] ) ) {
$license_data['api_key'] = 'xxxxxxxxxxxxxxxxxxxxxxxxxx' . substr( $license_data['api_key'], - 6 );
$license_data['licence'] = 'xxxxxxxxxxxxxxxxxxxxxxxxxx' . substr( $license_data['api_key'], - 6 );
}
}
if ( $license['plugin'] === 'FunnelKit Funnel Builder Pro' || $license['plugin'] === 'FunnelKit Funnel Builder Basic' ) {
$data = array(
'id' => $license['product_file_path'],
'label' => $license['plugin'],
'type' => 'license',
'key' => $license['product_file_path'],
'license' => ! empty( $license_data ) ? $license_data : false,
'is_manually_deactivated' => ( isset( $license['_data']['manually_deactivated'] ) && true === bwf_string_to_bool( $license['_data']['manually_deactivated'] ) ) ? 1 : 0,
'activated' => ( isset( $license['_data']['activated'] ) && true === bwf_string_to_bool( $license['_data']['activated'] ) ) ? 1 : 0,
'expired' => ( isset( $license['_data']['expired'] ) && true === bwf_string_to_bool( $license['_data']['expired'] ) ) ? 1 : 0
);
$localized_data['pro_status'] = $data;
}
}
}
return $localized_data;
}
public function update_general_settings() {
check_admin_referer( 'bwf_general_settings_update', '_nonce' );
$options = isset( $_POST['data'] ) ? bwf_clean( $_POST['data'] ) : 0;
$resp = $this->update_global_settings_fields( $options );
wp_send_json( $resp );
}
public function update_global_settings_fields( $options ) {
$options = ( is_array( $options ) && wp_unslash( bwf_clean( $options ) ) ) ? bwf_clean( $options ) : 0;
$resp = [
'status' => false,
'msg' => __( 'Settings Updated', 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'data' => '',
];
$db_options = get_option( 'bwf_gen_config', [] );
if(!is_array($db_options)) {
$db_options = [];
}
$options = array_merge( $this->default_general_settings(), $db_options, $options );
if ( $options !== 0 ) {
update_option( 'bwf_gen_config', $options, true );
update_option( 'bwf_needs_rewrite', 'yes', true );
if ( class_exists( 'BWF_JSON_Cache' ) && method_exists( 'BWF_JSON_Cache', 'run_json_endpoints_cache_handling' ) ) {
BWF_JSON_Cache::run_json_endpoints_cache_handling();
}
$resp['status'] = true;
}
do_action( 'bwf_general_settings_updated', $options );
return $resp;
}
public function get_settings_link() {
return apply_filters( 'bwf_general_settings_link', 'javascript:void(0)' );
}
public function hide_from_menu() {
global $woofunnels_menu_slug;
global $parent_file, $plugin_page, $submenu_file; //phpcs:ignore
if ( filter_input( INPUT_GET, 'tab', FILTER_UNSAFE_RAW ) === 'bwf_settings' ) :
$parent_file = $woofunnels_menu_slug;//phpcs:ignore
$submenu_file = 'admin.php?page=woofunnels_settings'; //phpcs:ignore
endif;
}
/**
* Filter options before passing it to the javascript
*
* @param $config array configuration array
*
* @return array
*/
public function filter_admin_options( $config ) {
foreach ( $config as $key => &$data ) {
/**
* Check if data is 'false' (string) then make it blank so that checkboxes works accordingly
*/
if ( 'false' === $data ) {
$config[ $key ] = '';
}
}
return $config;
}
public function maybe_change_title( $title ) {
if ( 'bwf_settings' === filter_input( INPUT_GET, 'tab', FILTER_UNSAFE_RAW ) || 'bwf_settings' === filter_input( INPUT_GET, 'section', FILTER_UNSAFE_RAW ) ) {
$admin_title = get_bloginfo( 'name' );
$title = sprintf( __( '%1$s &lsaquo; %2$s &#8212; WordPress', 'woofunnels' ), 'FunnelKit', $admin_title ); // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch, WordPress.WP.I18n.MissingTranslatorsComment
}
return $title;
}
public function all_fields() {
$static_config = include WooFunnel_Loader::$ultimate_path . '/helpers/settings.php';
$legacy = apply_filters( 'bwf_general_settings_fields', [] );
$legacy_altered = [];
if ( count( $legacy ) > 0 ) {
$i = 0;
foreach ( $legacy as $key => $new ) {
$legacy_altered[ $i ] = array( 'key' => $key );
$legacy_altered[ $i ] = array_merge( $legacy_altered[ $i ], $new );
$i ++;
}
}
$static_config['permalinks']['fields'] = $legacy_altered;
foreach ( $static_config as &$arr ) {
$values = [];
foreach ( $arr['fields'] as &$field ) {
$values[ $field['key'] ] = $this->get_option( $field['key'] );
}
$arr['values'] = $values;
}
return $static_config;
}
}
}
BWF_Admin_General_Settings::get_instance();

View File

@@ -0,0 +1,90 @@
<?php
if ( ! class_exists( 'BWF_Data_Tags' ) ) {
#[AllowDynamicProperties]
class BWF_Data_Tags {
public $shortcodes = array(
'get_cookie',
'get_url_parameter',
);
// The pattern to match restricted cookies 'wordpress_*', '_fk_contact_uid', 'wp-settings-*', 'PHPSESSID', 'wordpress_logged_in_*', 'wp_woocommerce_session_*'
public $restricted_cookie_pattern = "/^(wordpress_.*|_fk_contact_uid|wp-settings-.*|PHPSESSID|wordpress_logged_in_.*|wp_woocommerce_session_.*)$/";
public function __construct() {
foreach ( $this->shortcodes as $code ) {
add_shortcode( 'wf_' . $code, array( $this, $code ) );
}
}
private static $ins = null;
/**
* @return BWF_Optin_Tags|null
*/
public static function get_instance() {
if ( null === self::$ins ) {
self::$ins = new self;
}
return self::$ins;
}
public function get_first_name( $attr ) {
if ( isset( $this->get_optin()->optin_first_name ) && ! empty( $this->get_optin()->optin_first_name ) ) {
return $this->get_optin()->optin_first_name;
}
return $this->get_default( $attr, 'first_name' );
}
public function get_cookie( $attr ) {
$attr = shortcode_atts( array(
'key' => '',
), $attr );
if ( empty( $attr['key'] ) ) {
return '';
}
// Check if the cookie key is restricted
if (preg_match($this->restricted_cookie_pattern, $attr['key'])) {
return '';
}
$data = isset( $_COOKIE[ $attr['key'] ] ) ? bwf_clean( $_COOKIE[ $attr['key'] ] ) : '';
/*** read cookie when drop cookie on page **/
if ( empty( $data ) ) {
$key = str_replace( 'bwf_', '', $attr['key'] );
$data = isset( $_GET[ $key ] ) ? bwf_clean( $_GET[ $key ] ) : '';
}
return $data;
}
public function get_url_parameter( $attr ) {
$attr = shortcode_atts( array(
'key' => '',
), $attr );
if ( empty( $attr['key'] ) ) {
return '';
}
return isset( $_GET[ $attr['key'] ] ) ? bwf_clean( $_GET[ $attr['key'] ] ) : '';
}
}
BWF_Data_Tags::get_instance();
}

View File

@@ -0,0 +1,60 @@
<?php
if ( ! class_exists( 'BWF_Facebook_Sdk_Factory' ) ) {
#[AllowDynamicProperties]
class BWF_Facebook_Sdk_Factory {
private static $pixel_id = null;
private static $access_token = null;
private static $version = null;
private static $setup_run = false;
private static $test_event_code = false;
private static $partner_code = false;
/**
* @param $pixel_id
* @param $access_token
* @param string $version
*
* @return boolean
*/
public static function setup( $pixel_id, $access_token, $version = 'v11.0' ) {
if ( empty( $pixel_id ) || empty( $access_token ) ) {
return false;
}
self::$pixel_id = $pixel_id;
self::$access_token = $access_token;
self::$version = $version;
self::$setup_run = true;
return true;
}
public static function set_test( $test_code ) {
self::$test_event_code = $test_code;
}
public static function set_partner( $partner_code ) {
self::$partner_code = $partner_code;
}
public static function create() {
if ( false == self::$setup_run ) {
return null;
}
$instance = new BWF_Facebook_Sdk( self::$pixel_id, self::$access_token, self::$version );
if ( ! empty( self::$test_event_code ) ) {
$instance->set_test_event_code( self::$test_event_code );
}
if ( ! empty( self::$partner_code ) ) {
$instance->set_partner_agent( self::$partner_code );
}
return $instance;
}
}
}

View File

@@ -0,0 +1,353 @@
<?php
if ( ! class_exists( 'BWF_Facebook_Sdk' ) ) {
#[AllowDynamicProperties]
class BWF_Facebook_Sdk {
private static $instance = null;
protected $container = array();
protected $event_data = array();
private $api_url = 'https://graph.facebook.com';
private $version = '';
private $pixel_id = '';
private $event_name = '';
private $time = '';
private $test_event_code = '';
private $partner_agent = '';
private $body = [];
private $response_body = null;
private $access_token = '';
public function __construct( $pixel_id, $access_token, $version = 'v11.0' ) {
if ( ! empty( $pixel_id ) ) {
$this->pixel_id = $pixel_id;
}
if ( ! empty( $access_token ) ) {
$this->access_token = $access_token;
}
if ( ! empty( $version ) ) {
$this->version = $version;
}
$this->time = time();
}
public static function create( $pixel_id, $access_token, $version = 'v11.0' ) {
if ( is_null( self::$instance ) ) {
self::$instance = new self( $pixel_id, $access_token, $version );
}
return self::$instance;
}
public function set_event_data( $event_name, $event_data ) {
$this->event_name = $event_name;
$this->event_data = $event_data;
}
public function set_event_source_url( $url = '' ) {
$this->source_url = $url;
}
public function execute() {
$out_response = [ 'status' => false, 'errors' => [] ];
if ( empty( $this->event_name ) && empty( $this->event_data ) ) {
$out_response['errors'][] = 'Event Name is empty';
}
if ( count( $out_response['errors'] ) > 0 ) {
return $out_response;
}
$event_id = $this->get_event_id();
$input = [ 'event_name' => $this->event_name, 'event_time' => $this->get_time(), 'action_source' => 'website', 'event_id' => $event_id ];
if ( isset( $this->source_url ) ) {
$input['event_source_url'] = $this->source_url;
}
$user_data = $this->get_user_data();
if ( ! empty( $user_data ) ) {
$input['user_data'] = $user_data;
}
$input['custom_data'] = $this->event_data;
$body = [ 'data' => [ $input ] ];
if ( ! empty( $this->test_event_code ) ) {
$body['test_event_code'] = $this->test_event_code;
}
if ( ! empty( $this->partner_agent ) ) {
$body['partner_agent'] = $this->partner_agent;
}
$headers = [
'Authorization' => 'Bearer ' . $this->access_token,
];
$this->body = $body;
$post = wp_remote_post( $this->get_api_url(), [
'timeout' => 2,
'sslverify' => false,
'body' => $this->body,
'headers' => $headers
] );
$this->response_body = wp_remote_retrieve_body( $post );
return array( 'request' => $this->get_request_body(), 'response' => $this->response_body );
}
public function get_event_id() {
return isset( $this->container['event_id'] ) ? $this->container['event_id'] : '';
}
public function get_time() {
return time();
}
public function get_user_data() {
$normalized_payload = array();
$normalized_payload['em'] = self::hash( $this->getEmail() );
$normalized_payload['ph'] = self::hash( $this->getPhone() );
$normalized_payload['ge'] = self::hash( $this->getGender() );
$normalized_payload['db'] = self::hash( $this->getDateOfBirth() );
$normalized_payload['ln'] = self::hash( $this->getLastName() );
$normalized_payload['fn'] = self::hash( $this->getFirstName() );
$normalized_payload['ct'] = self::hash( $this->getCity() );
$normalized_payload['st'] = self::hash( $this->getState() );
$normalized_payload['zp'] = self::hash( $this->getZipCode() );
$normalized_payload['country'] = self::hash( $this->getCountryCode() );
$normalized_payload['dobd'] = self::hash( $this->getDobd() );
$normalized_payload['dobm'] = self::hash( $this->getDobm() );
$normalized_payload['doby'] = self::hash( $this->getDoby() );
$normalized_payload['client_ip_address'] = $this->getIpAddress();
$normalized_payload['client_user_agent'] = $this->getHttpUserAgent();
$normalized_payload['fbc'] = $this->getFbc();
$normalized_payload['fbp'] = $this->getFbp();
$normalized_payload['external_id'] = $this->getExternalId();
$normalized_payload = array_filter( $normalized_payload );
return $normalized_payload;
}
/**
* @param string $data hash input data using SHA256 algorithm.
*
* @return string
*/
public static function hash( $data ) {
if ( $data == null || self::isHashed( $data ) ) {
return $data;
}
return hash( 'sha256', $data, false );
}
/**
* @param string $pii PII data to check if its hashed.
*
* @return bool
*/
public static function isHashed( $pii ) {
// it could be sha256 or md5
return preg_match( '/^[A-Fa-f0-9]{64}$/', $pii ) || preg_match( '/^[a-f0-9]{32}$/', $pii );
}
/**
* Gets an email address, in lowercase.
* @return string
*/
public function getEmail() {
return $this->container['email'];
}
/**
* Gets a phone number
* @return string
*/
public function getPhone() {
return $this->container['phone'];
}
/**
* Gets gender.
* @return string
*/
public function getGender() {
return $this->container['gender'];
}
/**
* Gets Date Of Birth.
* @return string
*/
public function getDateOfBirth() {
return $this->container['date_of_birth'];
}
/**
* Gets Last Name.
* @return string
*/
public function getLastName() {
return $this->container['last_name'];
}
/**
* Gets First Name.
* @return string
*/
public function getFirstName() {
return $this->container['first_name'];
}
/**
* Gets city.
* @return string
*/
public function getCity() {
return $this->container['city'];
}
/**
* Gets state.
* @return string
*/
public function getState() {
return $this->container['state'];
}
/**
* Gets zip code
* @return string
*/
public function getZipCode() {
return $this->container['zip_code'];
}
/**
* Gets country code.
* @return string
*/
public function getCountryCode() {
return $this->container['country_code'];
}
/**
* Gets the date of birth day.
* @return string
*/
public function getDobd() {
return $this->container['dobd'];
}
/**
* Gets the date of birth month.
* @return string
*/
public function getDobm() {
return $this->container['dobm'];
}
/**
* Gets the date of birth year.
* @return string
*/
public function getDoby() {
return $this->container['doby'];
}
/**
* Extracts the IP Address from the PHP Request Context.
* @return string
*/
public function getIpAddress() {
return $this->container['client_ip_address'];
}
/**
* Extracts the HTTP User Agent from the PHP Request Context.
* @return string
*/
public function getHttpUserAgent() {
return $this->container['client_user_agent'];
}
/**
* Extracts the FBC cookie from the PHP Request Context.
* @return string
*/
public function getFbc() {
return $this->container['fbc'];
}
/**
* Extracts the FBP cookie from the PHP Request Context.
* @return string
*/
public function getFbp() {
return $this->container['fbp'];
}
public function getExternalId() {
return $this->container['external_id'];
}
public function get_api_url() {
return $this->api_url . '/' . $this->version . '/' . $this->pixel_id . '/events';
}
public function get_request_body() {
return $this->body;
}
public function set_user_data( $data = [] ) {
$this->container['email'] = isset( $data['email'] ) ? $data['email'] : ( isset( $data['em'] ) ? $data['em'] : null );
$this->container['phone'] = isset( $data['phone'] ) ? $data['phone'] : ( isset( $data['ph'] ) ? $data['ph'] : null );
$this->container['gender'] = isset( $data['gender'] ) ? $data['gender'] : null;
$this->container['date_of_birth'] = isset( $data['date_of_birth'] ) ? $data['date_of_birth'] : null;
$this->container['last_name'] = isset( $data['last_name'] ) ? $data['last_name'] : ( isset( $data['ln'] ) ? $data['ln'] : null );
$this->container['first_name'] = isset( $data['first_name'] ) ? $data['first_name'] : ( isset( $data['fn'] ) ? $data['fn'] : null );
$this->container['city'] = isset( $data['city'] ) ? $data['city'] : ( isset( $data['ct'] ) ? $data['ct'] : null );
$this->container['state'] = isset( $data['state'] ) ? $data['state'] : ( isset( $data['st'] ) ? $data['st'] : null );
$this->container['dobd'] = isset( $data['dobd'] ) ? $data['dobd'] : null;
$this->container['dobm'] = isset( $data['dobm'] ) ? $data['dobm'] : null;
$this->container['doby'] = isset( $data['doby'] ) ? $data['doby'] : null;
$this->container['country_code'] = isset( $data['country_code'] ) ? $data['country_code'] : ( isset( $data['country'] ) ? $data['country'] : null );
$this->container['zip_code'] = isset( $data['zip_code'] ) ? $data['zip_code'] : null;
$this->container['client_user_agent'] = isset( $data['client_user_agent'] ) ? $data['client_user_agent'] : null;
$this->container['client_ip_address'] = isset( $data['client_ip_address'] ) ? $data['client_ip_address'] : null;
$this->container['fbp'] = isset( $data['fbp'] ) ? $data['fbp'] : null;
$this->container['fbc'] = isset( $data['fbc'] ) ? $data['fbc'] : null;
$this->container['fbp'] = isset( $data['_fbp'] ) ? $data['_fbp'] : $this->container['fbp'];
$this->container['fbc'] = isset( $data['_fbc'] ) ? $data['_fbc'] : $this->container['fbc'];
$this->container['external_id'] = isset( $data['external_id'] ) ? $data['external_id'] : null;
}
public function get_response_body() {
return $this->response_body;
}
public function set_event_id( $event_id ) {
return $this->container['event_id'] = $event_id;
}
public function set_test_event_code( $event_code ) {
$this->test_event_code = $event_code;
}
public function set_partner_agent( $partner_agent ) {
$this->partner_agent = $partner_agent;
}
/**
* Extracts the URI from the PHP Request Context.
* @return string
*/
public function getRequestUri() {
return $this->container['reuqesturi'];
}
}
}

View File

@@ -0,0 +1,327 @@
<?php
if ( ! class_exists( 'BWF_JSON_Cache' ) ) {
class BWF_JSON_Cache {
public static function run_json_endpoints_cache_handling() {
/** Litespeed cache */
self::check_litespeed();
/** WordPress REST API Authentication */
self::check_wp_rest_api_authentication();
/** WP rocket cache */
self::check_wp_rocket();
/** WP fastest cache */
self::check_wp_fastest_cache();
}
/**
* For litespeed cache
* https://wordpress.org/plugins/litespeed-cache/
*
* @return void
*/
public static function check_litespeed() {
if ( ! defined( 'LSCWP_V' ) ) {
return;
}
/** Exclude json endpoints */
$exc_endpoints = get_option( 'litespeed.conf.cache-exc', '' );
$exc_endpoints = self::make_array( $exc_endpoints );
if ( defined( 'BWFAN_API_NAMESPACE' ) ) {
$exc_endpoints[] = "^/wp-json/" . BWFAN_API_NAMESPACE . "/";
}
$exc_endpoints[] = "^/wp-json/woofunnels/";
$exc_endpoints[] = "^/wp-json/funnelkit-automations/";
$exc_endpoints = self::maybe_clear_fb_endpoints( $exc_endpoints );
$exc_endpoints = self::unique( $exc_endpoints );
update_option( 'litespeed.conf.cache-exc', wp_json_encode( $exc_endpoints ) );
/** Exclude role */
$exc_role = get_option( 'litespeed.conf.cache-exc_roles', '' );
$exc_role = self::make_array( $exc_role );
$exc_role[] = "administrator";
$exc_role = self::unique( $exc_role );
update_option( 'litespeed.conf.cache-exc_roles', wp_json_encode( $exc_role ) );
/** Exclude query string */
$exc_qs = get_option( 'litespeed.conf.cache-exc_qs', '' );
$exc_qs = self::make_array( $exc_qs );
$exc_qs[] = "bwfan-track-id";
$exc_qs[] = "bwfan-track-action";
$exc_qs[] = "bwfan-link-trigger";
$exc_qs = self::unique( $exc_qs );
update_option( 'litespeed.conf.cache-exc_qs', wp_json_encode( $exc_qs ) );
}
/**
* For WordPress rest api authentication
* https://wordpress.org/plugins/wp-rest-api-authentication/
*
* @return void
*/
public static function check_wp_rest_api_authentication() {
if ( ! defined( 'MINIORANGE_API_AUTHENTICATION_VERSION' ) ) {
return;
}
/** json endpoints */
$endpoints = get_option( 'mo_api_authentication_protectedrestapi_route_whitelist', '' );
if ( empty( $endpoints ) ) {
return;
}
$endpoints = maybe_unserialize( $endpoints );
$exc_endpoints = [
"/woofunnels/v1",
"/autonami/v1",
"/autonami/v2",
"/funnelkit-automations",
];
$exc_endpoints = self::maybe_clear_fb_endpoints( $exc_endpoints, 'api-auth' );
$endpoints = array_filter( $endpoints, function ( $endpoint ) use ( $exc_endpoints ) {
foreach ( $exc_endpoints as $url ) {
if ( false !== strpos( $endpoint, $url ) ) {
return false;
}
}
return true;
} );
$endpoints = self::unique( $endpoints );
update_option( 'mo_api_authentication_protectedrestapi_route_whitelist', $endpoints );
}
/**
* For WP rocket cache
* https://wp-rocket.me/
*
* @return void
*/
public static function check_wp_rocket() {
if ( ! defined( 'WP_ROCKET_VERSION' ) || ! function_exists( 'get_rocket_option' ) || ! function_exists( 'update_rocket_option' ) || ! function_exists( 'rocket_generate_config_file' ) ) {
return;
}
$exc_endpoints = (array) get_rocket_option( 'cache_reject_uri', [] );
$exc_endpoints = self::make_array( $exc_endpoints );
if ( defined( 'BWFAN_API_NAMESPACE' ) ) {
$exc_endpoints[] = "^/wp-json/" . BWFAN_API_NAMESPACE . "/";
}
$exc_endpoints[] = "/wp-json/woofunnels/*";
$exc_endpoints[] = "/wp-json/funnelkit-automations/*";
$exc_endpoints = self::maybe_clear_fb_endpoints( $exc_endpoints, 'wp_rocket' );
$exc_endpoints = self::unique( $exc_endpoints );
/** Update the "Never cache the following pages" option */
update_rocket_option( 'cache_reject_uri', $exc_endpoints );
/** Update config file */
rocket_generate_config_file();
}
/**
* For WP fastest cache
* https://wordpress.org/plugins/wp-fastest-cache/
*
* @return void
*/
public static function check_wp_fastest_cache() {
if ( ! class_exists( 'WpFastestCache' ) ) {
return;
}
$existing_data = get_option( 'WpFastestCacheExclude' );
$existing_rules = self::make_array( $existing_data );
$new_rules_array = [
[
"prefix" => "contain",
"content" => "bwfan-action",
"type" => "page"
],
[
"prefix" => "contain",
"content" => "bwfan-track-id",
"type" => "page"
],
[
"prefix" => "contain",
"content" => "bwfan-link-trigger",
"type" => "page"
],
[
"prefix" => "contain",
"content" => "bwfan-track-action",
"type" => "page"
],
[
"prefix" => "contain",
"content" => "wp-json/woofunnels/",
"type" => "page"
],
[
"prefix" => "contain",
"content" => "wp-json/autonami/",
"type" => "page"
],
[
"prefix" => "contain",
"content" => "wp-json/funnelkit-automations",
"type" => "page"
],
[
"prefix" => "contain",
"content" => "wp-json/funnelkit-app",
"type" => "page"
],
[
"prefix" => "contain",
"content" => "wp-json/woofunnel_customer/",
"type" => "page"
],
[
"prefix" => "contain",
"content" => "wp-json/autonami-app",
"type" => "page"
],
[
"prefix" => "contain",
"content" => "wp-json/autonami-webhook",
"type" => "page"
]
];
$new_rules = array_filter( $new_rules_array, function ( $new_rule ) use ( $existing_rules ) {
return ! in_array( $new_rule, $existing_rules, true );
} );
if ( empty( $new_rules ) ) {
return;
}
$updated_array = array_merge( $existing_rules, $new_rules );
$updated_json = wp_json_encode( $updated_array );
update_option( 'WpFastestCacheExclude', $updated_json );
}
/**
* Convert string/ json to array
*
* @param $value
*
* @return array
*/
public static function make_array( $value ) {
$value = self::is_json( $value ) ? json_decode( $value, true ) : $value;
return empty( $value ) || ! is_array( $value ) ? [] : $value;
}
/**
* Check if string is a json
*
* @param $string
*
* @return bool
*/
public static function is_json( $string ) {
if ( ! is_string( $string ) ) {
return false;
}
json_decode( $string );
return ( json_last_error() === JSON_ERROR_NONE );
}
/**
* Array unique and sort
*
* @param $value
*
* @return array|mixed
*/
public static function unique( $value ) {
if ( ! is_array( $value ) ) {
return $value;
}
$value = array_unique( $value );
sort( $value );
return $value;
}
/**
* @param $endpoints
* @param $plugin_slug
*
* @return array|mixed
*/
public static function maybe_clear_fb_endpoints( $endpoints, $plugin_slug = 'litespeed' ) {
if ( ! class_exists( 'WFFN_Core' ) ) {
return $endpoints;
}
$endpoints = ( ! is_array( $endpoints ) ) ? [] : $endpoints;
$db_options = get_option( 'bwf_gen_config', [] );
$cl_slug = is_array( $db_options ) && isset( $db_options['checkout_page_base'] ) ? $db_options['checkout_page_base'] : '';
$of_slug = is_array( $db_options ) && isset( $db_options['wfocu_page_base'] ) ? $db_options['wfocu_page_base'] : '';
if ( 'api-auth' === $plugin_slug ) {
$endpoints[] = "/funnelkit-app/";
if ( ! empty( $cl_slug ) ) {
$endpoints[] = '/' . $cl_slug . '/';
}
if ( ! empty( $of_slug ) ) {
$endpoints[] = '/' . $of_slug . '/';
}
return $endpoints;
}
if ( 'litespeed' === $plugin_slug ) {
$endpoints[] = "^/wp-json/funnelkit-app/";
if ( ! empty( $cl_slug ) ) {
$endpoints[] = '^/' . $cl_slug . '/';
}
if ( ! empty( $of_slug ) ) {
$endpoints[] = '^/' . $of_slug . '/';
}
return $endpoints;
}
if ( 'wp_rocket' === $plugin_slug ) {
$endpoints[] = "^/wp-json/funnelkit-app/(.*)";
if ( ! empty( $cl_slug ) ) {
$endpoints[] = '^/' . $cl_slug . '/(.*)';
}
if ( ! empty( $of_slug ) ) {
$endpoints[] = '^/' . $of_slug . '/(.*)';
}
return $endpoints;
}
return $endpoints;
}
}
}

View File

@@ -0,0 +1,112 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
if ( ! class_exists( 'BWF_Logger' ) ) {
#[AllowDynamicProperties]
class BWF_Logger {
private static $ins = null;
public $wc_logger = null;
public function __construct() {
}
public static function get_instance() {
if ( self::$ins === null ) {
self::$ins = new self;
}
return self::$ins;
}
public function log( $message, $file_name = '', $folder_prefix = 'fk-temp', $force = false ) {
if ( ! $force && false === apply_filters( 'bwf_logs_allowed', false, $file_name ) ) {
return;
}
$plugin_short_name = $folder_prefix . '-logs';
$transient_key = $file_name . '-' . gmdate( 'Y-m-d' );
$transient_key = $transient_key . '-' . hash_hmac( 'md5', $transient_key, defined( 'AUTH_SALT' ) && AUTH_SALT ? AUTH_SALT : 'funnelkit-logs' );
$transient_value = gmdate( 'c', time() ) . ' - ' . $message . "\n";
$file_api = $this->is_writable( $plugin_short_name, $transient_key );
if ( false === $file_api ) {
return;
}
$old_content = $file_api->get_contents( $transient_key );
if ( ! empty( $old_content ) ) {
$old_content = maybe_unserialize( $old_content );
$transient_value = $old_content . $transient_value;
}
$transient_value = maybe_serialize( $transient_value );
$file_api->put_contents( $transient_key, $transient_value );
}
public function is_writable( $plugin_short_name, $transient_key ) {
if ( ! class_exists( 'WooFunnels_File_Api' ) ) {
return false;
}
$file_api = new WooFunnels_File_Api( $plugin_short_name );
$file_api->touch( $transient_key );
if ( $file_api->is_writable( $transient_key ) && $file_api->is_readable( $transient_key ) ) {
return $file_api;
}
return false;
}
public function get_log_options() {
$wp_dir = wp_upload_dir();
$woofunnels_uploads_directory = $wp_dir['basedir'];
$woofunnels_uploads_directory = $woofunnels_uploads_directory . '/funnelkit';
$final_logs_result = array();
$plugin_logs_directories = glob( $wp_dir['basedir'] . '/funnelkit/*-logs' );
foreach ( $plugin_logs_directories as $directory ) {
$result = array();
$directory_data = pathinfo( $directory );
if ( ! isset( $directory_data['basename'] ) ) {
continue;
}
$plugin_uploads_directory = $woofunnels_uploads_directory . '/' . $directory_data['basename'];
$files = @scandir( $plugin_uploads_directory ); // @codingStandardsIgnoreLine.
if ( ! is_array( $files ) || 0 === count( $files ) ) {
continue;
}
$file_timestamps = array();
foreach ( $files as $value ) {
if ( ! in_array( $value, array( '.', '..' ), true ) ) {
$file_path = $plugin_uploads_directory . '/' . $value;
if ( ! is_dir( $file_path ) ) {
$file_timestamps[$value] = filemtime( $file_path );
}
}
}
// Sort files by modified time (newest first)
arsort( $file_timestamps );
foreach ( $file_timestamps as $file => $timestamp ) {
$result[$file] = $file;
}
if ( is_array( $result ) && count( $result ) > 0 ) {
$final_logs_result[ $directory_data['basename'] ] = $result;
}
}
return $final_logs_result;
}
}
}

View File

@@ -0,0 +1,102 @@
<?php
/*if ( ! class_exists( 'WFCO_Model' ) ) {
require_once __DIR__ . '/class-wfco-model.php';
}*/
if ( ! class_exists( 'WFCO_Model_Report_views' ) ) {
#[AllowDynamicProperties]
class WFCO_Model_Report_views extends WFCO_Model {
static $primary_key = 'ID';
public static function count_rows( $dependency = null ) {
global $wpdb;
$table_name = self::_table();
$sql = 'SELECT COUNT(*) FROM ' . $table_name;
if ( 'all' !== filter_input( INPUT_GET, 'status', FILTER_UNSAFE_RAW ) ) {
$status = filter_input( INPUT_GET, 'status', FILTER_UNSAFE_RAW );
$status = ( 'active' === $status ) ? 1 : 2;
$sql = $wpdb->prepare( "SELECT COUNT(*) FROM $table_name WHERE status = %d", $status ); //phpcs:ignore WordPress.DB.PreparedSQL
}
return $wpdb->get_var( $sql ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
}
private static function _table() {
global $wpdb;
$table_name = strtolower( get_called_class() );
$table_name = str_replace( 'wfco_model_', 'wfco_', $table_name );
return $wpdb->prefix . $table_name;
}
/**
* @param string $date Date(Y-m-d)
* @param string $object_id post_id or unique_id
* @param int $type 1=abandoned,2=upstroke,3=aero,4=bump
*/
public static function update_data( $date = '', $object_id = '', $type = 1 ) {
global $wpdb;
$where = [];
$insert = [];
if ( $date !== '' ) {
$where['date'] = "`date`='$date'";
$insert['date'] = $date;
} else {
$date = date( 'Y-m-d' );
$where['date'] = "`date`='$date'";
$insert['date'] = $date;
}
if ( $object_id !== '' ) {
$where['object_id'] = "`object_id`='$object_id'";
$insert['object_id'] = $object_id;
}
$where['type'] = "`type`='$type'";
$insert['type'] = $type;
$where_string = implode( ' and ', $where );
$table = self::_table();
$get_sql = "SELECT * FROM $table WHERE {$where_string};";
$result = $wpdb->get_results( $get_sql, ARRAY_A ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
if ( ! empty( $result ) ) {
$primary_id = $result[0]['id'];
$sql = "UPDATE $table set no_of_sessions=no_of_sessions+1 where id ='{$primary_id}';";
$wpdb->query( $sql ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
} else {
$wpdb->insert( $table, $insert ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
}
}
public static function get_data( $date = '', $object_id = '', $type = 1, $interval = false ) {
$where = [];
if ( $date !== '' ) {
if ( true === $interval ) {
$where['date'] = $date;
} else {
$where['date'] = "`date`='$date'";
}
} else {
$date = date( 'Y-m-d' );
$where['date'] = "`date`='$date'";
}
if ( $object_id !== '' ) {
$where['object_id'] = "`object_id`='$object_id'";
}
$where['type'] = "`type`='$type'";
$where_string = implode( ' and ', $where );
global $wpdb;
$table = self::_table();
$sql = "select * from `{$table}` WHERE {$where_string};";
$data = $wpdb->get_results( $sql, ARRAY_A ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
return $data;
}
}
}

View File

@@ -0,0 +1,118 @@
<?php
if ( ! class_exists( 'WFCO_Model' ) ) {
#[AllowDynamicProperties]
abstract class WFCO_Model {
static $primary_key = 'id';
static $count = 20;
static function get( $value ) {
global $wpdb;
return $wpdb->get_row( self::_fetch_sql( $value ), ARRAY_A ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
}
private static function _fetch_sql( $value ) {
global $wpdb;
$sql = sprintf( 'SELECT * FROM %s WHERE %s = %%s', self::_table(), static::$primary_key );
return $wpdb->prepare( $sql, $value ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
}
private static function _table() {
global $wpdb;
$tablename = strtolower( get_called_class() );
$tablename = str_replace( 'wfco_model_', 'wfco_', $tablename );
return $wpdb->prefix . $tablename;
}
static function insert( $data ) {
global $wpdb;
$wpdb->insert( self::_table(), $data ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
}
static function update( $data, $where ) {
global $wpdb;
$wpdb->update( self::_table(), $data, $where ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
}
static function delete( $value ) {
global $wpdb;
$sql = sprintf( 'DELETE FROM %s WHERE %s = %%s', self::_table(), static::$primary_key );
return $wpdb->query( $wpdb->prepare( $sql, $value ) ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
}
static function insert_id() {
global $wpdb;
return $wpdb->insert_id;
}
static function now() {
return self::time_to_date( time() );
}
static function time_to_date( $time ) {
return gmdate( 'Y-m-d H:i:s', $time );
}
static function date_to_time( $date ) {
return strtotime( $date . ' GMT' );
}
static function num_rows() {
global $wpdb;
return $wpdb->num_rows;
}
static function count_rows( $dependency = null ) {
global $wpdb;
$sql = 'SELECT COUNT(*) FROM ' . self::_table();
if ( ! is_null( $dependency ) ) {
$sql .= ' INNER JOIN ' . $dependency['dependency_table'];
$sql .= ' on ' . self::_table() . '.' . $dependency['dependent_col'];
$sql .= ' =' . $dependency['dependency_table'] . '.' . $dependency['dependency_col'];
$sql .= ' WHERE ' . $dependency['dependency_table'] . '.' . $dependency['col_name'];
$sql .= ' =' . $dependency['col_value'];
if ( isset( $dependency['connector_id'] ) ) {
$sql .= ' AND ' . $dependency['connector_table'] . '.' . $dependency['connector_col'] . '=' . $dependency['connector_id'];
}
}
return $wpdb->get_var( $sql ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
}
static function get_specific_rows( $where_key, $where_value ) {
global $wpdb;
$table_name = self::_table();
$results = $wpdb->get_results( "SELECT * FROM $table_name WHERE $where_key = '$where_value'", ARRAY_A ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
return $results;
}
static function get_results( $query ) {
global $wpdb;
$query = str_replace( '{table_name}', self::_table(), $query );
$results = $wpdb->get_results( $query, ARRAY_A ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
return $results;
}
static function delete_multiple( $query ) {
global $wpdb;
$query = str_replace( '{table_name}', self::_table(), $query );
$wpdb->query( $query ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
}
static function update_multiple( $query ) {
global $wpdb;
$query = str_replace( '{table_name}', self::_table(), $query );
$wpdb->query( $query ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
}
}
}

View File

@@ -0,0 +1,93 @@
<?php
if ( ! class_exists( 'WooFunnels_Addons' ) ) {
/**
* Basic class that do operations and get data from wp core
* @since 1.0.0
* @package WooFunnels
* @author woofunnels
*/
#[AllowDynamicProperties]
class WooFunnels_Addons {
public static $installed_addons = array();
public static $update_available = array();
public static function init() {
add_filter( 'extra_plugin_headers', array( __CLASS__, 'extra_woocommerce_headers' ) );
}
/**
* Adding WooFunnels Header to tell WordPress to read one extra params while reading plugin's header info. <br/>
* Hooked over `extra_plugin_headers`
*
* @param array $headers already registered arrays
*
* @return type
* @since 1.0.0
*
*/
public static function extra_woocommerce_headers( $headers ) {
array_push( $headers, 'WooFunnels' );
array_push( $headers, 'WooFunnels' );
return $headers;
}
/**
* Getting all installed plugin that has woofunnels header within
* @return array Addons
*/
public static function get_installed_plugins() {
if ( ! empty( self::$installed_addon ) ) {
return self::$installed_addon;
}
wp_cache_delete( 'plugins', 'plugins' );
$plugins = self::get_plugins( true );
$plug_addons = array();
foreach ( $plugins as $plugin_file => $plugin_data ) {
if ( isset( $plugin_data['WooFunnels'] ) && $plugin_data['WooFunnels'] ) {
$plug_addons[ $plugin_file ] = $plugin_data;
}
}
self::$installed_addons = $plug_addons;
return $plug_addons;
}
/**
* Play it safe and require WP's plugin.php before calling the get_plugins() function.
*
* @return array An array of installed plugins.
*/
public static function get_plugins( $clear_cache = false ) {
require_once( ABSPATH . '/wp-admin/includes/plugin.php' );
$plugins = get_plugins();
if ( $clear_cache || ! self::plugins_have_woofunnels_plugin_header( $plugins ) ) {
$plugins = get_plugins();
}
return $plugins;
}
/**
* Checking Plugin header and Trying to find out the one with the header `WooFunnels`
*
* @param Array $plugins array of available plugins
*
* @return mixed
*/
public static function plugins_have_woofunnels_plugin_header( $plugins ) {
$plugin = reset( $plugins );
return $plugin && isset( $plugin['WooFunnels'] );
}
}
WooFunnels_Addons::init();
}

View File

@@ -0,0 +1,127 @@
<?php
if ( ! class_exists( 'WooFunnels_Admin_Notifications' ) ) {
/**
* Class that is responsible for pushing , removing and sometimes handling the way notifications comes from the core.
* @since 1.0.0
* @package WooFunnels
* @author woofunnels
*/
#[AllowDynamicProperties]
class WooFunnels_Admin_Notifications {
public static $all_notifications;
/**
* Add notification
* <br/> This function will add the notification
*
* @param array $args configuration for notification
*
* <br/>
*
* @since 1.0.0
*/
public static function add_notification( $args ) {
$default = array(
'type' => 'success',
'content' => '',
'is_dismissible' => true,
'callback' => null,
'show_only' => false,
);
self::$all_notifications[ key( $args ) ] = wp_parse_args( $args[ key( $args ) ], $default );
}
/**
* Hide notices to show under dashboard
* <br/> Its a handler function to any request come to hide the notice
* <br/> save the slug in Database so that it wont come again
*/
public static function hide_notices() {
if ( isset( $_GET['woofunnels-hide-notice'] ) && isset( $_GET['_woofunnels_notice_nonce'] ) ) {
if ( ! wp_verify_nonce( sanitize_text_field( $_GET['_woofunnels_notice_nonce'] ), 'woofunnels_hide_notices_nonce' ) ) {
wp_die( esc_html__( 'Action failed. Please refresh the page and retry.', 'woofunnels' ) ); // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
}
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( esc_html__( 'Cheating huh?', 'woofunnels' ) ); // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
}
$hide_notice = sanitize_text_field( $_GET['woofunnels-hide-notice'] );
self::remove_notice( $hide_notice );
do_action( 'woofunnels_hide_' . $hide_notice . '_notice' );
}
}
/**
* Remove a notice from being displayed
*
* @param string $name
*/
public static function remove_notice( $name ) {
$has_notice_removed = get_option( 'woofunnels_admin_notices' );
if ( $has_notice_removed && ! empty( $has_notice_removed ) ) {
$array_to_push = array_push( $has_notice_removed, $name );
update_option( 'woofunnels_admin_notices', $array_to_push, false );
} else {
update_option( 'woofunnels_admin_notices', array( $name ), false );
}
}
/**
* Render all the notifications after filtering
* @since 1.0.0
*/
public static function render() {
self::filter_before_render();
if ( ! is_null( self::$all_notifications ) && ! empty( self::$all_notifications ) ) {
foreach ( self::$all_notifications as $slug => $notification ) {
?>
<div id="message" class="notice notice-<?php echo esc_attr($notification['type']); ?>"><?php echo wp_kses_post( $notification['content'] ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></div>
<?php
}
}
}
/**
* Filter function that will filter pushed notification against the removed ones
*/
public static function filter_before_render() {
$clone = self::$all_notifications;
$get_all_removed = self::get_all_removed();
if ( ! is_null( self::$all_notifications ) && ! empty( self::$all_notifications ) && ! empty( $get_all_removed ) ) {
foreach ( self::$all_notifications as $slug => $notification ) {
if ( in_array( $slug, self::get_all_removed(), true ) ) {
unset( $clone[ $slug ] );
}
}
}
self::$all_notifications = $clone;
}
/**
* Get all removed notifications from database
* So that we can filter the push notification with the removed ones
* @return array
*/
public static function get_all_removed() {
return get_option( 'woofunnels_admin_notices' );
}
/**
* Check whether has notification pushed?
* @since 1.0.0
*/
public static function has_notification( $slug ) {
if ( is_null( self::$all_notifications ) ) :
return false;
endif;
return array_key_exists( $slug, self::$all_notifications );
}
}
}

View File

@@ -0,0 +1,228 @@
<?php
/**
* API handler for woofunnels
* @package WooFunnels
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
} // Exit if accessed directly
if ( ! class_exists( 'WooFunnels_API' ) ) :
/**
* WooFunnels_License Class
*/
#[AllowDynamicProperties]
class WooFunnels_API {
public static $woofunnels_api_url = 'https://track.funnelkit.com';
public static $is_ssl = false;
/**
* Get all the plugins that can be pushed from the API
* @return Mixed False on failure and array on success
*/
public static function get_woofunnels_list() {
$woofunnels_modules = get_transient( 'woofunnels_get_modules' );
if ( defined( 'WP_DEBUG' ) && WP_DEBUG === true ) {
$woofunnels_modules = '';
}
if ( ! empty( $woofunnels_modules ) ) {
return $woofunnels_modules;
}
$api_params = self::get_api_args( array(
'action' => 'get_woofunnels_plugins',
'attrs' => array(
'meta_query' => array(
array(
'key' => 'is_visible_in_dashboard',
'value' => 'yes',
'compare' => '=',
),
),
),
) );
$request_args = self::get_request_args( array(
'timeout' => 30,
'sslverify' => self::$is_ssl,
'body' => urlencode_deep( $api_params ),
) );
$request = wp_remote_post( self::get_api_url( self::$woofunnels_api_url ), $request_args );
if ( is_wp_error( $request ) ) {
return false;
}
$request = json_decode( wp_remote_retrieve_body( $request ) );
if ( ! $request ) {
return false;
}
$woofunnels_modules = $request;
set_transient( 'woofunnels_get_modules', $request, 60 * 60 * 12 );
return ! empty( $woofunnels_modules ) ? $woofunnels_modules : false;
}
/**
* Post tracking data to the Server
*
* @param $data
*
* @return array|void|WP_Error
*/
public static function post_tracking_data( $data ) {
if ( empty( $data ) ) {
return;
}
$api_params = self::get_api_args( array(
'action' => 'get_tracking_data',
'data' => $data,
) );
$request_args = self::get_request_args( array(
'timeout' => 30,
'sslverify' => self::$is_ssl,
'body' => urlencode_deep( $api_params ),
) );
$request = wp_remote_post( self::get_api_url( self::$woofunnels_api_url ), $request_args );
return $request;
}
/**
* @param $data
*
* @return array|bool|mixed|object|void|WP_Error|null
*/
public static function post_support_request( $data ) {
if ( empty( $data ) ) {
return;
}
$api_params = self::get_api_args( array(
'action' => 'submit_support_request',
'data' => $data,
) );
$request_args = self::get_request_args( array(
'timeout' => 30,
'sslverify' => self::$is_ssl,
'body' => urlencode_deep( $api_params ),
) );
$request = wp_remote_post( self::get_api_url( self::$woofunnels_api_url ), $request_args );
if ( ! is_wp_error( $request ) ) {
$request = json_decode( wp_remote_retrieve_body( $request ) );
return $request;
}
return false;
}
/**
* Filter function to modify args
*
* @param $args
*
* @return mixed|void
*/
public static function get_api_args( $args ) {
return apply_filters( 'woofunnels_api_call_args', $args );
}
/**
* Filter function for request args
*
* @param $args
*
* @return mixed|void
*/
public static function get_request_args( $args ) {
return apply_filters( 'woofunnels_api_call_request_args', $args );
}
/**
* All the data about the deactivation popups
*
* @param $deactivations
* @param $licenses
*
* @return array|WP_Error
*/
public static function post_deactivation_data( $deactivations ) {
$get_deactivation_data = array(
'site' => home_url(),
'deactivations' => $deactivations,
'logged_errors' => apply_filters( 'send_filter_deactivations_data', [] )
);
$api_params = self::get_api_args( array(
'action' => 'get_deactivation_data',
'data' => $get_deactivation_data,
'licenses' => [],
) );
$request_args = self::get_request_args( array(
'sslverify' => self::$is_ssl,
'body' => urlencode_deep( $api_params ),
) );
$request = wp_remote_post( self::get_api_url( self::$woofunnels_api_url ), $request_args );
return $request;
}
/**
* Get for API url
*
* @param string $link
*
* @return string
*/
public static function get_api_url( $link ) {
return apply_filters( 'woofunnels_api_call_url', $link );
}
public static function get_woofunnels_status() {
//do a woofunnels_status_check
return true;
}
/**
* @param $data
*
* @return array|void|WP_Error
*/
public static function post_optin_data( $data ) {
if ( empty( $data ) ) {
return;
}
$api_params = self::get_api_args( array(
'action' => 'woofunnelsapi_optin',
'data' => $data,
) );
$request_args = self::get_request_args( array(
'timeout' => 30,
'sslverify' => self::$is_ssl,
'body' => urlencode_deep( $api_params ),
) );
$request = wp_remote_post( self::get_api_url( self::$woofunnels_api_url ), $request_args );
return $request;
}
}
endif; // end class_exists check

View File

@@ -0,0 +1,75 @@
<?php
/**
* @author woofunnels
* @package WooFunnels
*/
if ( ! class_exists( 'WooFunnels_Cache' ) ) {
#[AllowDynamicProperties]
class WooFunnels_Cache {
protected static $instance;
protected $woofunnels_core_cache = array();
/**
* WooFunnels_Cache constructor.
*/
public function __construct() {
}
/**
* Creates an instance of the class
* @return WooFunnels_Cache
*/
public static function get_instance() {
if ( null === self::$instance ) {
self::$instance = new self;
}
return self::$instance;
}
/**
* Set the cache contents by key and group within page scope
*
* @param $key
* @param $data
* @param string $group
*/
public function set_cache( $key, $data, $group = '0' ) {
$this->woofunnels_core_cache[ $group ][ $key ] = $data;
}
/**
* Get the cache contents by the cache key or group.
*
* @param $key
* @param string $group
*
* @return bool|mixed
*/
public function get_cache( $key, $group = '0' ) {
if ( isset( $this->woofunnels_core_cache[ $group ] ) && isset( $this->woofunnels_core_cache[ $group ][ $key ] ) ) {
return $this->woofunnels_core_cache[ $group ][ $key ];
}
return false;
}
/**
* Reset the cache by group or complete reset by force param
*
* @param string $group
* @param bool $force
*/
function reset_cache( $group = '0', $force = false ) {
if ( true === $force ) {
$this->woofunnels_core_cache = array();
} elseif ( isset( $this->woofunnels_core_cache[ $group ] ) ) {
$this->woofunnels_core_cache[ $group ] = array();
}
}
}
}

View File

@@ -0,0 +1,929 @@
<?php
/**
* This class is a mail loader class for dashboard page , controls and sets up all the necessary actions
*
* @author woofunnels
* @package WooFunnels
*/
define( 'BWF_VERSION', '1.10.12.71' );
define( 'BWF_DB_VERSION', '1.0.6' );
if ( ! class_exists( 'WooFunnels_Dashboard' ) ) {
#[AllowDynamicProperties]
class WooFunnels_Dashboard {
public static $currentPage;
public static $parent;
public static $selected = '';
public static $pagefullurl = '';
public static $is_dashboard_page = false;
public static $loader_url = '';
public static $is_core_menu = false;
public static $classes = [];
protected static $expectedurl;
protected static $expectedslug;
/**
* Function Loads the html and required javascript to render on dashboard page
*/
public static function load_page() {
//do_action
do_action( 'woofunnels_before_dashboard_page' );
self::register_dashboard();
$model = apply_filters( 'woofunnels_tabs_modal_' . self::$selected, array() );
$all_valid_tabs = [ 'licenses', 'logs', 'plugins', 'support', 'tools' ];
if ( ! in_array( self::$selected, $all_valid_tabs, true ) ) {
return;
}
?>
<div class="wrap">
<div class="icon32" id="icon-themes"><br></div>
<div class="woofunnels_dashboard_tab_content" id="<?php echo esc_attr( self::$selected ); ?>">
<?php include_once self::$loader_url . 'views/woofunnels-tabs-' . self::$selected . '.phtml'; ?>
</div>
</div>
<?php
}
/**
* Register dashboard function just initializes the execution by firing some hooks that helps getting and rendering data
*/
public static function register_dashboard() {
//registering necessary hooks
//making sure these hooks loads only when register for dashboard happens (specific page)
self::woofunnels_dashboard_scripts();
add_action( 'woofunnels_tabs_modal_licenses', array( __CLASS__, 'woofunnels_licenses_data' ), 99 );
add_action( 'woofunnels_tabs_modal_support', array( __CLASS__, 'woofunnels_support_data' ), 99 );
add_action( 'woofunnels_tabs_modal_tools', array( __CLASS__, 'woofunnels_tools_data' ), 99 );
add_action( 'woofunnels_tabs_modal_logs', array( __CLASS__, 'woofunnels_logs_data' ), 99 );
add_action( 'woofunnels_tools_right_area', array( __CLASS__, 'show_right_area' ) );
add_filter( 'woofunnels_additional_tabs', array( __CLASS__, 'add_logs_tabs' ), 10, 1 );
}
/**
* Hooked over 'admin_enqueue_scripts' under the register function, cannot run on every admin page
* Enqueues `updates` handle script, core script that is responsible for plugin updates
*/
public static function woofunnels_dashboard_scripts() {
?>
<style type="text/css">
/* product grid */
.woofunnels_plugins_wrap .filter-links.filter-primary {
border-right: 2px solid #e5e5e5;
}
.woofunnels_plugins_wrap .wp-filter {
margin-bottom: 0;
}
.woofunnels_plugins_wrap .filter-links li {
border-bottom: 4px solid white;
}
.woofunnels_plugins_wrap .filter-links li a.current {
border-bottom: 4px solid #fff;
}
.woofunnels_plugins_wrap .filter-links li.current {
border-bottom-color: #666666;
}
.woofunnels_plugins_wrap .woofunnels_dashboard_tab_content {
float: left;
width: 54%;
}
.woofunnels_plugins_wrap .woofunnels_dashboard_license_content {
float: left;
width: 74%;
}
.woofunnels_plugins_wrap .woofunnels_dashboard_tab_content .woofunnels_core_tools {
width: 100% !important;
background: #fff;
}
.woofunnels_plugins_wrap .woofunnels_dashboard_tab_content .woofunnels_core_tools h2 {
margin-top: 0;
}
.woofunnels_plugins_wrap .woofunnels_plugins_status {
font-style: italic;
}
.woofunnels_plugins_wrap .woofunnels_plugins_features_div {
}
.woofunnels_plugins_wrap div#col-container.about-wrap {
max-width: 100%;
margin: 30px 20px 0 0;
width: auto;
margin-right: 0;
clear: both;
}
.woofunnels_plugins_wrap div#col-container.about-wrap .col-wrap {
float: left;
}
.woofunnels_dashboard_tab_content .woofunnels_plugins_wrap .woofunnels-area-right {
float: right;
width: 44%;
margin: 0;
}
.woofunnels_dashboard_tab_content#licenses .woofunnels_plugins_wrap .woofunnels-area-right {
width: 24%;
}
.woofunnels_plugins_wrap .woofunnels-area-right table {
padding: 15px;
}
.woofunnels_plugins_wrap .woofunnels-area-right table th, .woofunnels_plugins_wrap .woofunnels-area-right table td {
vertical-align: middle;
padding: 15px 0;
}
.woofunnels_plugins_wrap .woofunnels-area-right table td {
text-align: right;
}
.woofunnels_plugins_wrap .woofunnels_plugins_features {
margin-left: -10px;
margin-right: -10px;
}
.woofunnels_plugins_wrap .woofunnels_plugins_features .woofunnels_plugins_half_col {
width: 100%;
margin: 4px 0;
padding-left: 30px;
padding-right: 10px;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.woofunnels_plugins_wrap .woofunnels_plugins_features .woofunnels_plugins_half_col:before {
margin-left: -20px;
content: "\f147";
font: 400 20px/.5 dashicons;
speak: none;
display: inline-block;
padding: 0;
top: 4px;
left: -2px;
position: relative;
vertical-align: top;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-decoration: none !important;
color: #444;
}
@media screen and (min-width: 481px) {
.woofunnels_plugins_wrap .woofunnels_plugins_features .woofunnels_plugins_half_col {
width: 50%;
float: left;
}
.woofunnels_plugins_wrap .woofunnels_plugins_features .woofunnels_plugins_half_col:nth-child(2n) {
text-align: right;
}
.woofunnels_plugins_wrap .woofunnels_plugins_features .woofunnels_plugins_half_col:nth-child(2n+1) {
clear: both;
}
}
.woofunnels_plugins_wrap .woofunnels_plugins_status_div {
padding-top: 8px;
padding-bottom: 8px;
border-color: rgba(221, 221, 221, 0.4);
background: #fff;
}
.woofunnels_plugins_wrap .woofunnels_plugins_status_div .woofunnels_plugins_status {
margin: 0;
}
.woofunnels_plugins_wrap .button-primary.woofunnels_plugins_renew_btn {
min-width: 120px;
text-align: center;
}
.woofunnels_plugins_wrap .button-primary.woofunnels_plugins_renew_btn:before {
content: "\f321";
font: 400 20px/.5 dashicons;
speak: none;
display: inline-block;
padding: 0;
top: 4px;
left: -2px;
position: relative;
vertical-align: top;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-decoration: none !important;
color: #fff;
}
.woofunnels_plugins_wrap .button-primary.woofunnels_plugins_buy_btn {
min-width: 120px;
text-align: center;
}
.woofunnels_plugins_wrap .button-primary.woofunnels_plugins_buy_btn:before {
content: "\f174";
font: 400 20px/.5 dashicons;
speak: none;
display: inline-block;
padding: 0;
top: 4px;
left: -2px;
position: relative;
vertical-align: top;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-decoration: none !important;
color: #fff;
}
.woofunnels_plugins_wrap .plugin-card-bottom.woofunnels_plugins_features_links_div {
background: #fff;
}
.woofunnels_plugins_wrap .plugin-card-bottom.woofunnels_plugins_features_links_div .woofunnels_plugins_features_links ul {
margin: 0;
}
.woofunnels_plugins_wrap .woofunnels_plugins_deactivate_add.woofunnels_plugins_features_links {
padding-right: 125px;
display: block;
position: relative;
}
.woofunnels_plugins_wrap .woofunnels_plugins_deactivate_add.woofunnels_plugins_features_links .woofunnels_plugins_deactivate {
color: #a00000;
display: inline-block;
line-height: 26px;
}
.clearfix:after, .clearfix:before {
display: table;
content: '';
}
.clearfix:after {
clear: both;
}
.woofunnels_plugins_wrap ul.woofunnels_plugins_options {
display: inline-block;
line-height: 26px;
float: right;
position: absolute;
z-index: 1;
right: 0;
}
.woofunnels_plugins_wrap ul.woofunnels_plugins_options li {
display: inline-block;
margin: 0;
}
.woofunnels_plugins_wrap .js_filters li a:focus {
box-shadow: none;
-webkit-box-shadow: none;
color: #23282d;
}
#licenses .column-product_status, .index_page_woothemes-helper-network .column-product_status {
width: 350px;
}
#licenses .below_input_message {
color: #9E0B0F;
padding-left: 1px;
}
#licenses .below_input_message a {
text-decoration: underline;
}
.woofunnels-updater-plugin-upgrade-notice {
font-weight: 400;
color: #fff;
background: #d54d21;
padding: 1em;
margin: 9px 0;
}
.woofunnels-updater-plugin-upgrade-notice:before {
content: "\f348";
display: inline-block;
font: 400 18px/1 dashicons;
speak: none;
margin: 0 8px 0 -2px;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
vertical-align: top;
}
#support-request label:not(.radio) {
display: block;
font-weight: 600;
font-size: 14px;
line-height: 1.3;
}
#pdf-system-status {
overflow: hidden;
}
#pdf-system-status p {
clear: left;
}
#pdf-system-status span.details, #support-request span.details {
font-size: 95%;
color: #444;
margin-top: 7px;
display: inline-block;
clear: left;
}
#pdf-system-status span.details.path, #support-request span.details.path {
padding: 2px;
background: #f2f2f2;
}
#support-request input:not([type="radio"]), #support-request select {
width: 20em;
max-width: 350px;
width: 100%;
}
#support-request input[type="submit"] {
width: auto;
}
#support-request textarea {
width: 65%;
height: 150px;
}
#support-request input, #support-request textarea {
padding: 5px 4px;
}
#support-request #support-request-button {
padding: 0 8px;
}
#support-request .gfspinner {
vertical-align: middle;
margin-left: 5px;
}
#support-request textarea {
max-width: 350px;
width: 100%;
/* border: 1px solid #999;
color: #444;*/
}
#support-request :disabled, #support-request textarea:disabled {
color: #CCC;
border: 1px solid #CCC;
}
#support-request input.error, #support-request textarea.error, #support-request select.error {
color: #d10b0b;
border: 1px solid #d10b0b;
}
#support-request .form-table .radioBtns span {
margin-right: 10px;
display: inline-block;
}
#support-request .fa-times-circle {
vertical-align: middle;
}
.icon-spinner {
font-size: 18px;
margin-left: 5px;
}
#support-request span.msg {
margin-left: 5px;
color: #008000;
}
#support-request span.error {
margin-left: 5px;
color: #d10b0b;
}
#lv_pointer_target {
float: right;
background: #0e3f7a;
color: #fff;
border: none;
position: relative;
top: -6px;
}
#lv_pointer_target:focus {
border: none;
-webkit-box-shadow: none;
box-shadow: none;
}
.woofunnels_plugins_wrap .filter-links li > a:focus {
-webkit-box-shadow: none;
box-shadow: none;
-moz-box-shadow: none;
}
@media (max-width: 1023px) {
#support-request .form-table .radioBtns span {
display: block;
margin-bottom: 4px;
}
}
@media screen and (max-width: 782px) {
.woofunnels_plugins_wrap .woofunnels_dashboard_tab_content {
float: none;
}
.woofunnels_plugins_wrap div#col-container.about-wrap {
margin-right: 0;
}
.woofunnels_plugins_wrap div#col-container.about-wrap .woofunnels-area-right {
float: none;
margin-right: 0;
width: 280px;
margin-left: 0;
margin: auto;
}
.woofunnels_plugins_wrap div#col-container.about-wrap .col-wrap {
float: left;
}
#support-request .form-table input[type="radio"] {
height: 16px;
width: 16px;
}
}
.woofunnels_core_tools .woofunnels_download_files_label {
display: inline-block;
padding-left: 10px;
vertical-align: -webkit-baseline-middle;
}
.woofunnels_core_tools .woofunnels_download_buttons {
display: inline-block;
padding-left: 5px;
}
</style>
<?php
}
/**
* Init function hooked on `admin_init`
* Set the required variables and register some important hooks
*/
public static function init() {
self::$loader_url = WooFunnel_Loader::$ultimate_path;
$selected = null !== sanitize_text_field( filter_input( INPUT_GET, 'tab', FILTER_UNSAFE_RAW ) ) ? sanitize_text_field( filter_input( INPUT_GET, 'tab', FILTER_UNSAFE_RAW ) ) : 'plugins';
self::$selected = $selected;
/**
* Function to trigger error message at WordPress plugins page when we have update but license invalid
*/
self::add_notice_unlicensed_product();
/**
* Initialize Localization
*/
add_action( 'init', array( __CLASS__, 'localization' ) );
add_action( 'admin_head', [ __CLASS__, 'apply_scroll_fix_css' ] );
}
/**
* Getting and parsing all our licensing products and checking if there update is available
*/
public static function add_notice_unlicensed_product() {
/**
* Getting necessary data
*/
$licenses = WooFunnels_licenses::get_instance()->get_data();
/**
* Looping over to check how many licenses are invalid and pushing notification and error accordingly
*/
if ( $licenses && count( $licenses ) > 0 ) {
foreach ( $licenses as $key => $license ) {
if ( $license['product_status'] === 'invalid' ) {
add_action( 'in_plugin_update_message-' . $key, array( __CLASS__, 'need_license_message' ), 10, 2 );
}
}
}
}
public static function localization() {
load_plugin_textdomain( 'woofunnels', false, plugin_basename( dirname( __FILE__ ) ) . '/languages' );
}
/**
* Message displayed if license not activated. <br/>
*
* @param array $plugin_data
* @param object $r
*
* @return void
*/
public static function need_license_message( $plugin_data, $r ) {
if ( empty( $r->package ) ) {
echo wp_kses_post( '<div class="woofunnels-updater-plugin-upgrade-notice">' . __( 'To enable this update please activate your FunnelKit license by visiting the Dashboard Page.', 'woofunnels' ) . '</div>' ); // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
}
}
/**
* Model function to fire over licensing page. <br/>
* Hooked over 'woofunnels_tabs_modal_licenses'. <br/>
* @return mixed false on failure and data on success
*/
public static function woofunnels_licenses_data() {
if ( false === WooFunnels_API::get_woofunnels_status() ) {
return;
}
$get_list = array();
$License = WooFunnels_licenses::get_instance();
return (object) array_merge( (array) $get_list, (array) array(
'additional_tabs' => apply_filters( 'woofunnels_additional_tabs', array(
array(
'slug' => 'tools',
'label' => __( 'Tools', 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
),
) ),
'licenses' => $License->get_data(),
'current_tab' => self::$selected,
) );
}
/**
* Model function to fire over licensing page. <br/>
* Hooked over 'woofunnels_tabs_modal_licenses'. <br/>
* @return mixed false on failure and data on success
*/
public static function woofunnels_tools_data() {
if ( false === WooFunnels_API::get_woofunnels_status() ) {
return;
}
$get_list = array();
return (object) array_merge( (array) $get_list, (array) array(
'additional_tabs' => apply_filters( 'woofunnels_additional_tabs', array(
array(
'slug' => 'tools',
'label' => __( 'Tools', 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
),
) ),
'current_tab' => self::$selected,
) );
}
/**
* Model function to fire over support page. <br/>
* Hooked over 'woofunnels_tabs_modal_support'. <br/>
* @return mixed false on failure and data on success
*/
public static function woofunnels_support_data( $data ) {
//getting plugins list and tabs data
$get_list = array();
return (object) array_merge( (array) $get_list, (array) array(
'additional_tabs' => apply_filters( 'woofunnels_additional_tabs', array(
array(
'slug' => 'tools',
'label' => __( 'Tools', 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
),
) ),
'email' => get_bloginfo( 'admin_email' ),
'current_tab' => self::$selected,
) );
}
/**
* Model function to fire over support page. <br/>
* Hooked over 'woofunnels_tabs_modal_logs'. <br/>
* @return mixed false on failure and data on success
*/
public static function woofunnels_logs_data( $data ) {
//getting plugins list and tabs data
$get_list = array();
return (object) array_merge( (array) $get_list, (array) array(
'additional_tabs' => apply_filters( 'woofunnels_additional_tabs', array(
array(
'slug' => 'tools',
'label' => __( 'Tools', 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
),
) ),
'current_tab' => self::$selected,
) );
}
public static function show_right_area() {
if ( wp_verify_nonce( filter_input( INPUT_GET, '_nonce', FILTER_UNSAFE_RAW ), 'bwf_tools_action' ) && isset( $_GET['woofunnels_transient'] ) && ( 'clear' === sanitize_text_field( $_GET['woofunnels_transient'] ) ) ) {
$woofunnels_transient_obj = WooFunnels_Transient::get_instance();
$woofunnels_transient_obj->delete_force_transients();
$message = __( 'All Plugins transients cleared.', 'woofunnels' ); // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
?>
<div class="notice notice-success is-dismissible">
<p><?php echo esc_html( $message ); ?></p>
</div>
<?php
}
$nonce = wp_create_nonce( 'bwf_tools_action' );
$clear_transient_url = admin_url( 'admin.php?page=woofunnels&tab=tools&woofunnels_transient=clear&_nonce=' . $nonce );
$show_reset_tracking = apply_filters( 'woofunnels_show_reset_tracking', false );
?>
<table class="widefat" cellspacing="0">
<tbody class="tools">
<?php do_action( 'woofunnels_tools_add_tables_row_start' ); ?>
<tr>
<th>
<strong class="name"><?php esc_html_e( 'WooFunnels transients', 'woofunnels' ); // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch ?></strong>
<p class="description"><?php esc_html_e( 'This tool will clear all the WooFunnels plugins transients cache.', 'woofunnels' ); // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch ?></p>
</th>
<td class="run-tool">
<a href="<?php echo esc_url( $clear_transient_url ); ?>" class="button button-large"><?php esc_html_e( 'Clear transients', 'woofunnels' ); // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch ?></a>
</td>
</tr>
<?php if ( true === $show_reset_tracking ) {
$reset_tracking_url = admin_url( 'admin.php?page=woofunnels&tab=tools&woofunnels_tracking=reset&_nonce=' . $nonce );
$is_opted = WooFunnels_OptIn_Manager::get_optIn_state();
if ( 'yes' === $is_opted ) {
$text_btn = __( 'Turn Off', 'woofunnels' ); // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
} else {
$reset_tracking_url .= '&action=yes';
$text_btn = __( 'Turn On', 'woofunnels' ); // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
}
?>
<tr>
<th>
<strong class="name"><?php esc_html_e( 'Usage Tracking', 'woofunnels' ); // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch ?></strong>
<p class="description"><?php esc_html_e( 'This action controls Usage Tracking', 'woofunnels' ); // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch ?></p>
</th>
<td class="run-tool">
<a href="<?php echo esc_url( $reset_tracking_url ); ?>" class="button button-large"><?php echo esc_html( $text_btn ); ?></a>
</td>
</tr>
<?php } ?>
<?php do_action( 'woofunnels_tools_add_tables_row' ); ?>
</tbody>
</table>
<?php
}
public static function add_logs_tabs( $tabs ) {
$tabs[] = array(
'slug' => 'logs',
'label' => __( 'Logs', 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
);
return $tabs;
}
public static function autoloader( $class_name ) {
if ( 0 === strpos( $class_name, 'WooFunnels_' ) || 0 === strpos( $class_name, 'BWF_' ) ) {
$path = WooFunnel_Loader::$ultimate_path . 'includes/class-' . self::slugify_classname( $class_name ) . '.php';
$contact_path = WooFunnel_Loader::$ultimate_path . 'contact/class-' . self::slugify_classname( $class_name ) . '.php';
if ( is_file( $path ) ) {
require_once $path;
}
if ( is_file( $contact_path ) ) {
require_once $contact_path;
}
/**
* loading compatibility classes
*/
if ( false !== strpos( $class_name, 'Compatibility' ) || false !== strpos( $class_name, 'Compatibilities' ) ) {
$path = WooFunnel_Loader::$ultimate_path . 'compatibilities/class-' . self::slugify_classname( $class_name ) . '.php';
if ( is_file( $path ) ) {
require_once $path;
}
}
}
if ( 0 === strpos( $class_name, 'WFCO_' ) ) {
$path = WooFunnel_Loader::$ultimate_path . 'connector/class-' . self::slugify_classname( $class_name ) . '.php';
$model_path = WooFunnel_Loader::$ultimate_path . 'includes/class-' . self::slugify_classname( $class_name ) . '.php';
if ( is_file( $path ) ) {
require_once $path;
}
if ( is_file( $model_path ) ) {
require_once $model_path;
}
}
}
/**
* Slug-ify the class name and remove underscores and convert it to filename
* Helper function for the auto-loading
*
* @param $class_name
*
*
* @return mixed|string
* @see WooFunnels_Dashboard::autoloader();
*
*/
public static function slugify_classname( $class_name ) {
$classname = self::custom_sanitize_title( $class_name );
$classname = str_replace( '_', '-', $classname );
return $classname;
}
/**
* Custom sanitize title method to avoid conflicts with WordPress hooks on sanitize_title
*
* @param string $title The title to sanitize
* @return string The sanitized title
*/
private static function custom_sanitize_title( $title ) {
$title = remove_accents( $title );
$title = sanitize_title_with_dashes( $title );
return $title;
}
public static function load_core_classes() {
require dirname( __DIR__ ) . '/includes/bwf-functions.php';
require dirname( __DIR__ ) . '/contact/woofunnels-db-updater-functions.php';
require dirname( __DIR__ ) . '/contact/woofunnels-contact-functions.php';
require dirname( __DIR__ ) . '/contact/woofunnels-customer-functions.php';
$core_classes = array(
'WooFunnels_process',
'WooFunnels_Notifications',
'WooFunnels_DB_Updater',
'WooFunnels_DB_Tables',
'WFCO_Admin',
'WooFunnels_Funnel_Builder_Commons',
'BWF_Data_Tags',
'BWF_Ecomm_Tracking_Common',
'BWF_Logger',
);
foreach ( $core_classes as $class ) {
self::$classes[ $class ] = $class::get_instance();
}
$static_classes = array( 'WooFunnels_OptIn_Manager', 'WooFunnels_deactivate' );
foreach ( $static_classes as $class ) {
$class::init();
}
/** WooFunnels AS Data Store */
include_once dirname( __DIR__ ) . '/as-data-store/class-woofunnels-as-ds.php';
add_action( 'shutdown', [ __CLASS__, 'fetch_template_json' ] );
add_action( 'admin_init', array( __CLASS__, 'index_templates' ) );
}
public static function apply_scroll_fix_css() {
global $current_screen;
if ( $current_screen instanceof WP_Screen && strpos( $current_screen->base, 'woofunnels' ) !== false ) {
/** Allow for woofunnels pages */
} elseif ( false === apply_filters( 'bwf_scroll_fix_allow', false ) ) {
return;
}
ob_start();
?>
<style>
#adminmenuwrap {
position: relative !important;
top: 0 !important;
}
body, html {
height: auto;
position: relative
}
</style>
<?php
echo ob_get_clean(); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
public static function index_templates() {
$get_templates = filter_input( INPUT_GET, 'wffn_parse_template', FILTER_UNSAFE_RAW );
if ( 'yes' === $get_templates && current_user_can( 'manage_options' ) ) {
self::get_all_templates( true );
wp_safe_redirect( admin_url( 'admin.php?page=woofunnels&tab=tools' ) );
exit;
}
}
public static function get_all_templates( $force = false ) {
$woofunnels_cache_object = WooFunnels_Cache::get_instance();
$get_transient_instance = WooFunnels_Transient::get_instance();
$transient = $woofunnels_cache_object->get_cache( '_bwf_fb_templates' );
if ( empty( $transient ) ) {
$transient = $get_transient_instance->get_transient( '_bwf_fb_templates' );
}
if ( empty( $transient ) || true === $force ) {
$templates = self::get_remote_templates();
if ( is_array( $templates ) ) {
$get_transient_instance->set_transient( '_bwf_fb_templates', count( $templates ), HOUR_IN_SECONDS * 12 );
}
return $templates;
}
return apply_filters( 'bwf_fb_templates', get_option( '_bwf_fb_templates' ) );
}
public static function get_remote_templates() {
$json_templates = [];
$endpoint_url = self::get_template_api_url();
$request_args = array(
'timeout' => 30, //phpcs:ignore WordPressVIPMinimum.Performance.RemoteRequestTimeout.timeout_timeout
'sslverify' => false
);
$response = wp_safe_remote_get( $endpoint_url . 'templatesv3.json', $request_args );
BWF_Logger::get_instance()->log( 'API Call templates.json response::: ' . print_r( $response, true ), 'wffn_template_import' ); //phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r
if ( ! is_wp_error( $response ) ) {
$body = wp_remote_retrieve_body( $response );
if ( ! empty( $body ) ) {
$json_templates = json_decode( $body, true );
if ( is_array( $json_templates ) ) {
update_option( '_bwf_fb_templates', $json_templates, false );
}
}
}
return $json_templates;
}
public static function get_template_api_url() {
return 'https://gettemplates.funnelkit.com/';
}
public static function fetch_template_json() {
if ( 'yes' === filter_input( INPUT_GET, 'activated', FILTER_UNSAFE_RAW ) ) {
flush_rewrite_rules(); // phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.flush_rewrite_rules_flush_rewrite_rules
self::get_all_templates();
}
}
}
}
spl_autoload_register( array( 'WooFunnels_dashboard', 'autoloader' ) );
WooFunnels_dashboard::load_core_classes();
//Initialize the instance so that some necessary hooks can run on each load
add_action( 'admin_init', array( 'WooFunnels_dashboard', 'init' ), 11 );

View File

@@ -0,0 +1,202 @@
<?php
if ( ! class_exists( 'WooFunnels_Deactivate' ) ) {
/**
* Contains the logic for deactivation popups
* @since 1.0.0
* @author woofunnels
* @package WooFunnels
*/
#[AllowDynamicProperties]
class WooFunnels_Deactivate {
public static $deactivation_str;
/**
* Initialization of hooks where we prepare the functionality to ask use for survey
*/
public static function init() {
add_action( 'admin_init', array( __CLASS__, 'load_all_str' ) );
add_action( 'admin_footer', array( __CLASS__, 'maybe_load_deactivate_options' ) );
add_action( 'wp_ajax_woofunnels_submit_uninstall_reason', array( __CLASS__, '_submit_uninstall_reason_action' ) );
}
/**
* Localizes all the string used
*/
public static function load_all_str() {
self::$deactivation_str = array(
'deactivation-share-reason' => __( 'If you have a moment, please let us know why you are deactivating', 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'reason-no-longer-needed' => __( 'No longer need the plugin', 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'reason-found-a-better-plugin' => __( 'I found an alternate plugin', 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'reason-needed-for-a-short-period' => __( 'I only needed the plugin for a short period', 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'placeholder-plugin-name' => __( 'Please share which plugin', 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'reason-broke-my-site' => __( 'Encountered a fatal error', 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'reason-suddenly-stopped-working' => __( 'The plugin suddenly stopped working', 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'reason-other' => _x( 'Other', 'the text of the "other" reason for deactivating the plugin that is shown in the modal box.', 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'deactivation-modal-button-submit' => __( 'Submit & Deactivate', 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'deactivate' => __( 'Deactivate', 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'deactivation-modal-button-deactivate' => __( 'Deactivate', 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'deactivation-modal-button-confirm' => __( 'Yes - Deactivate', 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'deactivation-modal-button-cancel' => _x( 'Cancel', 'the text of the cancel button of the plugin deactivation dialog box.', 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'reason-cant-pay-anymore' => __( "I can't pay for it anymore", 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'placeholder-comfortable-price' => __( 'What price would you feel comfortable paying?', 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'reason-couldnt-make-it-work' => __( "I couldn't understand how to make it work", 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'reason-great-but-need-specific-feature' => __( "The plugin is great, but I need specific feature that you don't support", 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'reason-not-working' => __( 'Couldn\'t get the plugin to work', 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'reason-not-what-i-was-looking-for' => __( "It's not what I was looking for", 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'reason-didnt-work-as-expected' => __( "The plugin didn't work as expected", 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'placeholder-feature' => __( 'What feature?', 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'placeholder-share-what-didnt-work' => __( "Kindly share what didn't work so we can fix it for future users...", 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'placeholder-what-youve-been-looking-for' => __( "What you've been looking for?", 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'placeholder-what-did-you-expect' => __( 'What did you expect?', 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'reason-didnt-work' => __( "The plugin didn't work", 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'reason-dont-like-to-share-my-information' => __( "I don't like to share my information with you", 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'conflicts-other-plugins' => __( "Conflicts with other plugins", 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'temporary-deactivation' => __( "It's a temporary deactivation", 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
);
}
/**
* Checking current page and pushing html, js and css for this task
* @global string $pagenow current admin page
* @global array $VARS global vars to pass to view file
*/
public static function maybe_load_deactivate_options() {
global $pagenow;
if ( $pagenow === 'plugins.php' ) {
global $VARS;
$VARS = array(
'slug' => '',
'reasons' => self::deactivate_options(),
);
include_once dirname( dirname( __FILE__ ) ) . '/views/woofunnels-deactivate-modal.phtml';
}
}
/**
* deactivation reasons in array format
* @return array reasons array
* @since 1.0.0
*/
public static function deactivate_options() {
$reasons = array( 'default' => [] );
$reasons['default'] = array(
array(
'id' => 1,
'text' => self::load_str( 'reason-not-working' ),
'input_type' => '',
'input_placeholder' => self::load_str( 'placeholder-plugin-name' ),
),
array(
'id' => 2,
'text' => self::load_str( 'reason-found-a-better-plugin' ),
'input_type' => 'textfield',
'input_placeholder' => self::load_str( 'placeholder-plugin-name' )
),
array(
'id' => 3,
'text' => self::load_str( 'reason-no-longer-needed' ),
'input_type' => '',
'input_placeholder' => '',
),
array(
'id' => 4,
'text' => self::load_str( 'temporary-deactivation' ),
'input_type' => '',
'input_placeholder' => '',
),
array(
'id' => 5,
'text' => self::load_str( 'conflicts-other-plugins' ),
'input_type' => 'textfield',
'input_placeholder' => self::load_str( 'placeholder-plugin-name' )
),
array(
'id' => 6,
'text' => self::load_str( 'reason-broke-my-site' ),
'input_type' => '',
'input_placeholder' => '',
),
array(
'id' => 7,
'text' => self::load_str( 'reason-other' ),
'input_type' => 'textfield',
'input_placeholder' => __( 'Please share the reason', 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
)
);
return $reasons;
}
/**
* get exact str against the slug
*
* @param $slug
*
* @return mixed
*/
public static function load_str( $slug ) {
return self::$deactivation_str[ $slug ];
}
/**
* Called after the user has submitted his reason for deactivating the plugin.
*
* @since 1.1.2
*/
public static function _submit_uninstall_reason_action() {
try {
check_admin_referer( 'bwf_secure_key', '_nonce' );
if ( ! current_user_can( 'install_plugins' ) ) {
wp_send_json_error();
}
if ( ! isset( $_POST['reason_id'] ) ) {
wp_send_json_error();
}
$reason_info = isset( $_POST['reason_info'] ) ? sanitize_textarea_field( stripslashes( bwf_clean( $_POST['reason_info'] ) ) ) : '';
$reason = array(
'id' => sanitize_text_field( $_POST['reason_id'] ),
'info' => substr( $reason_info, 0, 128 ),
);
$licenses = WooFunnels_addons::get_installed_plugins();
$version = 'NA';
$plugin_basename = isset( $_POST['plugin_basename'] ) ? bwf_clean( $_POST['plugin_basename'] ) : '';
if ( $licenses && count( $licenses ) > 0 ) {
foreach ( $licenses as $key => $license ) {
if ( $key === $plugin_basename ) {
$version = $license['Version'];
}
}
}
$deactivations = array(
$plugin_basename . '(' . $version . ')' => $reason,
);
WooFunnels_API::post_deactivation_data( $deactivations );
} catch ( Exception $e ) {
// Log the exception if necessary
}
wp_send_json_success();
}
}
}

View File

@@ -0,0 +1,211 @@
<?php
/**
* Including WordPress Filesystem API
*/
include_once ABSPATH . '/wp-admin/includes/file.php';
if ( function_exists( 'WP_Filesystem' ) ) {
WP_Filesystem();
}
if ( class_exists( 'WP_Filesystem_Direct' ) ) {
#[AllowDynamicProperties]
class WooFunnels_File_Api extends WP_Filesystem_Direct {
private $upload_dir;
private static $ins = null;
private $core_dir = 'funnelkit';
private $component = '';
public function __construct( $component ) {
$upload = wp_upload_dir();
$this->upload_dir = $upload['basedir'];
$this->woofunnels_core_dir = $this->upload_dir . '/' . $this->core_dir;
$this->set_component( $component );
$this->makedirs();
self::$ins = 1;
}
public function set_component( $component ) {
if ( '' !== $component ) {
$this->component = $component;
}
}
public function get_component_dir() {
return $this->woofunnels_core_dir . '/' . $this->component;
}
public function touch( $file, $time = 0, $atime = 0 ) {
$file = $this->file_path( $file );
return parent::touch( $file, $time, $atime );
}
public function file_path( $file ) {
$file_path = $this->woofunnels_core_dir . '/' . $this->component . '/' . $file;
return $file_path;
}
public function folder_path( $folder_name ) {
$folder_path = $this->woofunnels_core_dir . '/' . $folder_name . '/';
return $folder_path;
}
public function is_readable( $file ) {
$file = $this->file_path( $file );
return parent::is_readable( $file );
}
public function is_writable( $file ) {
$file = $this->file_path( $file );
return parent::is_writable( $file );
}
public function put_contents( $file, $contents, $mode = false ) {
$file = $this->file_path( $file );
return parent::put_contents( $file, $contents, $mode );
}
public function delete_file( $file, $recursive = false, $type = 'f' ) {
$file = $this->file_path( $file );
return parent::delete( $file, $recursive, $type );
}
public function delete_all( $folder_name, $recursive = false ) {
$folder_path = $this->folder_path( $folder_name );
return parent::rmdir( $folder_path, $recursive );
}
/**
* Gets details for files in a directory or a specific file.
*
* @param string $path Path to directory or file.
* @param bool $include_hidden Optional. Whether to include details of hidden ("." prefixed) files.
* Default true.
* @param bool $recursive Optional. Whether to recursively include file details in nested directories.
* Default false.
*
* @return array|false {
* Array of files. False if unable to list directory contents.
*
* @type string $name Name of the file or directory.
* @type string $perms *nix representation of permissions.
* @type int $permsn Octal representation of permissions.
* @type string $owner Owner name or ID.
* @type int $size Size of file in bytes.
* @type int $lastmodunix Last modified unix timestamp.
* @type mixed $lastmod Last modified month (3 letter) and day (without leading 0).
* @type int $time Last modified time.
* @type string $type Type of resource. 'f' for file, 'd' for directory.
* @type mixed $files If a directory and $recursive is true, contains another array of files.
* }
* @since 2.5.0
*
*/
public function dirlist( $path, $include_hidden = true, $recursive = false ) {
if ( $this->is_file( $path ) ) {
$limit_file = basename( $path );
$path = dirname( $path );
} else {
$limit_file = false;
}
if ( ! $this->is_dir( $path ) ) {
return false;
}
$dir = dir( $path );
if ( ! $dir ) {
return false;
}
$ret = array();
while ( false !== ( $entry = $dir->read() ) ) {
$struc = array();
$struc['name'] = $entry;
if ( '.' == $struc['name'] || '..' == $struc['name'] ) {
continue;
}
if ( ! $include_hidden && '.' == $struc['name'][0] ) {
continue;
}
if ( $limit_file && $struc['name'] != $limit_file ) {
continue;
}
$struc['perms'] = $this->gethchmod( $path . '/' . $entry );
$struc['permsn'] = $this->getnumchmodfromh( $struc['perms'] );
$struc['number'] = false;
$struc['owner'] = $this->owner( $path . '/' . $entry );
$struc['group'] = $this->group( $path . '/' . $entry );
$struc['size'] = $this->size( $path . '/' . $entry );
$struc['lastmodunix'] = $this->mtime( $path . '/' . $entry );
$struc['lastmod'] = gmdate( 'M j', $struc['lastmodunix'] );
$struc['time'] = gmdate( 'h:i:s', $struc['lastmodunix'] );
$struc['type'] = $this->is_dir( $path . '/' . $entry ) ? 'd' : 'f';
if ( 'd' == $struc['type'] ) {
if ( $recursive ) {
$struc['files'] = $this->dirlist( $path . '/' . $struc['name'], $include_hidden, $recursive );
} else {
$struc['files'] = array();
}
}
$ret[ $struc['name'] ] = $struc;
}
$dir->close();
unset( $dir );
return $ret;
}
public function delete_folder( $folder_path, $recursive = false ) {
return parent::rmdir( $folder_path, $recursive );
}
public function exists( $file ) {
$file = $this->file_path( $file );
return parent::exists( $file );
}
public function get_contents( $file ) {
$file = $this->file_path( $file );
return parent::get_contents( $file );
}
public function makedirs() {
$component = $this->component;
if ( parent::is_writable( $this->upload_dir ) ) {
if ( false === $this->is_dir( $this->woofunnels_core_dir ) ) {
$this->mkdir( $this->woofunnels_core_dir );
$file_handle = @fopen( trailingslashit( $this->woofunnels_core_dir ) . '/.htaccess', 'w' ); // phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged, WordPress.WP.AlternativeFunctions.file_system_read_fopen
if ( $file_handle ) {
fwrite( $file_handle, 'deny from all' ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_read_fwrite
fclose( $file_handle ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_read_fclose
}
}
$dir = $this->woofunnels_core_dir . '/' . $component;
if ( false === $this->is_dir( $dir ) ) {
$this->mkdir( $dir );
}
}
}
}
}

View File

@@ -0,0 +1,88 @@
<?php
/**
* @author woofunnels
* @package WooFunnels
*/
if ( ! class_exists( 'WooFunnels_Funnel_Builder_Commons' ) ) {
#[AllowDynamicProperties]
class WooFunnels_Funnel_Builder_Commons {
protected static $instance;
/**
* WooFunnels_Cache constructor.
*/
public function __construct() {
add_action( 'manage_shop_order_posts_custom_column', array( $this, 'show_woofunnels_total_in_order_listings' ), 99, 2 );
/**
* this is specific for the case when HPOS is enabled.
*/
add_action( 'manage_woocommerce_page_wc-orders_custom_column', array( $this, 'show_woofunnels_total_in_order_listings' ), 99, 2 );
add_action( 'admin_init', function () {
if ( class_exists( 'WFOCU_Admin' ) ) {
remove_filter( 'woocommerce_get_formatted_order_total', array( WFOCU_Core()->admin, 'show_upsell_total_in_order_listings' ), 999, 2 );
}
if ( class_exists( 'WFOB_Admin' ) ) {
remove_filter( 'woocommerce_get_formatted_order_total', array( WFOB_Core()->admin, 'show_bump_total_in_order_listings' ), 9999, 2 );
}
} );
}
/**
* Creates an instance of the class
* @return WooFunnels_Funnel_Builder_Commons
*/
public static function get_instance() {
if ( null === self::$instance ) {
self::$instance = new self;
}
return self::$instance;
}
public function show_woofunnels_total_in_order_listings( $column_name, $post_id ) {
$total_woofunnels = 0;
$order = wc_get_order( $post_id );
$html = '';
if ( 'order_total' === $column_name ) {
$show_combined = true;
if ( class_exists( 'WFOCU_Admin' ) ) {
$result_in_order_currency = $order->get_meta( '_wfocu_upsell_amount_currency' );
if ( true === $show_combined && ! empty( $result_in_order_currency ) ) {
$total_woofunnels = $total_woofunnels + $result_in_order_currency;
}
}
if ( class_exists( 'WFOB_Admin' ) ) {
if ( true === $show_combined ) {
/**
* Check if bump accepted in order meta
*/
$bump_total = $order->get_meta( '_bump_purchase_item_total' );
if ( ! empty( $bump_total ) ) {
$total_woofunnels += $bump_total;
}
}
}
if ( ! empty( $total_woofunnels ) ) {
$html = '<br/>
<p style="font-size: 12px;"><em> ' . sprintf( esc_html__( 'FunnelKit: %s', 'woofunnels' ), wc_price( $total_woofunnels, array( 'currency' => get_option( 'woocommerce_currency' ) ) ) ) . '</em></p>'; // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch, WordPress.WP.I18n.MissingTranslatorsComment
}
}
echo $html; //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
}
}

View File

@@ -0,0 +1,696 @@
<?php
if ( ! class_exists( 'WooFunnels_License_check' ) ) {
#[AllowDynamicProperties]
class WooFunnels_License_check {
private $server_point = 'https://license.funnelkit.com/';
private $software_end_point = '';
private $update_end_point = '';
private $http = null;
private $license_data = array();
private $request_body = false;
private $request_args = array(
'timeout' => 30,
'sslverify' => false,
);
private $plugin_hash_key = '';
private $human_name = '';
private $version = '0.1.0';
private $name = '';
public $slug = '';
public $wp_override = null;
private $cache_key = '';
private $invalidate_cache = '';
private $default_keys = array(
'plugin_slug' => '',
'email' => '',
'license_key' => '',
'product_id' => '',
'api_key' => '',
'version' => '',
'activation_email' => '',
);
public function __construct( $hash_key = '', $data = array() ) {
$this->software_end_point = add_query_arg( array(
'wc-api' => 'am-software-api',
), $this->server_point );
$this->update_end_point = add_query_arg( array(
'wc-api' => 'upgrade-api',
), $this->server_point );
if ( '' !== $hash_key ) {
$this->set_hash( $hash_key );
}
if ( is_array( $data ) && count( $data ) > 0 ) {
$this->setup_data( $data );
}
$this->invalidate_cache = filter_input( INPUT_GET, 'bwf_clear_plugin_cache', FILTER_UNSAFE_RAW );
if ( 'yes' === $this->invalidate_cache ) {
delete_transient( 'update_plugins' );
delete_site_transient( 'update_plugins' );
}
WooFunnels_License_Controller::register_plugin( $hash_key, $this );
}
public function set_hash( $hash ) {
if ( '' !== $hash ) {
$this->plugin_hash_key = $hash;
}
}
public function setup_data( $data ) {
$default = array(
'plugin_slug' => '',
'plugin_name' => '',
'email' => '',
'license_key' => '',
'product_id' => '',
'api_key' => '',
'version' => '',
'activation_email' => '',
'platform' => $this->get_domain(),
'domain' => $this->get_domain(),
);
if ( isset( $data['email'] ) ) {
$data['activation_email'] = $data['email'];
}
if ( isset( $data['license_key'] ) ) {
$data['api_key'] = $data['license_key'];
}
$data['instance'] = $this->pass_instance();
$this->license_data = wp_parse_args( $data, $default );
}
public function get_domain() {
global $sitepress;
$domain = site_url();
if ( isset( $sitepress ) ) {
$default_language = $sitepress->get_default_language();
$domain = $sitepress->convert_url( $sitepress->get_wp_api()->get_home_url(), $default_language );
}
// Check if Polylang is active
if ( function_exists( 'pll_default_language' ) && function_exists( 'pll_home_url' ) ) {
// Get the default language
$default_language = pll_default_language();
// Get the home URL in the default language
$domain = pll_home_url( $default_language );
}
// Remove trailing slash if it exists
return rtrim( $domain, '/' );
}
public function pass_instance() {
$plugin = $this->get_hash();
$instances = self::get_plugins();
if ( is_array( $instances ) ) {
if ( isset( $instances[ $plugin ] ) && isset( $instances[ $plugin ]['instance'] ) && '' !== $instances[ $plugin ]['instance'] ) {
return $instances[ $plugin ]['instance'];
} else {
return md5( wp_generate_password( 12 ) );
}
}
return false;
}
public function get_hash() {
return $this->plugin_hash_key;
}
public static function get_plugins() {
return WooFunnels_License_Controller::get_plugins();
}
/**
* Find activated plugin license data using Encode basename of plugin
*
* @param $basename
*
* @return [] |null
*/
public static function find_licence_data_using_basename( $basename ) {
if ( is_multisite() ) {
$active_plugins = get_site_option( 'active_sitewide_plugins', array() );
if ( is_array( $active_plugins ) && ( in_array( $basename, apply_filters( 'active_plugins', $active_plugins ), true ) || array_key_exists( $basename, apply_filters( 'active_plugins', $active_plugins ) ) ) ) {
$activated_licences = get_blog_option( get_network()->site_id, 'woofunnels_plugins_info', [] );
} else {
$activated_licences = get_option( 'woofunnels_plugins_info', [] );
}
} else {
$activated_licences = get_option( 'woofunnels_plugins_info', [] );
}
if ( empty( $activated_licences ) ) {
return null;
}
if ( isset( $activated_licences[ $basename ] ) ) {
return $activated_licences[ $basename ];
}
return null;
}
public function start_updater() {
$data = $this->get_data();
$this->version = $data['version'];
$this->name = $data['plugin_slug'];
$this->human_name = $data['plugin_name'];
$this->slug = str_replace( '.php', '', basename( $data['plugin_slug'] ) );
$this->wp_override = false;
$this->cache_key = md5( maybe_serialize( $this->slug ) );
add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_update' ) );
add_filter( 'plugins_api', array( $this, 'plugins_api_filter' ), 999, 3 );
}
public function get_data() {
return count( $this->license_data ) > 0 ? $this->license_data : $this->default_keys;
}
/**
* preform here license check for all installed plugin
*/
public function woofunnels_license_check() {
$plugins = $this->get_plugins();
$all_status = array();
if ( is_array( $plugins ) && count( $plugins ) > 0 ) {
foreach ( $plugins as $slug => $plugin ) {
$api_data = array(
'plugin_slug' => $slug,
'email' => $plugin['data_extra']['license_email'],
'license_key' => $plugin['data_extra']['api_key'],
'product_id' => $plugin['data_extra']['software_title'],
'version' => '0.1.0',
);
$this->setup_data( $api_data );
}
}
return $all_status;
}
public function license_status() {
//do nothing here as the login moved to License Controller class to batch this request
}
public function activate_license() {
$parse_data = $this->get_data();
$parse_data['request'] = 'activation';
$end_point_url = add_query_arg( $parse_data, $this->software_end_point );
$this->request_body = $this->http()->get( $end_point_url, $this->request_args );
$output = $this->build_output();
if ( false !== $output ) {
$this->save_license( $output );
}
WooFunnels_Process::get_instance()->maybe_clear_plugin_update_transients();
return $output;
}
public function http() {
if ( is_null( $this->http ) ) {
$this->http = new WP_Http();
}
return $this->http;
}
private function build_output( $is_serialize = false ) {
$output = $this->request_body;
if ( ! is_wp_error( $output ) ) {
$body = $output['body'];
if ( '' !== $body ) {
if ( false === $is_serialize ) {
$body = json_decode( $body, true );
if ( $body ) {
return $body;
}
} else {
$object = maybe_unserialize( $body );
if ( is_object( $object ) && count( get_object_vars( $object ) ) > 0 ) {
return $object;
}
return false;
}
}
}
return false;
}
/**
* Save plugin activation data in database
*
* @param $license_data
*/
private function save_license( $license_data ) {
if ( ! empty( $license_data ) && isset( $license_data['activated'] ) && 1 == $license_data['activated'] ) {
$slug = $this->get_hash();
if ( '' !== $slug ) {
$plugin_info = self::get_plugins();
$plugin_info[ $slug ] = $license_data;
$this->update_plugins( $plugin_info );
}
}
}
public static function update_plugins( $data ) {
WooFunnels_License_Controller::update_plugins( $data );
do_action( 'funnelkit_license_update' );
}
public function deactivate_license() {
$parse_data = $this->get_data();
$parse_data['request'] = 'deactivation';
$end_point_url = add_query_arg( $parse_data, $this->software_end_point );
$this->request_body = $this->http()->get( $end_point_url, $this->request_args );
$ouput = $this->build_output();
if ( is_array( $ouput ) && isset( $ouput['code'] ) && 100 === absint( $ouput['code'] ) ) {
/**
* removed plugin license info data form db if license key not found on server and api return code 100
*/
$this->removed_plugin_info_data();
} else if ( false !== $ouput ) {
$this->mark_license_deactiavted_manually();
}
return $this->build_output();
}
/**
*remove plugin license from database
*/
private function remove_license() {
$slug = $this->get_hash();
if ( '' !== $slug ) {
$plugin_info = self::get_plugins();
if ( isset( $plugin_info[ $slug ] ) ) {
unset( $plugin_info[ $slug ] );
$this->update_plugins( $plugin_info );
}
}
}
/**
*remove plugin license from database
*/
private function invalidate_license() {
$slug = $this->get_hash();
if ( '' !== $slug ) {
$plugin_info = self::get_plugins();
if ( isset( $plugin_info[ $slug ] ) ) {
unset( $plugin_info[ $slug ] );
$this->update_plugins( $plugin_info );
}
}
}
public function handle_license_check_response( $output ) {
if ( false !== $output ) {
/**
* $output['status_check']
* 1 == active and valid
* 2 == expired
* 3 == trial ended
* 0 == invalid
*/
if ( $output['status_check'] && 3 === absint( $output['status_check'] ) ) {
/**
* Trial license came with the info that trial ends and user did not renew the license
* Here we need to mark the data so that plugin gets abandoned.
*/
$this->remove_license();
} elseif ( 2 === absint( $output['status_check'] ) ) {
$this->mark_license_expired();
} elseif ( 0 === absint( $output['status_check'] ) ) {
$this->mark_license_invalid();
} else {
$this->mark_license_active();
}
if ( isset( $output['data_extra'] ) && is_array( $output['data_extra'] ) ) {
$this->update_data( $output["data_extra"] );
}
if ( 'active' === $output['status_check'] ) {
$activation_domain = $output['status_extra']['activation_domain'];
$activation_domain = str_replace( [ 'https://', 'http://' ], '', $activation_domain );
$activation_domain = trim( $activation_domain, '/' );
if ( strpos( $this->get_domain(), $activation_domain ) === false ) {
$this->mark_license_deactiavted_manually();
}
}
}
}
private function mark_license_expired() {
$slug = $this->get_hash();
if ( '' !== $slug ) {
$plugin_info = self::get_plugins();
if ( isset( $plugin_info[ $slug ] ) ) {
unset( $plugin_info[ $slug ]["manually_deactivated"] );
$plugin_info[ $slug ]["expired"] = 1;
$this->update_plugins( $plugin_info );
do_action( 'fk_license_expired', $plugin_info, $slug );
}
}
}
private function mark_license_invalid() {
$slug = $this->get_hash();
if ( '' !== $slug ) {
$plugin_info = self::get_plugins();
if ( isset( $plugin_info[ $slug ] ) ) {
unset( $plugin_info[ $slug ]["manually_deactivated"] );
$plugin_info[ $slug ]["activated"] = 0;
$plugin_info[ $slug ]["expired"] = 0;
$this->update_plugins( $plugin_info );
}
}
}
/**
* @return void
*/
private function removed_plugin_info_data() {
$slug = $this->get_hash();
if ( '' !== $slug ) {
$plugin_info = self::get_plugins();
if ( isset( $plugin_info[ $slug ] ) ) {
unset( $plugin_info[ $slug ] );
$this->update_plugins( $plugin_info );
}
}
}
private function mark_license_deactiavted_manually() {
$slug = $this->get_hash();
if ( '' !== $slug ) {
$plugin_info = self::get_plugins();
if ( isset( $plugin_info[ $slug ] ) ) {
$plugin_info[ $slug ]["activated"] = 0;
$plugin_info[ $slug ]["expired"] = 0;
$plugin_info[ $slug ]["manually_deactivated"] = 1;
$this->update_plugins( $plugin_info );
}
}
}
private function mark_license_active() {
$slug = $this->get_hash();
if ( '' !== $slug ) {
$plugin_info = self::get_plugins();
if ( isset( $plugin_info[ $slug ] ) ) {
$plugin_info[ $slug ]["activated"] = 1;
$plugin_info[ $slug ]["expired"] = 0;
unset( $plugin_info[ $slug ]["manually_deactivated"] );
$this->update_plugins( $plugin_info );
}
}
}
public function update_data( $output_data_extra ) {
$slug = $this->get_hash();
if ( '' !== $slug ) {
$plugin_info = self::get_plugins();
if ( isset( $plugin_info[ $slug ] ) ) {
$plugin_info[ $slug ]["data_extra"] = $output_data_extra;
$this->update_plugins( $plugin_info );
}
}
}
public function check_plugin_info() {
$parse_data = $this->get_data();
$parse_data['request'] = 'pluginupdatecheck';
$end_point_url = add_query_arg( $parse_data, $this->update_end_point );
$this->request_body = $this->http()->get( $end_point_url, $this->request_args );
return $this->build_output( true );
}
public function check_update( $_transient_data ) {
global $pagenow;
if ( ! is_object( $_transient_data ) ) {
$_transient_data = new stdClass;
}
if ( ! empty( $_transient_data->response ) && ! empty( $_transient_data->response[ $this->name ] ) && false === $this->wp_override ) {
return $_transient_data;
}
$version_info = $this->get_cached_version_info();
/**
* if we ever have the info blank it means we do not have any reponse
*/
if ( is_array( $version_info ) && count( $version_info ) === 0 ) {
return $_transient_data;
}
if ( 'yes' === $this->invalidate_cache || false === $version_info ) {
$output = $this->check_update_info();
/**
* if we found update info as blank array then set the cache as blank and return from here
*/
if ( is_array( $output ) && count( $output ) === 0 ) {
$this->set_version_info_cache( $output );
return $_transient_data;
}
/**
* validate a valid output
*/
if ( false !== $output ) {
$output->slug = str_replace( '.php', '', basename( $this->slug ) );
$version_info = $output;
$version_info->plugin = $this->name;
$this->set_version_info_cache( $version_info );
}
}
if ( ! is_object( $version_info ) ) {
return $_transient_data;
}
if ( false !== $version_info && is_object( $version_info ) && isset( $version_info->version ) ) {
if ( version_compare( $this->version, $version_info->version, '<' ) ) {
$_transient_data->response[ $this->name ] = $version_info;
}
$_transient_data->last_checked = current_time( 'timestamp' );
$_transient_data->checked[ $this->name ] = $this->version;
}
return $_transient_data;
}
public function get_cached_version_info( $cache_key = '' ) {
if ( 'yes' === $this->invalidate_cache ) {
return false;
}
if ( empty( $cache_key ) ) {
$cache_key = "_bwf_version_cache_" . $this->cache_key;
}
$cache = get_option( $cache_key );
if ( empty( $cache['timeout'] ) || current_time( 'timestamp' ) > $cache['timeout'] ) {
delete_option( $cache_key );
return false; // Cache is expired
}
return json_decode( $cache['value'] );
}
public function check_update_info() {
$output = WooFunnels_License_Controller::get_plugin_update_check( $this->get_hash() );
/**
* if we have blank array as output then return as it is
*/
if ( is_array( $output ) && count( $output ) === 0 ) {
return [];
}
if ( false !== $output ) {
/*
* IF any error from the API then return blank array
*/
if ( isset( $output->errors ) ) {
return [];
}
/**
* BY this level we can be sure that we have the api response
* check for any new available version
*/
if ( version_compare( $this->version, $output['new_version'], '<' ) ) {
$parse_data = $this->get_data();
if ( ! empty( $parse_data['domain'] ) ) {
global $wpdb;
$db_domain = $wpdb->get_var( $wpdb->prepare( "SELECT option_value FROM $wpdb->options WHERE option_name = %s", 'siteurl' ) ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
if ( ! empty( $db_domain ) && $db_domain !== $parse_data['domain'] ) {
$parse_data['db_domain'] = rtrim( $db_domain, '/' );
}
}
$parse_data['request'] = 'plugininformation';
$end_point_url = add_query_arg( $parse_data, $this->update_end_point );
$this->request_body = $this->http()->get( $end_point_url, $this->request_args );
$out = $this->build_output( true );
if ( false !== $out ) {
$out->new_version = $output['new_version'];
$out->package = $output['package'];
$out->download_link = $output['package'];
$out->access_expires = $output['access_expires'];
return $out;
}
}
}
return [];
}
public function set_version_info_cache( $value = '', $cache_key = '' ) {
if ( empty( $cache_key ) ) {
$cache_key = "_bwf_version_cache_" . $this->cache_key;
}
$data = array(
'timeout' => strtotime( '+3 hours', current_time( 'timestamp' ) ),
'value' => wp_json_encode( $value ),
);
update_option( $cache_key, $data, 'no' );
}
/**
* Updates information on the "View version x.x details" page with custom data.
*
*
* @param mixed $_data
* @param string $_action
* @param object $_args
*
* @return object $_data
*/
public function plugins_api_filter( $_data, $_action = '', $_args = null ) {
if ( $_action !== 'plugin_information' ) {
return $_data;
}
if ( ! isset( $_args->slug ) || ( $_args->slug !== $this->slug ) ) {
return $_data;
}
$version_info = $this->get_cached_version_info();
/**
* if we ever have the info blank it means we do not have any reponse
*/
if ( is_array( $version_info ) && count( $version_info ) === 0 ) {
return $_data;
}
if ( false === $version_info ) {
$output = $this->check_update_info();
/**
* if we found update info as blank array then set the cache as blank and return from here
*/
if ( is_array( $output ) && count( $output ) === 0 ) {
$this->set_version_info_cache( $output );
return $_data;
}
if ( false !== $output ) {
$output->slug = str_replace( '.php', '', basename( $this->slug ) );
$_data = $output;
$_data->plugin = basename( $this->slug );
$this->set_version_info_cache( $_data );
}
} else {
$_data = $version_info;
}
// Convert sections into an associative array, since we're getting an object, but Core expects an array.
if ( isset( $_data->sections ) && ! is_array( $_data->sections ) ) {
$new_sections = array();
foreach ( $_data->sections as $key => $value ) {
$new_sections[ $key ] = $value;
}
$_data->sections = $new_sections;
}
// Convert banners into an associative array, since we're getting an object, but Core expects an array.
if ( isset( $_data->banners ) && ! is_array( $_data->banners ) ) {
$new_banners = array();
foreach ( $_data->banners as $key => $value ) {
$new_banners[ $key ] = $value;
}
$_data->banners = $new_banners;
}
return $_data;
}
/**
* Disable SSL verification in order to prevent download update failures
*
* @param array $args
* @param string $url
*
* @return $array
*/
public function http_request_args( $args, $url ) {
$verify_ssl = $this->verify_ssl();
if ( ! is_null( $url ) && ( strpos( $url, 'https://' ) !== false && strpos( $url, 'edd_action=package_download' ) ) ) {
$args['sslverify'] = $verify_ssl;
}
return $args;
}
/**
* Returns if the SSL of the store should be verified.
*
* @return bool
* @since 1.6.13
*/
private function verify_ssl() {
return (bool) apply_filters( 'edd_sl_api_request_verify_ssl', true, $this );
}
}
}

View File

@@ -0,0 +1,244 @@
<?php
if ( ! class_exists( 'WooFunnels_License_Controller' ) ) {
#[AllowDynamicProperties]
class WooFunnels_License_Controller {
/**
* @var WooFunnels_License_check[]
*/
public static $plugins = [];
/**
* @var WP_Http
*/
public static $http;
private static $server_point = 'https://license.funnelkit.com/';
private static $software_end_point = '';
private static $request_args = array(
'timeout' => 30,
'sslverify' => false,
);
private static $plugin_update_check_data;
private static $cached_site_url = null;
private $license_data = array();
private $request_body = false;
public static function register_plugin( $hash, $object ) {
if ( ! isset( self::$plugins[ $hash ] ) ) {
self::$plugins[ $hash ] = $object;
}
}
public static function get_all_plugins() {
return self::$plugins;
}
/**
* Get cached site URL to avoid duplicate database calls
* @return string|null
*/
private static function get_cached_site_url() {
if ( self::$cached_site_url === null ) {
global $wpdb;
self::$cached_site_url = $wpdb->get_var( $wpdb->prepare( "SELECT option_value FROM $wpdb->options WHERE option_name = %s", 'siteurl' ) ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
}
return self::$cached_site_url;
}
/**
* Run a batch request to check license status of all the plugin
* Then trigger handle license check response of child class so that they can process their data.
*/
public static function license_check() {
$parse_data = [];
$parse_data['plugins'] = [];
$plugins_to_send = [];
foreach ( self::$plugins as $hash => $plugin ) {
$data = $plugin->get_data();
if ( empty( $data['plugin_slug'] ) ) {
continue;
}
$parse_url = wp_parse_url( $data['domain'] );
/**
* prevent license check when domain is IP, it will help reducing domain mismatches
*/
if ( is_array( $parse_url ) && ! empty( $parse_url['host'] ) && ! empty( ip2long( $parse_url['host'] ) ) ) {
continue;
}
if ( ! empty( $data['domain'] ) ) {
$cached_site_url = self::get_cached_site_url();
if ( ! empty( $cached_site_url ) && $cached_site_url !== $data['domain'] ) {
$data['db_domain'] = rtrim( $cached_site_url, '/' );
}
}
$parse_data['plugins'][ $hash ] = $plugins_to_send[ $hash ] = $data;
}
$request = 'status_request_all';
$output = self::build_output( self::http()->post( self::get_software_endpoint( $request ), array_merge( [ 'body' => $parse_data ], self::$request_args ) ) );
if ( $output && is_array( $output ) && count( $output ) > 0 ) {
foreach ( $output as $hash => $output_plugin ) {
if ( isset( $plugins_to_send[ $hash ] ) ) {
self::$plugins[ $hash ]->handle_license_check_response( $output_plugin );
}
}
}
WooFunnels_Process::get_instance()->maybe_clear_plugin_update_transients();
}
private static function build_output( $response, $is_searilize = false ) {
if ( ! is_wp_error( $response ) ) {
$body = $response['body'];
if ( '' !== $body ) {
if ( false === $is_searilize ) {
$body = json_decode( $body, true );
if ( $body ) {
return $body;
}
} else {
$object = maybe_unserialize( $body );
if ( is_object( $object ) && count( get_object_vars( $object ) ) > 0 ) {
return $object;
}
return false;
}
}
}
return false;
}
public static function http() {
if ( is_null( self::$http ) ) {
self::$http = new WP_Http();
}
return self::$http;
}
public static function get_software_endpoint( $request = '' ) {
return add_query_arg( array(
'wc-api' => 'am-software-api',
'request' => $request,
), self::$server_point );
}
public static function get_plugin_update_check( $hash ) {
$get_data = self::license_update_check();
if ( ! isset( $get_data[ $hash ] ) ) {
return false;
}
return $get_data[ $hash ];
}
public static function license_update_check() {
if ( ! is_null( self::$plugin_update_check_data ) ) {
return self::$plugin_update_check_data;
}
$parse_data = [];
$parse_data['plugins'] = [];
$plugins_to_send = [];
$prepare_dummy = [];
foreach ( self::$plugins as $hash => $plugin ) {
$data = $plugin->get_data();
if ( empty( $data['plugin_slug'] ) ) {
continue;
}
if ( ! empty( $data['domain'] ) ) {
$cached_site_url = self::get_cached_site_url();
if ( ! empty( $cached_site_url ) && $cached_site_url !== $data['domain'] ) {
$data['db_domain'] = rtrim( $cached_site_url, '/' );
}
}
$parse_data['plugins'][ $hash ] = $plugins_to_send[ $hash ] = $data;
$prepare_dummy[ $hash ] = [];
}
$request = 'pluginupdatecheckall';
$output = self::build_output( self::http()->post( self::get_update_endpoint( $request ), array_merge( [ 'body' => $parse_data ], self::$request_args ) ) );
if ( $output ) {
self::$plugin_update_check_data = $output;
} else {
$output = $prepare_dummy;
self::$plugin_update_check_data = $output;
}
return $output;
}
public static function get_update_endpoint( $request = '' ) {
return add_query_arg( array(
'wc-api' => 'upgrade-api',
'request' => $request,
), self::$server_point );
}
public static function get_plugins() {
if ( is_multisite() ) {
$plugin_config = WooFunnel_Loader::get_the_latest();
$active_plugins = get_site_option( 'active_sitewide_plugins', array() );
if ( is_array( $active_plugins ) && is_array( $plugin_config ) && count( $plugin_config ) > 0 && ( in_array( $plugin_config['basename'], apply_filters( 'active_plugins', $active_plugins ), true ) || array_key_exists( $plugin_config['basename'], apply_filters( 'active_plugins', $active_plugins ) ) ) ) {
return get_blog_option( get_network()->site_id, 'woofunnels_plugins_info', [] );
} else {
return is_array( get_option( 'woofunnels_plugins_info', [] ) ) ? get_option( 'woofunnels_plugins_info', [] ) : [];
}
}
return is_array( get_option( 'woofunnels_plugins_info', [] ) ) ? get_option( 'woofunnels_plugins_info', [] ) : [];
}
public static function update_plugins( $data ) {
update_option( 'woofunnels_plugins_info', $data, 'yes' );
}
public static function get_basename_by_key( $hash ) {
if ( ! isset( self::$plugins[ $hash ] ) ) {
return __return_empty_string();
}
$data = self::$plugins[ $hash ]->get_data();
return $data['plugin_slug'];
}
/**
* Callback method to run license check manually
* @return void
*/
public static function license_check_api_call_init() {
try {
$check_transient = get_transient( 'fk_license_check_api_call_init' );
if ( ! empty( $check_transient ) ) {
wp_send_json( array( 'status' => 'failure', 'message' => 'lock exists' ) );
}
self::license_check();
set_transient( 'fk_license_check_api_call_init', 1, HOUR_IN_SECONDS );
$plugins = self::get_all_plugins();
wp_send_json( array( 'status' => 'success', 'message' => 'License check initiated', 'is_pro' => count( $plugins ) > 0 ? true : false ) );
} catch ( Exception|Error $e ) {
wp_send_json( array( 'status' => 'failure', 'message' => $e->getMessage() ) );
}
}
}
}

View File

@@ -0,0 +1,186 @@
<?php
if ( ! class_exists( 'WooFunnels_Licenses' ) ) {
/**
* Plugin licenses data class / we do not handle license activation and deactivation at this class
*
* @author woofunnels
* @package WooFunnels
*/
#[AllowDynamicProperties]
class WooFunnels_Licenses {
protected static $instance;
public $plugins_list;
public function __construct() {
//calling appropriate hooks by identifying the request
$this->maybe_submit();
$this->maybe_deactivate();
add_action( 'admin_notices', array( $this, 'maybe_show_invalid_license_error' ) );
}
/**
* Pass to submission
*/
public function maybe_submit() {
if ( isset( $_POST['_wpnonce'] ) && wp_verify_nonce( bwf_clean( $_POST['_wpnonce'] ), 'woofunnels-activate-license' ) ) {
if ( isset( $_POST['action'] ) && $_POST['action'] === 'woofunnels_activate-products' ) {
do_action( 'woofunnels_licenses_submitted', $_POST );
}
}
}
/**
* Pass to deactivate hook
*/
public function maybe_deactivate() {
if ( isset( $_GET['_wpnonce'] ) && wp_verify_nonce( bwf_clean( $_GET['_wpnonce'] ), 'bwf-deactivate-product' ) ) {
if ( isset( $_GET['action'] ) && 'woofunnels_deactivate-product' === sanitize_text_field( $_GET['action'] ) ) {
do_action( 'woofunnels_deactivate_request', $_GET );
}
}
}
/**
* Creates and instance of the class
* @return WooFunnels_licenses
*/
public static function get_instance() {
if ( null === self::$instance ) {
self::$instance = new self;
}
return self::$instance;
}
public function maybe_show_invalid_license_error() {
$get_plugins_data = $this->get_data();
if ( ! is_array( $get_plugins_data ) ) {
return;
}
if ( empty( $get_plugins_data ) ) {
return;
}
$plugins_need_license_woofunnels = $this->get_data( 'woofunnels' );
$plugins_need_license_autonami = $this->get_data( 'autonami' );
$plugins_need_license_woofunnels_titles = [];
$plugins_need_license_autonami_titles = [];
foreach ( $plugins_need_license_woofunnels as $plugin_data ) {
if ( 'active' !== $plugin_data['product_status'] || $this->is_expired( $plugin_data ) || $this->is_disabled( $plugin_data ) ) {
array_push( $plugins_need_license_woofunnels_titles, $plugin_data['plugin'] );
}
}
foreach ( $plugins_need_license_autonami as $plugin_data ) {
if ( 'active' !== $plugin_data['product_status'] || $this->is_expired( $plugin_data ) || $this->is_disabled( $plugin_data ) ) {
array_push( $plugins_need_license_autonami_titles, $plugin_data['plugin'] );
}
}
if ( ! empty( $plugins_need_license_woofunnels_titles ) ) {
$this->show_invalid_license_notice( $plugins_need_license_woofunnels_titles, 'woofunnels' );
}
if ( ! empty( $plugins_need_license_autonami_titles ) ) {
$this->show_invalid_license_notice( $plugins_need_license_autonami_titles, 'autonami' );
}
}
public function get_data( $type = 'all' ) {
if ( is_null( $this->plugins_list ) ) {
$this->get_plugins_list();
}
if ( 'all' === $type ) {
return $this->plugins_list;
}
if ( 'autonami' === $type || 'woofunnels' === $type ) {
$plugins_autonami = [];
$plugins_woofunnels = $this->plugins_list;
if ( is_array( $this->plugins_list ) && count( $this->plugins_list ) ) {
foreach ( $this->plugins_list as $key => $license ) {
if ( ! is_null( $license['plugin'] ) && false !== strpos( $license['plugin'], 'Automations' ) ) {
$plugins_autonami[ $key ] = $license;
unset( $plugins_woofunnels[ $key ] );
}
}
}
return ( 'autonami' === $type ) ? $plugins_autonami : $plugins_woofunnels;
}
}
public function get_plugins_list() {
$this->plugins_list = apply_filters( 'woofunnels_plugins_license_needed', array() );
$get_all_plugins_data = WooFunnels_License_Controller::get_plugins();
foreach ( array_keys( $this->plugins_list ) as $key ) {
if ( false === array_key_exists( $key, $get_all_plugins_data ) ) {
continue;
}
$this->plugins_list[ $key ]['_data'] = $get_all_plugins_data[ $key ];
}
}
public function is_expired( $license_data ) {
if ( isset( $license_data['_data'] ) && isset( $license_data['_data']['expired'] ) && ! empty( $license_data['_data']['expired'] ) ) {
return true;
}
return false;
}
public function is_disabled( $license_data ) {
if ( empty( $license_data['_data']['activated'] ) ) {
return true;
}
return false;
}
public function show_invalid_license_notice( $plugins, $type ) {
?>
<div class="bwf-notice notice error">
<p>
<?php
echo sprintf( __( '<strong>Invalid License Key: </strong> You are <i>not receiving</i> Latest Updates, New Features, Security Updates &amp; Bug Fixes for <strong>%1$s</strong>. <a href="%2$s">Click Here To Fix This</a>.', 'buildwoofunnels' ), implode( ', ', $plugins ), $this->license_url( $type ) ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.I18n.MissingTranslatorsComment, WordPress.WP.I18n.TextDomainMismatch
?>
</p>
</div>
<?php
}
public function license_url( $type ) {
if ( $type === 'woofunnels' && defined( 'WFFN_VERSION' ) ) {
return admin_url( '/admin.php?page=bwf&path=/settings/woofunnels_general_settings' );
} elseif ( $type === 'autonami' && defined( 'BWFAN_VERSION' ) && version_compare( BWFAN_VERSION, '2.0', '>=' ) ) {
return admin_url( '/admin.php?page=autonami&path=%2Fsettings' );
} else {
return admin_url( 'admin.php?page=woofunnels&tab=licenses' );
}
}
public function get_secret_license_key( $key ) {
$last_six = substr( $key, - 6 );
$initial_string = str_replace( $last_six, '', $key );
$initial_string_length = strlen( $initial_string );
$final_string = str_repeat( 'x', $initial_string_length ) . $last_six;
return $final_string;
}
}
}

View File

@@ -0,0 +1,470 @@
<?php
defined( 'ABSPATH' ) || exit;
if ( ! class_exists( 'WooFunnels_Notifications' ) ) {
#[AllowDynamicProperties]
class WooFunnels_Notifications {
private static $instance = null;
/** Notification listed array */
protected $notifications_list = [];
public function __construct() {
/** Inline styling for woofunnels notifications */
add_action( 'admin_head', [ $this, 'notification_inline_style' ] );
/** Inline javascript for woofunnels notifications */
add_action( 'admin_footer', [ $this, 'notification_inline_script' ] );
/** Ajax function dismiss to woofunnels notifications */
add_action( 'wp_ajax_wf_dismiss_link', array( $this, 'wf_dismiss_link' ) );
}
/**
* Instance of class
* @return WooFunnels_Notifications|null
*/
public static function get_instance() {
if ( is_null( self::$instance ) ) {
self::$instance = new WooFunnels_Notifications();
}
return self::$instance;
}
/**
* This will return all the notifications or the notifications based on the group id.
*
* @param string $notification_group Optional
*
* @return array
*/
public function get_all_notifications( $notification_group = '' ) {
if ( '' !== $notification_group && isset( $this->notifications_list[ $notification_group ] ) && ( is_array( $this->notifications_list[ $notification_group ] ) && count( $this->notifications_list[ $notification_group ] ) > 0 ) ) {
$notification_group_arr = [];
$notification_group_arr[ $notification_group ] = $this->notifications_list[ $notification_group ];
return $notification_group_arr;
}
return $this->notifications_list;
}
/**
* This is used to register a notification
*
* @param array $notification_value
* @param string $group
*
* @return array
*/
public function register_notification( $notification_value = [], $group = '' ) {
$error = [
'error' => 'Notification not register checkout your notification array or group name ',
];
if ( ( ! is_array( $notification_value ) || sizeof( $notification_value ) >= 2 ) || '' === $group ) {
$error['error'] = 'Check Your notification array format or notification group name';
return $error;
}
if ( ! is_array( $notification_value ) || count( $notification_value ) === 0 ) {
return $error;
}
$notice_key = key( $notification_value );
if ( isset( $this->notifications_list[ $group ][ $notice_key ] ) ) {
return $error;
}
$this->notifications_list[ $group ][ $notice_key ] = $notification_value[ $notice_key ];
return [
'success' => $notice_key . ' Key Set',
];
}
/**
* This is used to deregister a notification based on notification key and group
*
* @param string $notification_key
* @param string $notification_group
*
* @return array
*/
public function deregister_notification( $notification_key = '', $notification_group = '' ) {
$error = [
'error' => $notification_key . ' Key or notification group may be not Available.',
];
if ( '' === $notification_key || '' === $notification_group ) {
$error['error'] = 'Check your notification key and their group. Both are required for deletion';
return $error;
}
if ( ! isset( $this->notifications_list[ $notification_group ][ $notification_key ] ) || ! is_array( $this->notifications_list[ $notification_group ][ $notification_key ] ) || count( $this->notifications_list[ $notification_group ][ $notification_key ] ) === 0 ) {
return $error;
}
unset( $this->notifications_list[ $notification_group ][ $notification_key ] );
return [
'success' => $notification_key . ' Notices has been removed',
];
}
/**
* Display internal CSS
*/
public function notification_inline_style() {
?>
<style>
.notice.notice-error.wf_notice_cache_wrap {
position: relative;
overflow: hidden;
}
.wf_notice_cache_wrap a::before {
position: relative;
top: 18px;
left: -20px;
-webkit-transition: all .1s ease-in-out;
transition: all .1s ease-in-out;
}
.wf_notice_cache_wrap a.notice-dismiss {
position: static;
float: right;
top: 0;
right: 0;
padding: 0 15px 10px 28px;
margin-top: -10px;
font-size: 13px;
line-height: 1.23076923;
text-decoration: none;
}
/* cache setting */
.wf_notification_list_wrap h3.hndle {
text-align: left;
}
.wf_notification_wrap .swal2-icon.swal2-warning {
font-size: 6px;
line-height: 33px;
}
.wf_notification_content_sec p {
font-size: 14px;
line-height: 1.5;
position: relative;
padding-left: 20px;
margin-bottom: 11px;
}
.wf_notification_links a {
font-size: 15px;
font-weight: 100;
line-height: 1.5;
}
.wf_notification_wrap .wf_notification_btn_wrap a:hover {
background: #fafafa;
border-color: #999;
color: #23282d;
}
.wf_notification_wrap .inside {
padding: 0px 15px 30px;
}
.wf_notification_btn_wrap {
margin-bottom: 10px;
}
.wf_overlay_active {
z-index: 1;
position: absolute;
left: 0;
right: 0;
bottom: 0;
background: #ffffff5e;
top: 0;
display: none;
}
.wf_overlay_active.wf_show {
display: block;
}
.wf_notification_wrap a.notice-dismiss {
bottom: auto;
top: auto;
position: relative;
float: none;
right: 0;
padding: 0;
margin-top: 0;
font-size: 13px;
line-height: 20px;
text-decoration: none;
height: 20px;
display: inline-block;
margin-left: 20px;
}
.wf_notice_dismiss_link_wrap {
text-align: center;
}
.wf_notification_wrap a.notice-dismiss:before {
position: absolute;
top: 0px;
left: -20px;
-webkit-transition: all .1s ease-in-out;
transition: all .1s ease-in-out;
}
.wf_notification_content_sec:last-child {
margin-bottom: 0;
}
.wf_notification_content_sec {
margin-bottom: 30px;
position: relative;
}
.wf_notification_wrap.closed a.notice-dismiss {
display: none;
}
.wf_notification_wrap .wf_notification_btn_wrap a:last-child {
margin-bottom: 0;
}
.wf_notification_wrap .wf_notification_btn_wrap a {
color: #555;
border-color: #cccccc;
background: #f7f7f7;
box-shadow: 0 1px 0 #cccccc;
vertical-align: top;
display: block;
text-decoration: none;
font-size: 15px;
line-height: 20px;
padding: 8px 10px;
cursor: pointer;
margin: 0 0 11px;
border-width: 1px;
border-style: solid;
-webkit-appearance: none;
border-radius: 3px;
white-space: nowrap;
box-sizing: border-box;
text-align: center;
}
.wf_notification_wrap a.notice-dismiss + span {
display: block;
margin-top: 2px;
font-size: 14px;
line-height: 20px;
text-transform: capitalize;
}
.wf_notification_content_sec .wf_notification_html p:first-child:before {
width: 10px;
content: '';
height: 10px;
background: red;
position: absolute;
left: 0;
border-radius: 50%;
top: 6px;
}
.wf_notification_content_sec.wf_warning .wf_notification_html p:first-child:before {
background-color: orange;
}
.wf_notification_content_sec.wf_success .wf_notification_html > p:first-child:before {
background-color: green;
}
.wf_notification_content_sec.wf_error .wf_notification_html > p:first-child:before {
background-color: red;
}
.wf_notification_links a {
font-size: 15px;
font-weight: 100;
line-height: 1.5;
}
</style>
<?php
}
/**
* Display internal scripts
*/
public function notification_inline_script() {
?>
<script>
(function ($) {
function wf_dismiss_notice() {
jQuery(document).on('click', '.wf_notice_dismiss_link_wrap .notice-dismiss', function (e) {
var $this = jQuery(this);
var noticeGroup = $this.parents('.wf_notification_content_sec').attr('wf-noti-group');
var noticekey = $this.parents('.wf_notification_content_sec').attr('wf-noti-key');
var wf_count = $this.attr('wf-notice-count');
$this.parents('.wf_notification_content_sec').find('.wf_overlay_active ').addClass('wf_show');
if (noticeGroup === '' && noticeGroup === '') {
return;
}
jQuery.ajax({
url: ajaxurl,
type: "POST",
data: {
action: 'wf_dismiss_link',
noticeGroup: noticeGroup,
noticekey: noticekey,
_nonce: '<?php echo wp_create_nonce( 'bwf_notice_dismiss' ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>',
},
success: function (result) {
if (result.status === 'success' && result.success === 'true') {
/** check if the right notification area has only 1 notification */
if (jQuery(".wf_notification_wrap .wf_notification_content_sec").length == 1) {
$this.parents('.wf_notification_list_wrap').remove();
return;
}
/** remove the self notification html after 500 ms delay */
setTimeout(function () {
$this.parents('.wf_notification_content_sec').remove();
}, 500);
} else {
$this.parents('.wf_notification_content_sec').find('.wf_overlay_active ').removeClass('wf_show');
jQuery(".wf_notice_dismiss_link_wrap").append("<span >" + result.msg + "</span >")
}
}
});
});
}
jQuery(document).ready(function () {
wf_dismiss_notice();
});
})(jQuery);
</script>
<?php
}
/**
* Dismiss the notification
*/
public function wf_dismiss_link() {
$results = array(
'status' => 'failed',
'success' => 'false',
'msg' => 'Problem With dismiss',
);
check_ajax_referer( 'bwf_notice_dismiss', '_nonce' );
if ( ( isset( $_POST['noticeGroup'] ) && $_POST['noticeGroup'] !== '' ) && ( isset( $_POST['noticekey'] ) && $_POST['noticekey'] !== '' ) ) {
$noticeGroup = sanitize_text_field( $_POST['noticeGroup'] );
$noticekey = str_replace( 'wf-', '', sanitize_text_field( $_POST['noticekey'] ) );
$notices_display = get_option( 'wf_notification_list_' . $noticeGroup, [] );
$notice = $this->get_notification( $noticekey, $noticeGroup );
if ( ! is_array( $notices_display ) ) {
unset( $notices_display );
$notices_display = [];
}
if ( is_array( $notice ) && count( $notice ) > 0 ) {
$notices_display[] = $noticekey;
update_option( 'wf_notification_list_' . $noticeGroup, $notices_display );
}
$results = array(
'status' => 'success',
'success' => 'true',
'msg' => $noticekey . ' Notification Deleted',
);
}
wp_send_json( $results );
}
/**
* This will return the notification based on notification key and the group id
*
* @param string $notification_key
* @param string $notification_group
*
* @return array
*/
public function get_notification( $notification_key = '', $notification_group = '' ) {
$error = [
'error' => $notification_key . ' Key or Notification group may be Not Available.',
];
if ( '' === $notification_key || '' === $notification_group ) {
$error['error'] = 'Check your Notification Key and Their group. Both are required';
}
if ( isset( $this->notifications_list[ $notification_group ][ $notification_key ] ) && is_array( $this->notifications_list[ $notification_group ][ $notification_key ] ) && count( $this->notifications_list[ $notification_group ][ $notification_key ] ) > 0 ) {
return $this->notifications_list[ $notification_group ][ $notification_key ];
}
return $error;
}
/**
* Return the updated dismiss notification keys
*
* @param $group
*
* @return array|mixed|void
*/
public function get_dismiss_notification_key( $group ) {
if ( '' === $group ) {
return [
'error' => 'Need to a notice group for update key',
];
}
$notices_display = get_option( 'wf_notification_list_' . $group, [] );
if ( ! is_array( $notices_display ) ) {
$notices_display = [];
}
return $notices_display;
}
/**
* Display the notifications HTML
*
* @param $notifications_list
*/
public function get_notification_html( $notifications_list ) {
include dirname( dirname( __FILE__ ) ) . '/views/woofunnels-notifications.php';
}
}
}

View File

@@ -0,0 +1,363 @@
<?php
/**
* OptIn manager class is to handle all scenarios occurs for opting the user
* @author: WooFunnels
* @since 0.0.1
* @package WooFunnels
*/
if ( ! class_exists( 'WooFunnels_OptIn_Manager' ) ) {
#[AllowDynamicProperties]
class WooFunnels_OptIn_Manager {
public static $should_show_optin = true;
/**
* Initialization to execute several hooks
*/
public static function init() {
//push notification for optin
add_action( 'admin_init', array( __CLASS__, 'maybe_push_optin_notice' ), 15 );
add_action( 'admin_init', array( __CLASS__, 'maybe_clear_optin' ), 15 );
// track usage user callback
add_action( 'fk_fb_every_day', array( __CLASS__, 'maybe_track_usage' ), 10, 2 );
add_action( 'bwf_track_usage_scheduled_single', array( __CLASS__, 'maybe_track_usage' ), 10, 2 );
//initializing schedules
add_action( 'admin_footer', array( __CLASS__, 'initiate_schedules' ) );
// For testing license notices, uncomment this line to force checks on every page load
/** optin ajax call */
add_action( 'wp_ajax_woofunnelso_optin_call', array( __CLASS__, 'woofunnelso_optin_call' ) );
// optin yes track callback
add_action( 'woofunnels_optin_success_track_scheduled', array( __CLASS__, 'optin_track_usage' ), 10 );
add_filter( 'cron_schedules', array( __CLASS__, 'register_weekly_schedule' ), 10 );
}
/**
* Set function to block
*/
public static function block_optin() {
update_option( 'bwf_is_opted', 'no', true );
}
public static function maybe_clear_optin() {
if ( wp_verify_nonce( filter_input( INPUT_GET, '_nonce', FILTER_UNSAFE_RAW ), 'bwf_tools_action' ) && isset( $_GET['woofunnels_tracking'] ) && ( 'reset' === sanitize_text_field( $_GET['woofunnels_tracking'] ) ) ) {
self::reset_optin();
wp_safe_redirect( admin_url( 'admin.php?page=woofunnels&tab=tools' ) );
exit;
}
}
/**
* Reset optin
*/
public static function reset_optin() {
$get_action = filter_input( INPUT_GET, 'action', FILTER_UNSAFE_RAW );
if ( 'yes' === $get_action ) {
self::Allow_optin();
} else {
delete_option( 'bwf_is_opted' );
}
}
/**
* Set function to allow
*/
public static function Allow_optin( $pass_jit = false, $product = 'FB' ) {
if ( 'yes' === self::get_optIn_state() ) {
return;
}
if ( false !== wp_next_scheduled( 'bwf_track_usage_scheduled_single' ) ) {
wp_clear_scheduled_hook( 'bwf_track_usage_scheduled_single' );
}
if ( true === $pass_jit ) {
wp_schedule_single_event( current_time( 'timestamp' ), 'bwf_track_usage_scheduled_single', array( 'yes', $product ) );
} else {
wp_schedule_single_event( current_time( 'timestamp' ), 'bwf_track_usage_scheduled_single', array( false, $product ) );
}
update_option( 'bwf_is_opted', 'yes', true );
}
/**
* Collect some data and let the hook left for our other plugins to add some more info that can be tracked down
*
* @return array data to track
*/
public static function collect_data() {
global $wpdb, $woocommerce;
$installed_plugs = WooFunnels_addons::get_installed_plugins();
$active_plugins = get_option( 'active_plugins' );
$licenses = WooFunnels_licenses::get_instance()->get_data();
$theme = array();
$get_theme_info = wp_get_theme();
$theme['name'] = $get_theme_info->get( 'Name' );
$theme['uri'] = $get_theme_info->get( 'ThemeURI' );
$theme['version'] = $get_theme_info->get( 'Version' );
$theme['author'] = $get_theme_info->get( 'Author' );
$theme['author_uri'] = $get_theme_info->get( 'AuthorURI' );
$ref = get_option( 'woofunnels_optin_ref', '' );
$sections = array();
if ( class_exists( 'WooCommerce' ) ) {
$payment_gateways = WC()->payment_gateways->payment_gateways();
foreach ( $payment_gateways as $gateway_key => $gateway ) {
if ( 'yes' === $gateway->enabled ) {
$sections[] = esc_html( $gateway_key );
}
}
}
/** Product Count */
$product_count = array();
if ( class_exists( 'WooCommerce' ) ) {
$product_count_data = wp_count_posts( 'product' );
$product_count['total'] = property_exists( $product_count_data, 'publish' ) ? $product_count_data->publish : 0;
$product_statuses = get_terms( 'product_type', array( 'hide_empty' => 0 ) );
if ( is_array( $product_statuses ) && count( $product_statuses ) > 0 ) {
foreach ( $product_statuses as $product_status ) {
$product_count[ $product_status->name ] = $product_status->count;
}
}
}
/** Order Count */
$order_count = array();
if ( class_exists( 'WooCommerce' ) && function_exists( 'wc_orders_count' ) ) {
foreach ( wc_get_order_statuses() as $status_slug => $status_name ) {
$order_count[ $status_slug ] = wc_orders_count( $status_slug );
}
}
/** Base country slug */
$base_country = '';
if ( class_exists( 'WooCommerce' ) ) {
$base_country = get_option( 'woocommerce_default_country', false );
if ( ! empty( $base_country ) ) {
$base_country = substr( $base_country, 0, 2 );
}
}
$return = array(
'url' => home_url(),
'email' => get_option( 'admin_email' ),
'installed' => $installed_plugs,
'active_plugins' => $active_plugins,
'license_info' => $licenses,
'theme_info' => $theme,
'users_count' => self::get_user_counts(),
'locale' => get_locale(),
'is_mu' => is_multisite() ? 'yes' : 'no',
'wp' => get_bloginfo( 'version' ),
'php' => phpversion(),
'mysql' => $wpdb->db_version(),
'WooFunnels_version' => WooFunnel_Loader::$version,
'notification_ref' => $ref,
'date' => date( 'd.m.Y H:i:s' ),
'bwf_order_index_status' => get_option( '_bwf_db_upgrade', '0' ),
'bwf_version' => defined( 'BWF_VERSION' ) ? BWF_VERSION : '0.0.0',
);
if ( class_exists( 'WooCommerce' ) ) {
$return['country'] = $base_country;
$return['currency'] = get_woocommerce_currency();
$return['wc'] = $woocommerce->version;
$return['calc_taxes'] = get_option( 'woocommerce_calc_taxes' );
$return['guest_checkout'] = get_option( 'woocommerce_enable_guest_checkout' );
$return['product_count'] = $product_count;
$return['order_count'] = $order_count;
$return['wc_gateways'] = $sections;
}
return apply_filters( 'woofunnels_global_tracking_data', $return );
}
/**
* Get user totals based on user role.
* @return array
*/
private static function get_user_counts() {
$user_count = array();
$user_count_data = count_users();
$user_count['total'] = $user_count_data['total_users'];
// Get user count based on user role
foreach ( $user_count_data['avail_roles'] as $role => $count ) {
$user_count[ $role ] = $count;
}
return $user_count;
}
public static function update_optIn_referer( $referer ) {
update_option( 'woofunnels_optin_ref', $referer, false );
}
/**
* Checking the opt-in state and if we have scope for notification then push it
*/
public static function maybe_push_optin_notice() {
if ( self::get_optIn_state() === false && apply_filters( 'woofunnels_optin_notif_show', self::$should_show_optin ) ) {
do_action( 'bwf_maybe_push_optin_notice_state_action' );
}
}
/**
* Get current optin status from database
*
* @return mixed|void
*/
public static function get_optIn_state() {
return get_option( 'bwf_is_opted' );
}
/**
* Callback function to run on schedule hook
*/
public static function maybe_track_usage( $is_jit = false, $product = 'FB' ) {
//checking optin state
if ( true === self::is_optin_allowed() && 'yes' === self::get_optIn_state() ) {
$data = self::collect_data();
if ( $is_jit === 'yes' ) {
$data['jit'] = 'yes';
}
$data['product'] = $product;
//posting data to api
WooFunnels_API::post_tracking_data( $data );
}
}
/**
* Initiate schedules in order to start tracking data regularly.
*
*/
public static function initiate_schedules() {
// Run only in the admin dashboard
try {
if ( ! is_admin() ) {
return;
}
if ( ! current_user_can( 'administrator' ) ) {
return;
}
if ( ! wp_next_scheduled( 'fk_fb_every_day' ) ) {
wp_schedule_event( self::get_midnight_store_time(), 'daily', 'fk_fb_every_day' );
} else {
$scheduled_time = wp_next_scheduled( 'fk_fb_every_day' );
$midnight_time = self::get_midnight_store_time();
if ( $scheduled_time && abs( $scheduled_time - $midnight_time ) > 3600 ) {
do_action( 'fk_fb_every_day' );
wp_clear_scheduled_hook( 'fk_fb_every_day' );
}
}
$legacy_schedules = array(
'wfocu_schedule_mails_for_bacs_and_cheque',
'wfocu_schedule_pending_emails',
'wfocu_schedule_normalize_order_statuses',
'wfocu_schedule_thankyou_action',
'wfocu_remove_orphaned_transients',
'wffn_remove_orphaned_transients',
'bwf_maybe_track_usage_scheduled',
'woofunnels_license_check',
);
foreach ( $legacy_schedules as $schedule ) {
if ( strpos( $schedule, 'wfocu_' ) === 0 && ! wp_next_scheduled( 'fk_fb_every_4_minute' ) ) {
continue;
}
if ( wp_next_scheduled( $schedule ) ) {
wp_clear_scheduled_hook( $schedule );
}
}
} catch ( Exception $e ) {
}
}
/**
* @return int|void
*/
public static function get_midnight_store_time() {
try {
$timezone = new DateTimeZone( wp_timezone_string() );
$date = new DateTime();
$date->modify( '+1 days' );
$date->setTimezone( $timezone );
$date->setTime( 0, 0, 0 );
return $date->getTimestamp();
} catch ( Exception $e ) {
}
}
public static function is_optin_allowed() {
return apply_filters( 'buildwoofunnels_optin_allowed', true );
}
public static function woofunnelso_optin_call() {
check_ajax_referer( 'bwf_secure_key' );
if ( is_array( $_POST ) && count( $_POST ) > 0 ) {
$_POST['domain'] = home_url();
$_POST['ip'] = isset( $_SERVER['REMOTE_ADDR'] ) ? sanitize_text_field( $_SERVER['REMOTE_ADDR'] ) : '';
WooFunnels_API::post_optin_data( $_POST );
/** scheduling track call when success */
if ( isset( $_POST['status'] ) && 'yes' === sanitize_text_field( $_POST['status'] ) ) {
wp_schedule_single_event( time() + 2, 'woofunnels_optin_success_track_scheduled' );
}
}
wp_send_json( array(
'status' => 'success',
) );
exit;
}
/**
* Callback function to run on schedule hook
*/
public static function optin_track_usage() {
/** update week day for tracking */
$track_week_day = date( 'w' );
update_option( 'woofunnels_track_day', $track_week_day, false );
$data = self::collect_data();
//posting data to api
WooFunnels_API::post_tracking_data( $data );
}
public static function maybe_default_optin() {
return;
}
public static function register_weekly_schedule( $schedules ) {
$schedules['weekly_bwf'] = array(
'interval' => WEEK_IN_SECONDS,
'display' => __( 'Weekly BWF', 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
);
return $schedules;
}
}
// Initialization
WooFunnels_optIn_Manager::init();
}

View File

@@ -0,0 +1,744 @@
<?php
if ( ! class_exists( 'WooFunnels_Process' ) ) {
/**
* Basic process class that detect request and pass to respective class
*
* @author woofunnels
* @package WooFunnels
*/
#[AllowDynamicProperties]
class WooFunnels_Process {
private static $ins = null;
public $in_update_messages = array();
/**
* Initiate hooks
*/
public function __construct() {
add_action( 'admin_init', array( $this, 'parse_request_and_process' ), 14 );
add_filter( 'admin_notices', array( $this, 'maybe_show_advanced_update_notification' ), 999 );
add_action( 'admin_head', array( $this, 'register_in_update_plugin_message' ) );
add_action( 'fk_fb_every_day', array( 'WooFunnels_License_Controller', 'license_check' ) );
add_action( 'wp_ajax_nopriv_fk_init_license_request', array( 'WooFunnels_License_Controller', 'license_check_api_call_init' ) );
add_action( 'funnelkit_license_update', array( $this, 'maybe_clear_plugin_update_transients' ) );
add_action( 'funnelkit_delete_transients', array( $this, 'maybe_clear_plugin_update_transients' ) );
add_action( 'woocommerce_thankyou', array( $this, 'fire_thankyou_ajax' ), 10 );
add_action( 'wp_ajax_bwf_thankyou_ajax', array( $this, 'handle_thankyou_ajax' ), 10 );
add_action( 'wp_ajax_nopriv_bwf_thankyou_ajax', array( $this, 'handle_thankyou_ajax' ), 10 );
add_action( 'admin_init', array( $this, 'maybe_set_options_auto_loading_false' ) );
add_action( 'admin_head', array( $this, 'maybe_swap_order_to_make_it_correct' ), - 2 );
add_action( 'admin_head', array( $this, 'maybe_correct_submenu_order' ), - 1 );
add_action( 'admin_head', array( $this, 'correct_sub_menu_order' ), 999 );
add_action( 'admin_head', array( $this, 'correct_sub_menu_order_legacy' ), 999 );
add_action( 'admin_init', array( $this, 'hide_plugins_update_notices' ) );
add_action( 'admin_footer', array( $this, 'print_css' ), 9999 );
}
public static function get_instance() {
if ( self::$ins === null ) {
self::$ins = new self;
}
return self::$ins;
}
public function parse_request_and_process() {
//Initiating the license instance to handle submissions (submission can redirect page two that can cause "header already sent" issue to be arised)
// Initiating this to over come that issue
if ( 'woofunnels' === filter_input( INPUT_GET, 'page', FILTER_UNSAFE_RAW ) && 'licenses' === filter_input( INPUT_GET, 'tab', FILTER_UNSAFE_RAW ) ) {
WooFunnels_licenses::get_instance();
}
//Handling Optin
if ( isset( $_GET['woofunnels-optin-choice'] ) && isset( $_GET['_woofunnels_optin_nonce'] ) ) {
if ( ! wp_verify_nonce( sanitize_text_field( $_GET['_woofunnels_optin_nonce'] ), 'woofunnels_optin_nonce' ) ) {
wp_die( esc_html__( 'Action failed. Please refresh the page and retry.', 'woofunnels' ) ); // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
}
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( esc_html__( 'Cheating huh?', 'woofunnels' ) ); // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
}
$optin_choice = sanitize_text_field( $_GET['woofunnels-optin-choice'] );
if ( $optin_choice === 'yes' ) {
WooFunnels_optIn_Manager::Allow_optin();
if ( isset( $_GET['ref'] ) ) {
WooFunnels_optIn_Manager::update_optIn_referer( filter_input( INPUT_GET, 'ref', FILTER_UNSAFE_RAW ) );
}
} else {
WooFunnels_optIn_Manager::block_optin();
}
do_action( 'woofunnels_after_optin_choice', $optin_choice );
}
//Initiating the license instance to handle submissions (submission can redirect page two that can cause "header already sent" issue to be arised)
// Initiating this to over come that issue
if ( isset( $_GET['page'] ) && 'woofunnels' === sanitize_text_field( $_GET['page'] ) && isset( $_GET['tab'] ) && 'support' === sanitize_text_field( $_GET['tab'] ) && isset( $_POST['woofunnels_submit_support'] ) ) {
$instance_support = WooFunnels_Support::get_instance();
if ( filter_input( INPUT_POST, 'choose_addon', true ) === '' || filter_input( INPUT_POST, 'comments', true ) === '' ) {
$instance_support->validation = false;
}
}
}
public function maybe_show_advanced_update_notification() {
$screen = get_current_screen();
$plugins_installed = WooFunnels_Addons::get_installed_plugins();
$hide_notice = get_option( 'woofunnel_hide_update_notice', 'no' );
if ( 'yes' !== $hide_notice && is_object( $screen ) && 'index.php' === $screen->parent_file ) {
$plugins = get_site_transient( 'update_plugins' );
if ( isset( $plugins->response ) && is_array( $plugins->response ) ) {
$plugins = array_keys( $plugins->response );
$plugin_names = [];
foreach ( $plugins_installed as $basename => $installed ) {
if ( is_array( $plugins ) && count( $plugins ) > 0 && in_array( $basename, $plugins, true ) ) {
$plugin_names[] = $installed['Name'];
}
}
if ( count( $plugin_names ) > 0 ) {
?>
<div class="woofunnel-notice-message notice notice-warning">
<a class="woofunnel-message-close notice-dismiss" href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'woofunnel-update-notice', 'hide' ), 'woofunnel_update_notice_nonce', '_woofunnel_update_notice_nonce' ) ); ?>">
<?php esc_html_e( 'Dismiss', 'woofunnels' ); // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch ?>
</a>
<p>
<?php
_e( sprintf( 'Attention: There is an update available of <strong>%s</strong> plugin. &nbsp;<a href="%s" class="">Go to updates</a>', implode( ', ', $plugin_names ), admin_url( 'plugins.php?s=funnelkit&plugin_status=all' ) ), 'woofunnels' ); // phpcs:ignore WordPress.Security.EscapeOutput, WordPress.WP.I18n.TextDomainMismatch, WordPress.WP.I18n.MissingTranslatorsComment, WordPress.WP.I18n.NonSingularStringLiteralText
?>
</p>
</div>
<style>
div.woofunnel-notice-message {
overflow: hidden;
position: relative;
}
.woofunnel-notice-message a.woofunnel-message-close {
position: static;
float: right;
padding: 0px 15px 5px 28px;
margin-top: -10px;
line-height: 14px;
text-decoration: none;
}
.woofunnel-notice-message a.woofunnel-message-close:before {
position: relative;
top: 18px;
left: -20px;
transition: all .1s ease-in-out;
}
</style>
<?php
}
}
}
}
/**
* Set option for hide woofunnel plugin update notice
*/
public static function hide_plugins_update_notices() {
if ( isset( $_GET['woofunnel-update-notice'] ) && isset( $_GET['_woofunnel_update_notice_nonce'] ) ) {
if ( ! wp_verify_nonce( sanitize_text_field( $_GET['_woofunnel_update_notice_nonce'] ), 'woofunnel_update_notice_nonce' ) ) {
wp_die( esc_html__( 'Action failed. Please refresh the page and retry.', 'woofunnels' ) ); // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
}
update_option( 'woofunnel_hide_update_notice', 'yes' );
wp_safe_redirect( admin_url( 'index.php' ) );
exit;
}
}
public function register_in_update_plugin_message() {
$get_in_update_message_support = apply_filters( 'woofunnels_in_update_message_support', array() );
if ( empty( $get_in_update_message_support ) ) {
return;
}
$this->in_update_messages = $get_in_update_message_support;
$get_basenames = array_keys( $get_in_update_message_support );
foreach ( $get_basenames as $basename ) {
add_action( 'in_plugin_update_message-' . $basename, array( $this, 'in_plugin_update_message' ), 10, 2 );
}
}
/**
* Show plugin changes on the plugins screen. Code adapted from W3 Total Cache.
*
* @param array $args Unused parameter.
* @param stdClass $response Plugin update response.
*/
public function in_plugin_update_message( $args, $response ) {
$changelog_path = $this->in_update_messages[ $args['plugin'] ];
$current_version = $args['Version'];
$upgrade_notice = $this->get_upgrade_notice( $response->new_version, $changelog_path, $current_version );
echo apply_filters( 'woofunnels_in_plugin_update_message', $upgrade_notice ? '</br>' . wp_kses_post( $upgrade_notice ) : '', $args['plugin'] ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
echo '<style>span.woofunnels_plugin_upgrade_notice::before {
content: ' . '"\f463";
margin-right: 6px;
vertical-align: bottom;
color: #f56e28;
display: inline-block;
font: 400 20px/1 dashicons;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
vertical-align: top;
}</style>';
}
/**
* Get the upgrade notice from WordPress.org.
*
* @param string $version WooCommerce new version.
*
* @return string
*/
protected function get_upgrade_notice( $version, $path, $current_version ) {
$transient_name = 'woofunnels_upgrade_notice_' . $version . md5( $path );
$upgrade_notice = get_transient( $transient_name );
if ( false === $upgrade_notice ) {
$response = wp_safe_remote_get( $path );
if ( ! is_wp_error( $response ) && ! empty( $response['body'] ) ) {
$upgrade_notice = $this->parse_update_notice( $response['body'], $version, $current_version );
set_transient( $transient_name, $upgrade_notice, DAY_IN_SECONDS );
}
}
return $upgrade_notice;
}
/**
* Parse update notice from readme file.
*
* @param string $content WooCommerce readme file content.
* @param string $new_version WooCommerce new version.
*
* @return string
*/
private function parse_update_notice( $content, $new_version, $current_version ) {
$version_parts = explode( '.', $new_version );
$check_for_notices = array(
$version_parts[0] . '.0', // Major.
$version_parts[0] . '.0.0', // Major.
$version_parts[0] . '.' . $version_parts[1], // Minor.
);
$notice_regexp = '~==\s*Upgrade Notice\s*==\s*=\s*(.*)\s*=(.*)(=\s*' . preg_quote( $new_version ) . '\s*=|$)~Uis';
$upgrade_notice = '';
foreach ( $check_for_notices as $check_version ) {
if ( version_compare( $current_version, $check_version, '>' ) ) {
continue;
}
$matches = null;
if ( preg_match( $notice_regexp, $content, $matches ) ) {
$notices = (array) preg_split( '~[\r\n]+~', trim( $matches[2] ) );
if ( version_compare( trim( $matches[1] ), $check_version, '=' ) ) {
$upgrade_notice .= '<span class="woofunnels_plugin_upgrade_notice">';
foreach ( $notices as $line ) {
$upgrade_notice .= preg_replace( '~\[([^\]]*)\]\(([^\)]*)\)~', '<a href="${2}">${1}</a>', $line );
}
$upgrade_notice .= '</span>';
}
break;
}
}
return wp_kses_post( $upgrade_notice );
}
public function fire_thankyou_ajax( $order_id ) {
$action = 'bwf_thankyou_ajax';
$nonce = wp_create_nonce( 'bwf_thankyou_ajax' );
$ajaxurl = admin_url( 'admin-ajax.php' );
$bwfUrlAjaxThankYou = $ajaxurl . '?action=' . $action . '&nonce=' . $nonce . '&order_id=' . $order_id;
?>
<script>
document.addEventListener("DOMContentLoaded", function (event) {
var xhr = new XMLHttpRequest();
var bwfUrlAjaxThankYou = '<?php echo $bwfUrlAjaxThankYou; //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>';
xhr.open("POST", bwfUrlAjaxThankYou, true);
//Send the proper header information along with the request
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.send();
});
</script>
<?php
}
public function handle_thankyou_ajax() {
check_ajax_referer( 'bwf_thankyou_ajax', 'nonce' );
$get_order_id = filter_input( INPUT_GET, 'order_id', FILTER_SANITIZE_NUMBER_INT );
if ( empty( $get_order_id ) ) {
return;
}
/**
* Fires a generic WC thankyou hook
*/
do_action( 'woofunnels_woocommerce_thankyou', $get_order_id );
wp_send_json( array( 'success' => true ) );
}
/**
* @hooked over 'admin_init'
* Mark the customizer data to not autoload on WP load as its only needed on specific pages.
*/
public function maybe_set_options_auto_loading_false() {
$should_run_query = get_option( '_bwf_upgrade_1_9_14', 'no' );
if ( 'yes' === $should_run_query ) {
return;
}
global $wpdb;
/**
* Update session table with the data
*/
$query = $wpdb->prepare( "UPDATE `" . $wpdb->prefix . "options` SET `autoload` = %s WHERE (`option_name` LIKE '%wfocu_c_%' OR `option_name` LIKE '%wfacp_c_%') AND `autoload` LIKE 'yes' AND `option_name` NOT LIKE 'wfacp_css_migrated'", 'no' );
$wpdb->query( $query ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
update_option( '_bwf_upgrade_1_9_14', 'yes' );
}
public function maybe_swap_order_to_make_it_correct() {
global $menu, $submenu;
if ( ! isset( $submenu['woofunnels'] ) ) {
return;
}
$get_parent_position = $this->get_parent_position( $menu );
$get_autonami_position = $this->get_autonami_position( $menu );
if ( false === $get_parent_position ) {
return;
}
if ( ! isset( $menu[ $get_autonami_position ] ) || ! is_array( $menu[ $get_autonami_position ] ) || 'autonami' !== $menu[ $get_autonami_position ][2] ) {
return;
}
$this->array_swap( $menu, $get_parent_position, $get_autonami_position );
}
/**
* @hooked over admin_head::-1
* Handles menu order for woofunnels submenu as it gets registered by the different plugin on different priorities
*/
public function maybe_correct_submenu_order() {
global $submenu, $menu, $woofunnels_menu_slug;
if ( ! isset( $submenu['woofunnels'] ) ) {
return;
}
$woofunnels_menu_slug = 'woofunnels';
$get_all_submenu = $submenu['woofunnels'];
/**
* get the top slug/submenu to play as parent menu
*/
$get_slug = $this->get_top_slug( $get_all_submenu );
if ( empty( $get_slug ) ) {
return;
}
/**
* get 'woofunnels' parent menu position so that we can alter it
*/
$get_parent_position = $this->get_parent_position( $menu );
if ( false === $get_parent_position ) {
return;
}
/**
* Assign found submenu in place of woofunnels to be shown as first menu in the series
*/
$menu[ $get_parent_position ][2] = $get_slug;
/**
* Unset woofunnels we do not need it
*/
unset( $submenu['woofunnels'] );
/**
* get the menu order sorted by placing license at the bottom
*/
$get_all_submenu = $this->get_current_order( $get_all_submenu );
/**
* Manage menu URL
*/
$get_all_submenu = array_map( function ( $val ) {
$val[2] = 'admin.php?page=' . $val[2];
return $val;
}, $get_all_submenu );
/**
* Place correct submenu in the global
*/
$submenu[ $get_slug ] = $get_all_submenu;
$woofunnels_menu_slug = $get_slug;
/**
* manage highlighting the menus
*/ global $parent_file, $plugin_page, $submenu_file, $current_page;
if ( true === $this->is_our_submenu( $plugin_page, $get_all_submenu ) ) :
$parent_file = $get_slug;//phpcs:ignore
$submenu_file = 'admin.php?page=' . $plugin_page;//phpcs:ignore
endif;
}
public function get_top_slug( $submenu ) {
if ( isset( $submenu[1][2] ) ) {
return $submenu[1][2];
}
return '';
}
function array_swap( &$array, $swap_a, $swap_b ) {
list( $array[ $swap_a ], $array[ $swap_b ] ) = array( $array[ $swap_b ], $array[ $swap_a ] );
}
public function get_parent_position( $menus ) {
$found = false;
foreach ( $menus as $key => $menu ) {
if ( 'woofunnels' === $menu[2] ) {
$found = $key;
break;
}
}
return $found;
}
public function get_autonami_position( $menus ) {
$found = false;
foreach ( $menus as $key => $menu ) {
if ( 'autonami' === $menu[2] ) {
$found = $key;
break;
}
}
return $found;
}
public function get_current_order( $get_all_submenu ) {
$get_license_config = $get_all_submenu[0];
array_shift( $get_all_submenu );
$get_all_submenu[ count( $get_all_submenu ) ] = $get_license_config;
return $get_all_submenu;
}
public function is_our_submenu( $plugin_page, $get_all_submenu ) {
$found = false;
foreach ( $get_all_submenu as $menu ) {
if ( 'admin.php?page=' . $plugin_page === $menu[2] ) {
$found = true;
break;
}
}
return $found;
}
public function correct_sub_menu_order() {
global $submenu, $menu;
/**
* change the title of the woofunnels to the new menu
*/
foreach ( $menu as &$men ) {
if ( isset( $men[5] ) && $men[5] === 'toplevel_page_woofunnels' ) {
$men[0] = 'FunnelKit';
$men[3] = 'FunnelKit';
}
}
if ( ! isset( $submenu['bwf'] ) ) {
return;
}
$new_sub_menu = [];
$any_external = false;
$max_count = 90;
$additional_break = false;
foreach ( $submenu['bwf'] as $key => $sub_item ) {
if ( ! current_user_can( $sub_item[1] ) ) {
continue;
}
if ( "admin.php?page=woofunnels" === $sub_item[2] ) {
continue;
}
switch ( $sub_item[2] ) {
case "admin.php?page=bwf":
$sub_item[4] = '';
$new_sub_menu[0] = $sub_item;
break;
case "admin.php?page=bwf&path=/funnels":
$new_sub_menu[10] = $sub_item;
break;
case "admin.php?page=bwf&path=/store-checkout":
$new_sub_menu[11] = $sub_item;
$new_sub_menu[11][4] = 'bwf_store_checkout';
break;
case "admin.php?page=bwf&path=/analytics":
$new_sub_menu[12] = $sub_item;
break;
case "admin.php?page=bwf&path=/templates":
$new_sub_menu[13] = $sub_item;
break;
case "admin.php?page=bwf_ab_tests":
$new_sub_menu[20] = $sub_item;
$any_external = true;
break;
case "admin.php?page=bwfcrm-contacts":
$sub_item[4] = 'bwf_admin_menu_b_top';
$new_sub_menu[70] = $sub_item;
$any_external = true;
break;
case "admin.php?page=autonami":
$new_sub_menu[80] = $sub_item;
$any_external = true;
break;
case "admin.php?page=bwf-campaigns":
$new_sub_menu[90] = $sub_item;
$any_external = true;
break;
case "admin.php?page=wfacp":
$any_external = true;
$new_sub_menu[40] = $sub_item;
break;
case "admin.php?page=wfch":
$any_external = true;
$new_sub_menu[45] = $sub_item;
break;
case "admin.php?page=wfob":
$any_external = true;
$new_sub_menu[50] = $sub_item;
break;
case "admin.php?page=upstroke":
$any_external = true;
$new_sub_menu[55] = $sub_item;
break;
default:
if ( false === $additional_break ) {
$additional_break = $max_count + 1;
}
$new_sub_menu[ $max_count + 1 ] = $sub_item;
$max_count ++;
break;
}
}
if ( ! empty( $new_sub_menu ) && count( $new_sub_menu ) > 0 ) {
/** Assigning class above native plugins */
if ( isset( $new_sub_menu[40] ) ) {
$new_sub_menu[40][4] = 'bwf_admin_menu_b_top';
} elseif ( isset( $new_sub_menu[45] ) ) {
$new_sub_menu[45][4] = 'bwf_admin_menu_b_top';
} elseif ( isset( $new_sub_menu[50] ) ) {
$new_sub_menu[50][4] = 'bwf_admin_menu_b_top';
} elseif ( isset( $new_sub_menu[55] ) ) {
$new_sub_menu[55][4] = 'bwf_admin_menu_b_top';
}
ksort( $new_sub_menu );
$submenu['bwf'] = $new_sub_menu;
ob_start();
?>
<style>
#adminmenu li.bwf_admin_menu_b_top {
border-top: 1px dashed #65686b;
padding-top: 5px;
margin-top: 5px
}
#adminmenu li.bwf_admin_menu_b_bottom {
border-bottom: 1px dashed #65686b;
padding-bottom: 5px;
margin-bottom: 5px
}
</style>
<?php
echo ob_get_clean(); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
}
public function correct_sub_menu_order_legacy() {
global $submenu;
if ( ! isset( $submenu['bwf_dashboard'] ) ) {
return;
}
$new_sub_menu = [];
$section = filter_input( INPUT_GET, 'section', FILTER_UNSAFE_RAW );
$aero_settings = filter_input( INPUT_GET, 'tab', FILTER_UNSAFE_RAW );
$aero_page = filter_input( INPUT_GET, 'page', FILTER_UNSAFE_RAW );
foreach ( $submenu['bwf_dashboard'] as $key => $sub_item ) {
if ( ! current_user_can( $sub_item[1] ) ) {
continue;
}
switch ( $sub_item[2] ) {
case "admin.php?page=bwf_dashboard":
$sub_item[4] = 'bwf_admin_menu_b_bottom';
$new_sub_menu[0] = $sub_item;
break;
case "admin.php?page=bwf_funnels":
$new_sub_menu[10] = $sub_item;
break;
case "admin.php?page=bwf_ab_tests":
$new_sub_menu[20] = $sub_item;
break;
case "admin.php?page=bwfcrm-contacts":
$sub_item[4] = 'bwf_admin_menu_b_top';
$new_sub_menu[70] = $sub_item;
break;
case "admin.php?page=autonami":
$new_sub_menu[80] = $sub_item;
break;
case "admin.php?page=bwf-campaigns":
$new_sub_menu[90] = $sub_item;
break;
case "admin.php?page=woofunnels_settings":
$sub_item[4] = 'bwf_admin_menu_b_top';
if ( in_array( $section, [ 'bwf_settings', 'lp-settings', 'op-settings', 'ty-settings' ] ) ) {
$sub_item[4] .= ' current';
} elseif ( 'settings' === $aero_settings && 'wfacp' === $aero_page ) {
$sub_item[4] .= ' current';
}
$new_sub_menu[140] = $sub_item;
break;
case "admin.php?page=woofunnels":
$new_sub_menu[150] = $sub_item;
break;
case "admin.php?page=wfacp":
$new_sub_menu[40] = $sub_item;
break;
case "admin.php?page=wfch":
$new_sub_menu[45] = $sub_item;
break;
case "admin.php?page=wfob":
$new_sub_menu[50] = $sub_item;
break;
case "admin.php?page=upstroke":
$new_sub_menu[55] = $sub_item;
break;
}
}
if ( ! empty( $new_sub_menu ) && count( $new_sub_menu ) > 0 ) {
/** Assigning class above native plugins */
if ( isset( $new_sub_menu[40] ) ) {
$new_sub_menu[40][4] = 'bwf_admin_menu_b_top';
} elseif ( isset( $new_sub_menu[45] ) ) {
$new_sub_menu[45][4] = 'bwf_admin_menu_b_top';
} elseif ( isset( $new_sub_menu[50] ) ) {
$new_sub_menu[50][4] = 'bwf_admin_menu_b_top';
}
ksort( $new_sub_menu );
$submenu['bwf_dashboard'] = $new_sub_menu;
ob_start();
?>
<style>
#adminmenu li.bwf_admin_menu_b_top {
border-top: 1px dashed #65686b;
padding-top: 5px;
margin-top: 5px
}
#adminmenu li.bwf_admin_menu_b_bottom {
border-bottom: 1px dashed #65686b;
padding-bottom: 5px;
margin-bottom: 5px
}
</style>
<?php
echo ob_get_clean(); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
}
public function maybe_clear_plugin_update_transients() {
delete_transient( 'update_plugins' );
delete_site_transient( 'update_plugins' );
global $wpdb;
$wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->options WHERE option_name LIKE %s", '%_bwf_version_cache_%' ) ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
}
public function print_css() {
?>
<style>
.wp-admin #adminmenu .toplevel_page_woofunnels .wp-menu-image:before {
content: none;
}
.wp-admin #adminmenu .toplevel_page_woofunnels .wp-not-current-submenu .wp-menu-image {
background-image: url("<?php echo esc_url( plugin_dir_url( WooFunnel_Loader::$ultimate_path ) . 'woofunnels/assets/img/bwf-icon-grey.svg'); ?>") !important;
}
.wp-admin #adminmenu .toplevel_page_woofunnels .wp-has-current-submenu .wp-menu-image {
background-image: url("<?php echo esc_url( plugin_dir_url( WooFunnel_Loader::$ultimate_path ) . 'woofunnels/assets/img/bwf-icon-white.svg'); ?>") !important;
}
.wp-admin #adminmenu .toplevel_page_woofunnels .wp-menu-image {
background-repeat: no-repeat;
position: relative;
top: 5px;
background-position: 50% 25%;
background-size: 60%;
}
</style> <?php
}
}
}

View File

@@ -0,0 +1,55 @@
<?php
if ( ! class_exists( 'WooFunnels_Support' ) ) {
/**
* @author woofunnels
* @package WooFunnels
*/
#[AllowDynamicProperties]
class WooFunnels_Support {
protected static $instance;
public $validation = true;
public $is_submitted;
/**
*
* WooFunnels_Support constructor.
*/
public function __construct() {
}
/**
* Creates and instance of the class
* @return WooFunnels_Support
*/
public static function get_instance() {
if ( null === self::$instance ) {
self::$instance = new self;
}
return self::$instance;
}
/**
* Processing support request
*
* @param $posted_data
*
* @uses WooFunnels_API used to fire api request to generate request
* @uses WooFunnels_admin_notifications pushing success and failure notifications
* @since 1.0.4
*/
public function woofunnels_maybe_push_support_request( $posted_data ) {
}
public function fetch_tools_data() {
}
public function js_script() {
}
}
}

View File

@@ -0,0 +1,196 @@
<?php
/**
* @author woofunnels
* @package WooFunnels
*/
if ( ! class_exists( 'WooFunnels_Transient' ) ) {
#[AllowDynamicProperties]
class WooFunnels_Transient {
protected static $instance;
/**
* WooFunnels_Transient constructor.
*/
public function __construct() {
}
/**
* Creates an instance of the class
* @return WooFunnels_Transient
*/
public static function get_instance() {
if ( null === self::$instance ) {
self::$instance = new self;
}
return self::$instance;
}
/**
* Set the transient contents by key and group within page scope
*
* @param $key
* @param $value
* @param int $expiration | default 1 hour
* @param string $plugin_short_name
*/
public function set_transient( $key, $value, $expiration = 3600, $plugin_short_name = 'bwf' ) {
$transient_key = '_woofunnels_transient_' . $plugin_short_name . '_' . $key;
$transient_value = array(
'time' => time() + (int) $expiration,
'value' => $value,
);
$file_writing = $this->is_file_saving_enabled();
if ( class_exists( 'WooFunnels_File_Api' ) && true === $file_writing ) {
$file_api = new WooFunnels_File_Api( $plugin_short_name . '-transient' );
$file_api->touch( $transient_key );
if ( $file_api->is_writable( $transient_key ) && $file_api->is_readable( $transient_key ) ) {
$transient_value = maybe_serialize( $transient_value );
$file_api->put_contents( $transient_key, $transient_value );
} else {
// woofunnels file api folder not writable
update_option( $transient_key, $transient_value, false );
}
} else {
// woofunnels file api method not available
update_option( $transient_key, $transient_value, false );
}
}
/**
* Get the transient contents by the transient key or group.
*
* @param $key
* @param string $plugin_short_name
*
* @return bool|mixed
*/
public function get_transient( $key, $plugin_short_name = 'bwf' ) {
if ( true === apply_filters( 'bwf_disable_woofunnels_transient', false, $plugin_short_name ) ) {
return false;
}
$transient_key = '_woofunnels_transient_' . $plugin_short_name . '_' . $key;
$file_writing = $this->is_file_saving_enabled();
if ( class_exists( 'WooFunnels_File_Api' ) && true === $file_writing ) {
$file_api = new WooFunnels_File_Api( $plugin_short_name . '-transient' );
if ( $file_api->is_writable( $transient_key ) && $file_api->is_readable( $transient_key ) ) {
$data = $file_api->get_contents( $transient_key );
$data = maybe_unserialize( $data );
$value = $this->get_value( $transient_key, $data );
if ( false === $value ) {
$file_api->delete( $transient_key );
}
return $value;
}
/**
* Restricted get value search only file if saving file enabled
*/
return false;
}
// woofunnels file api method not available
$data = get_option( $transient_key, false );
if ( false === $data ) {
return false;
}
return $this->get_value( $transient_key, $data, true );
}
public function get_value( $transient_key, $data, $db_call = false ) {
$current_time = time();
if ( is_array( $data ) && isset( $data['time'] ) ) {
if ( $current_time > (int) $data['time'] ) {
if ( true === $db_call ) {
delete_option( $transient_key );
}
return false;
} else {
return $data['value'];
}
}
return false;
}
/**
* Delete the transient by key
*
* @param $key
* @param string $plugin_short_name
*/
public function delete_transient( $key, $plugin_short_name = 'bwf' ) {
$transient_key = '_woofunnels_transient_' . $plugin_short_name . '_' . $key;
$file_writing = $this->is_file_saving_enabled();
if ( class_exists( 'WooFunnels_File_Api' ) && true === $file_writing ) {
$file_api = new WooFunnels_File_Api( $plugin_short_name . '-transient' );
if ( $file_api->exists( $transient_key ) ) {
$file_api->delete_file( $transient_key );
}
}
// removing db transient
delete_option( $transient_key );
}
/**
* Delete all the transients
*
* @param string $plugin_short_name
*/
public function delete_all_transients( $plugin_short_name = '' ) {
global $wpdb;
/** removing db transient */
$query = "DELETE FROM `$wpdb->options` WHERE `option_name` LIKE '%_woofunnels_transient_{$plugin_short_name}%'";
$wpdb->query( $query ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
/** removing files if file api exist */
$file_writing = $this->is_file_saving_enabled();
if ( class_exists( 'WooFunnels_File_Api' ) && true === $file_writing ) {
$file_api = new WooFunnels_File_Api( $plugin_short_name . '-transient' );
$file_api->delete_all( $plugin_short_name . '-transient', true );
}
}
/**
* Delete all woofunnels plugins transients
*/
public function delete_force_transients() {
global $wpdb;
/** removing db transient */
$query = "DELETE FROM `$wpdb->options` WHERE `option_name` LIKE '%_woofunnels_transient_%'";
$wpdb->query( $query ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
/** removing files if file api exist */
$file_writing = $this->is_file_saving_enabled();
if ( class_exists( 'WooFunnels_File_Api' ) && true === $file_writing ) {
$file_api = new WooFunnels_File_Api( 'bwf-transient' );
$file_api->delete_folder( $file_api->woofunnels_core_dir, true );
}
}
/**
* Can modify the file writing via filter hook
*
* @return bool
*/
protected function is_file_saving_enabled() {
return apply_filters( '_bwf_transient_file_saving', true );
}
}
}

View File

@@ -0,0 +1,245 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit;
} // Exit if accessed directly
if ( ! class_exists( 'WP_List_Table' ) ) {
require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
}
if ( ! class_exists( 'WooFunnels_Updater_Licenses_Table' ) ) {
/**
* Class WooFunnels_Updater_Licenses_Table
* @package WooFunnels
*/
#[AllowDynamicProperties]
class WooFunnels_Updater_Licenses_Table extends WP_List_Table {
public $per_page = 100;
public $data;
/**
* Constructor.
* @since 1.0.0
*/
public function __construct( $args = array() ) {
global $status, $page;
parent::__construct( array(
'singular' => 'license', //singular name of the listed records
'plural' => 'licenses', //plural name of the listed records
'ajax' => false, //does this table support ajax?
) );
$status = 'all';
$page = $this->get_pagenum();
$this->data = array();
// Make sure this file is loaded, so we have access to plugins_api(), etc.
require_once( ABSPATH . '/wp-admin/includes/plugin-install.php' );
parent::__construct( $args );
}
// End __construct()
/**
* Text to display if no items are present.
* @return void
* @since 1.0.0
*/
public function no_items() {
echo wpautop( __( 'No plugins available for activation.', 'woofunnels' ) ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.I18n.TextDomainMismatch
}
// End no_items(0)
/**
* The content of each column.
*
* @param array $item The current item in the list.
* @param string $column_name The key of the current column.
*
* @return string Output for the current column.
* @since 1.0.0
*/
public function column_default( $item, $column_name ) {
switch ( $column_name ) {
case 'plugin':
case 'product_status':
case 'product_version':
case 'license_expiry':
return $item[ $column_name ];
break;
}
}
// End column_default()
/**
* Content for the "product_name" column.
*
* @param array $item The current item.
*
* @return string The content of this column.
* @since 1.0.0
*/
public function column_plugin( $item ) {
return wpautop( '<strong>' . $item['plugin'] . '</strong>' );
}
// End get_sortable_columns()
/**
* Content for the "product_version" column.
*
* @param array $item The current item.
*
* @return string The content of this column.
* @since 1.0.0
*/
public function column_product_version( $item ) {
if ( isset( $item['latest_version'], $item['product_version'] ) && version_compare( $item['product_version'], $item['latest_version'], '<' ) ) {
$version_text = '<strong>' . $item['product_version'] . '<span class="update-available"> - ' . sprintf( __( 'version %1$s available', 'woofunnels' ), esc_html( $item['latest_version'] ) ) . '</span></strong>' . "\n"; // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch, WordPress.WP.I18n.MissingTranslatorsComment
} else {
$version_text = '<strong class="latest-version">' . $item['product_version'] . '</strong>' . "\n";
}
return wpautop( $version_text );
}
// End get_columns()
/**
* Content for the "status" column.
*
* @param array $item The current item.
*
* @return string The content of this column.
* @since 1.0.0
*/
public function column_product_status( $item ) {
$response = '';
$input_text = '<input name="license_keys[' . esc_attr( $item['product_file_path'] ) . '][key]" id="license_keys-' . esc_attr( $item['product_file_path'] ) . '" type="text" size="37" aria-required="true" value="' . $item['existing_key']['key'] . '" placeholder="' . esc_attr__( '
Place your license key here', 'woofunnels' ) . '" />' . "\n"; // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
if ( $this->is_license_expire( $item ) ) {
$response_notice = '';
$response_notice .= $input_text;
$response_notice .= '<span class="below_input_message">' . sprintf( __( 'This license has expired. Login to <a target="_blank" href="%s">Your Account</a> and renew your license.', 'woofunnels' ), 'https://myaccount.funnelkit.com/' ) . '</span>'; // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch, WordPress.WP.I18n.MissingTranslatorsComment
$response .= apply_filters( 'woofunnels_license_notice_bewlow_field', $response_notice, $item );
} elseif ( 'active' === $item['product_status'] ) {
if ( empty( $item['_data']['activated'] ) ) {
$response_notice = '';
$response_notice .= $input_text;
if ( ! isset( $item['_data']['manually_deactivated'] ) || empty( $item['_data']['manually_deactivated'] ) ) {
$response_notice .= '<span class="below_input_message">' . sprintf( __( 'This license is no longer valid. Login to <a target="_blank" href="%s">Your Account</a> and renew your license.', 'woofunnels' ), 'https://myaccount.funnelkit.com/' ) . '</span>'; // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch, WordPress.WP.I18n.MissingTranslatorsComment
}
$response .= apply_filters( 'woofunnels_license_notice_bewlow_field', $response_notice, $item );
} else {
$deactivate_url = wp_nonce_url( add_query_arg( 'action', 'woofunnels_deactivate-product', add_query_arg( 'filepath', $item['product_file_path'], add_query_arg( 'page', filter_input( INPUT_GET, 'page', FILTER_UNSAFE_RAW ), add_query_arg( 'tab', 'licenses' ), network_admin_url( 'admin.php' ) ) ) ), 'bwf-deactivate-product' );
if ( isset( $item['existing_key'] ) && isset( $item['existing_key']['key'] ) ) {
$license_obj = WooFunnels_Licenses::get_instance();
$license_key = $license_obj->get_secret_license_key( $item['existing_key']['key'] );
$response = $license_key . '<br/>';
}
$response .= '<a href="' . esc_url( $deactivate_url ) . '">' . __( 'Deactivate', 'woofunnels' ) . '</a>' . "\n"; // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
}
} else {
$response = $input_text;
}
return $response;
}
public function is_license_expire( $item ) {
if ( isset( $item['existing_key']['expires'] ) && $item['existing_key']['expires'] !== '' && ( strtotime( $item['existing_key']['expires'] ) < current_time( 'timestamp' ) ) ) {
return true;
}
if ( isset( $item['_data']['expired'] ) && ! empty( $item['_data']['expired'] ) ) {
return true;
}
return false;
}
public function column_product_expiry( $item ) {
if ( $this->is_license_expire( $item ) ) {
$date_string = __( 'Expire', 'woofunnels' ); // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
try {
$date = new DateTime( $item['existing_key']['expires'] );
$date_string = $date->format( get_option( 'date_format' ) );
} catch ( Exception $e ) {
}
return $date_string;
} else {
if ( '' === $item['existing_key']['key'] ) {
return __( 'N/A', 'woofunnels' ); // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
} elseif ( '' === $item['existing_key']['expires'] ) {
return __( 'Lifetime', 'woofunnels' ); // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
} else {
$date = new DateTime( $item['existing_key']['expires'] );
$date_string = $date->format( get_option( 'date_format' ) );
return $date_string;
}
}
}
/**
* Retrieve an array of possible bulk actions.
* @return array
* @since 1.0.0
*/
public function get_bulk_actions() {
$actions = array();
return $actions; // End column_status()
}
/**
* Prepare an array of items to be listed.
* @since 1.0.0
*/
public function prepare_items() {
$columns = $this->get_columns();
$hidden = array();
$sortable = $this->get_sortable_columns();
$this->_column_headers = array( $columns, $hidden, $sortable );
$total_items = is_array( $this->data ) ? count( $this->data ) : 0;
$this->set_pagination_args( array(
'total_items' => $total_items, //WE have to calculate the total number of items
'per_page' => $total_items, //WE have to determine how many items to show on a page
) );
$this->items = $this->data;
}
public function get_columns() {
$columns = array(
'plugin' => __( 'Plugin', 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'product_version' => __( 'Version', 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'product_status' => __( 'Key', 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'product_expiry' => __( 'Renews On', 'woofunnels' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
);
return $columns;
}
// End get_bulk_actions()
public function get_sortable_columns() {
return array();
}
}
}

View File

@@ -0,0 +1,2 @@
<?php
// Silence is golden.

View File

@@ -0,0 +1,2 @@
<?php
// Silence is golden.

View File

@@ -0,0 +1,2 @@
<?php
// Silence is golden.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,162 @@
<?php
/**
* WP Async Request
*
* @package WP-Background-Processing
*/
defined( 'ABSPATH' ) || exit;
if ( ! class_exists( 'WP_Async_Request' ) ) {
/**
* Abstract WP_Async_Request class.
*/
#[AllowDynamicProperties]
abstract class WP_Async_Request {
/**
* Prefix
*
* (default value: 'wp')
*
* @var string
* @access protected
*/
protected $prefix = 'wp';
/**
* Action
*
* (default value: 'async_request')
*
* @var string
* @access protected
*/
protected $action = 'async_request';
/**
* Identifier
*
* @var mixed
* @access protected
*/
protected $identifier;
/**
* Data
*
* (default value: array())
*
* @var array
* @access protected
*/
protected $data = array();
/**
* Initiate new async request
*/
public function __construct() {
$this->identifier = $this->prefix . '_' . $this->action;
add_action( 'wp_ajax_' . $this->identifier, array( $this, 'maybe_handle' ) );
add_action( 'wp_ajax_nopriv_' . $this->identifier, array( $this, 'maybe_handle' ) );
}
/**
* Set data used during the request
*
* @param array $data Data.
*
* @return $this
*/
public function data( $data ) {
$this->data = $data;
return $this;
}
/**
* Dispatch the async request
*
* @return array|WP_Error
*/
public function dispatch() {
$url = add_query_arg( $this->get_query_args(), $this->get_query_url() );
$args = $this->get_post_args();
return wp_remote_post( esc_url_raw( $url ), $args );
}
/**
* Get query args
*
* @return array
*/
protected function get_query_args() {
if ( property_exists( $this, 'query_args' ) ) {
return $this->query_args;
}
return array(
'action' => $this->identifier,
'nonce' => wp_create_nonce( $this->identifier ),
);
}
/**
* Get query URL
*
* @return string
*/
protected function get_query_url() {
if ( property_exists( $this, 'query_url' ) ) {
return $this->query_url;
}
return admin_url( 'admin-ajax.php' );
}
/**
* Get post args
*
* @return array
*/
protected function get_post_args() {
if ( property_exists( $this, 'post_args' ) ) {
return $this->post_args;
}
return array(
'timeout' => 0.01,
'blocking' => false,
'body' => $this->data,
'cookies' => $_COOKIE,
'sslverify' => apply_filters( 'https_local_ssl_verify', false ),
);
}
/**
* Maybe handle
*
* Check for correct nonce and pass to handler.
*/
public function maybe_handle() {
// Don't lock up other requests while processing
session_write_close();
check_ajax_referer( $this->identifier, 'nonce' );
$this->handle();
wp_die();
}
/**
* Handle
*
* Override this method to perform any actions required
* during the async request.
*/
abstract protected function handle();
}
}

View File

@@ -0,0 +1,509 @@
<?php // @codingStandardsIgnoreLine.
/**
* Abstract WP_Background_Process class.
*
* @package WP-Background-Processing
* @extends WP_Async_Request
*/
defined( 'ABSPATH' ) || exit;
if ( ! class_exists( 'WP_Background_Process' ) ) {
/**
* Abstract WP_Background_Process class.
*/
#[AllowDynamicProperties]
abstract class WP_Background_Process extends WP_Async_Request {
/**
* Action
*
* (default value: 'background_process')
*
* @var string
* @access protected
*/
protected $action = 'background_process';
/**
* Start time of current process.
*
* (default value: 0)
*
* @var int
* @access protected
*/
protected $start_time = 0;
/**
* Cron_hook_identifier
*
* @var mixed
* @access protected
*/
protected $cron_hook_identifier;
/**
* Cron_interval_identifier
*
* @var mixed
* @access protected
*/
protected $cron_interval_identifier;
/**
* Initiate new background process
*/
public function __construct() {
parent::__construct();
$this->cron_hook_identifier = $this->identifier . '_cron';
$this->cron_interval_identifier = $this->identifier . '_cron_interval';
add_action( $this->cron_hook_identifier, array( $this, 'handle_cron_healthcheck' ) );
add_filter( 'cron_schedules', array( $this, 'schedule_cron_healthcheck' ) );
}
/**
* Push to queue
*
* @param mixed $data Data.
*
* @return $this
*/
public function push_to_queue( $data ) {
$this->data[] = $data;
return $this;
}
/**
* Save queue
*
* @return $this
*/
public function save() {
$key = $this->generate_key();
if ( ! empty( $this->data ) ) {
update_site_option( $key, $this->data );
}
return $this;
}
/**
* Generate key
*
* Generates a unique key based on microtime. Queue items are
* given a unique key so that they can be merged upon save.
*
* @param int $length Length.
*
* @return string
*/
protected function generate_key( $length = 64 ) {
$unique = md5( microtime() . rand() );
$prepend = $this->identifier . '_batch_';
return substr( $prepend . $unique, 0, $length );
}
/**
* Maybe process queue
*
* Checks whether data exists within the queue and that
* the process is not already running.
*/
public function maybe_handle() {
// Don't lock up other requests while processing
session_write_close();
if ( $this->is_process_running() ) {
// Background process already running.
wp_die();
}
if ( $this->is_queue_empty() ) {
// No data to process.
wp_die();
}
check_ajax_referer( $this->identifier, 'nonce' );
$this->handle();
wp_die();
}
/**
* Is process running
*
* Check whether the current process is already running
* in a background process.
*/
protected function is_process_running() {
if ( get_site_transient( $this->identifier . '_process_lock' ) ) {
// Process already running.
return true;
}
return false;
}
/**
* Is queue empty
*
* @return bool
*/
protected function is_queue_empty() {
global $wpdb;
$table = $wpdb->options;
$column = 'option_name';
if ( is_multisite() ) {
$table = $wpdb->sitemeta;
$column = 'meta_key';
}
$key = $this->identifier . '_batch_%';
//phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
$count = $wpdb->get_var( $wpdb->prepare( "
SELECT COUNT(*)
FROM {$table}
WHERE {$column} LIKE %s
", $key ) );
return ! ( $count > 0 );
}
/**
* Handle
*
* Pass each queue item to the task handler, while remaining
* within server memory and time limit constraints.
*/
protected function handle() {
$this->lock_process();
do {
$batch = $this->get_batch();
foreach ( $batch->data as $key => $value ) {
$task = $this->task( $value );
if ( false !== $task ) {
$batch->data[ $key ] = $task;
} else {
unset( $batch->data[ $key ] );
}
if ( $this->time_exceeded() || $this->memory_exceeded() ) {
// Batch limits reached.
break;
}
}
// Update or delete current batch.
if ( ! empty( $batch->data ) ) {
$this->update( $batch->key, $batch->data );
} else {
$this->delete( $batch->key );
}
} while ( ! $this->time_exceeded() && ! $this->memory_exceeded() && ! $this->is_queue_empty() );
$this->unlock_process();
// Start next batch or complete process.
if ( ! $this->is_queue_empty() ) {
$this->dispatch();
} else {
$this->complete();
}
wp_die();
}
/**
* Lock process
*
* Lock the process so that multiple instances can't run simultaneously.
* Override if applicable, but the duration should be greater than that
* defined in the time_exceeded() method.
*/
protected function lock_process() {
$this->start_time = time(); // Set start time of current process.
$lock_duration = ( property_exists( $this, 'queue_lock_time' ) ) ? $this->queue_lock_time : 60; // 1 minute
$lock_duration = apply_filters( $this->identifier . '_queue_lock_time', $lock_duration );
set_site_transient( $this->identifier . '_process_lock', microtime(), $lock_duration );
}
/**
* Get batch
*
* @return stdClass Return the first batch from the queue
*/
protected function get_batch() {
global $wpdb;
$table = $wpdb->options;
$column = 'option_name';
$key_column = 'option_id';
$value_column = 'option_value';
if ( is_multisite() ) {
$table = $wpdb->sitemeta;
$column = 'meta_key';
$key_column = 'meta_id';
$value_column = 'meta_value';
}
$key = $this->identifier . '_batch_%';
//phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
$query = $wpdb->get_row( $wpdb->prepare( "
SELECT *
FROM {$table}
WHERE {$column} LIKE %s
ORDER BY {$key_column} ASC
LIMIT 1
", $key ) );
$batch = new stdClass();
$batch->key = $query->$column;
$batch->data = maybe_unserialize( $query->$value_column );
return $batch;
}
/**
* Task
*
* Override this method to perform any actions required on each
* queue item. Return the modified item for further processing
* in the next pass through. Or, return false to remove the
* item from the queue.
*
* @param mixed $item Queue item to iterate over.
*
* @return mixed
*/
abstract protected function task( $item );
/**
* Time exceeded.
*
* Ensures the batch never exceeds a sensible time limit.
* A timeout limit of 30s is common on shared hosting.
*
* @return bool
*/
protected function time_exceeded() {
$finish = $this->start_time + apply_filters( $this->identifier . '_default_time_limit', 20 ); // 20 seconds
$return = false;
if ( time() >= $finish ) {
$return = true;
}
return apply_filters( $this->identifier . '_time_exceeded', $return );
}
/**
* Memory exceeded
*
* Ensures the batch process never exceeds 90%
* of the maximum WordPress memory.
*
* @return bool
*/
protected function memory_exceeded() {
$memory_limit = $this->get_memory_limit() * 0.9; // 90% of max memory
$current_memory = memory_get_usage( true );
$return = false;
if ( $current_memory >= $memory_limit ) {
$return = true;
}
return apply_filters( $this->identifier . '_memory_exceeded', $return );
}
/**
* Get memory limit
*
* @return int
*/
protected function get_memory_limit() {
if ( function_exists( 'ini_get' ) ) {
$memory_limit = ini_get( 'memory_limit' );
} else {
// Sensible default.
$memory_limit = '128M';
}
if ( ! $memory_limit || - 1 === $memory_limit ) {
// Unlimited, set to 32GB.
$memory_limit = '32000M';
}
return intval( $memory_limit ) * 1024 * 1024;
}
/**
* Update queue
*
* @param string $key Key.
* @param array $data Data.
*
* @return $this
*/
public function update( $key, $data ) {
if ( ! empty( $data ) ) {
update_site_option( $key, $data );
}
return $this;
}
/**
* Delete queue
*
* @param string $key Key.
*
* @return $this
*/
public function delete( $key ) {
delete_site_option( $key );
return $this;
}
/**
* Unlock process
*
* Unlock the process so that other instances can spawn.
*
* @return $this
*/
protected function unlock_process() {
delete_site_transient( $this->identifier . '_process_lock' );
return $this;
}
/**
* Dispatch
*
* @access public
* @return void
*/
public function dispatch() {
// Schedule the cron healthcheck.
$this->schedule_event();
// Perform remote post.
return parent::dispatch();
}
/**
* Schedule event
*/
protected function schedule_event() {
if ( ! wp_next_scheduled( $this->cron_hook_identifier ) ) {
wp_schedule_event( time(), $this->cron_interval_identifier, $this->cron_hook_identifier );
}
}
/**
* Complete.
*
* Override if applicable, but ensure that the below actions are
* performed, or, call parent::complete().
*/
protected function complete() {
// Unschedule the cron healthcheck.
$this->clear_scheduled_event();
}
/**
* Clear scheduled event
*/
protected function clear_scheduled_event() {
$timestamp = wp_next_scheduled( $this->cron_hook_identifier );
if ( $timestamp ) {
wp_unschedule_event( $timestamp, $this->cron_hook_identifier );
}
}
/**
* Schedule cron healthcheck
*
* @access public
*
* @param mixed $schedules Schedules.
*
* @return mixed
*/
public function schedule_cron_healthcheck( $schedules ) {
$interval = apply_filters( $this->identifier . '_cron_interval', 5 );
if ( property_exists( $this, 'cron_interval' ) ) {
$interval = apply_filters( $this->identifier . '_cron_interval', $this->cron_interval );
}
// Adds every 5 minutes to the existing schedules.
$schedules[ $this->identifier . '_cron_interval' ] = array(
'interval' => MINUTE_IN_SECONDS * $interval,
'display' => sprintf( __( 'Every %d Minutes', 'woofunnels' ), $interval ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch, WordPress.WP.I18n.MissingTranslatorsComment
);
return $schedules;
}
/**
* Handle cron healthcheck
*
* Restart the background process if not already running
* and data exists in the queue.
*/
public function handle_cron_healthcheck() {
if ( $this->is_process_running() ) {
// Background process already running.
exit;
}
if ( $this->is_queue_empty() ) {
// No data to process.
$this->clear_scheduled_event();
exit;
}
$this->handle();
exit;
}
/**
* Cancel Process
*
* Stop processing queue items, clear cronjob and delete batch.
*
*/
public function cancel_process() {
if ( ! $this->is_queue_empty() ) {
$batch = $this->get_batch();
$this->delete( $batch->key );
wp_clear_scheduled_hook( $this->cron_hook_identifier );
}
}
}
}

View File

@@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.

Some files were not shown because too many files have changed in this diff Show More