Initial commit: Atomaste website
This commit is contained in:
@@ -0,0 +1,285 @@
|
||||
<?php
|
||||
|
||||
if ( ! class_exists( 'burst_goal' ) ) {
|
||||
class burst_goal {
|
||||
public $id;
|
||||
public $title = '';
|
||||
public $type = 'clicks';
|
||||
public $status = 'inactive';
|
||||
public $server_side = false;
|
||||
public $url = '*';
|
||||
public $conversion_metric = 'visitors';
|
||||
public $date_start;
|
||||
public $date_end;
|
||||
public $date_created;
|
||||
public $setup;
|
||||
public $attribute = 'class';
|
||||
public $attribute_value = '';
|
||||
public $hook = '';
|
||||
public $page_or_website = 'website';
|
||||
public $specific_page = '';
|
||||
|
||||
public function __construct( $id = 0 ) {
|
||||
$this->id = (int) $id;
|
||||
$this->get();
|
||||
}
|
||||
|
||||
public function __get( $property ) {
|
||||
if ( property_exists( $this, $property ) ) {
|
||||
return $this->$property;
|
||||
}
|
||||
}
|
||||
|
||||
public function __set( $property, $value ) {
|
||||
if ( property_exists( $this, $property ) ) {
|
||||
$this->$property = $value;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function get( $upgrade = true ) {
|
||||
if ( $this->id === 0 ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
global $wpdb;
|
||||
$goal = wp_cache_get( 'burst_goal_' . $this->id, 'burst' );
|
||||
if ( ! $goal ) {
|
||||
$goal = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}burst_goals WHERE ID = %s", $this->id ) );
|
||||
wp_cache_set( 'burst_goal_' . $this->id, $goal, 'burst', 10 );
|
||||
}
|
||||
|
||||
if ( ! $goal ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->title = $goal->title !== '' ? $goal->title : __( 'New goal', 'burst-statistics' );
|
||||
$this->type = $goal->type;
|
||||
$this->status = $goal->status;
|
||||
$this->server_side = $goal->server_side;
|
||||
$this->url = $goal->url;
|
||||
$this->conversion_metric = $goal->conversion_metric;
|
||||
$this->attribute = empty( $goal->attribute ) ? 'class' : $goal->attribute;
|
||||
$this->attribute_value = empty( $goal->attribute_value ) ? '' : $goal->attribute_value;
|
||||
$this->hook = empty( $goal->hook ) ? '' : $goal->hook;
|
||||
$this->date_start = $goal->date_start;
|
||||
$this->date_end = $goal->date_end > 0 ? $goal->date_end : strtotime( 'tomorrow midnight' ) - 1;
|
||||
$this->date_created = $goal->date_created;
|
||||
|
||||
// split url property into two separate properties, depending on * value
|
||||
$this->page_or_website = $this->url !== '*' ? 'page' : 'website';
|
||||
$this->specific_page = $this->page_or_website === 'page' ? $this->url : '';
|
||||
|
||||
// upgrade old structure data, then remove it
|
||||
$setup = isset( $goal->setup ) ? json_decode( $goal->setup, false ) : null;
|
||||
if ( $upgrade && $setup !== null && isset( $setup->attribute ) && isset( $setup->value ) ) {
|
||||
$this->attribute = $setup->attribute;
|
||||
$this->attribute_value = $setup->value;
|
||||
$this->setup = null;
|
||||
$this->save();
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function save(): void {
|
||||
do_action( 'burst_before_save_goals' );
|
||||
global $wpdb;
|
||||
$table_name = $wpdb->prefix . 'burst_goals';
|
||||
$available_goal_types = $this->get_available_goal_types();
|
||||
// merge url property from two separate properties, depending on 'website' value
|
||||
$url = $this->page_or_website === 'website' ? '*' : $this->specific_page;
|
||||
$this->url = $url !== '*' ? burst_sanitize_relative_url( $url ) : '*';
|
||||
$this->server_side = $available_goal_types[ $this->sanitize_type( $this->type ) ]['server_side'] ?? 0;
|
||||
//update start time only if the goal status has changed to active, or if it's a new goal
|
||||
$db_goal = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}burst_goals WHERE ID = %s", $this->id ) );
|
||||
if ( $db_goal) {
|
||||
if ( $db_goal->status !== $this->status && $this->status === 'active' ) {
|
||||
$this->date_start = time();
|
||||
$this->date_end = 0;
|
||||
}
|
||||
} else {
|
||||
$this->date_start = time();
|
||||
$this->date_end = 0;
|
||||
}
|
||||
|
||||
$args = [
|
||||
'title' => sanitize_text_field( $this->title ),
|
||||
'type' => $this->sanitize_type( $this->type ),
|
||||
'status' => $this->sanitize_status( $this->status ),
|
||||
'server_side' => $this->server_side,
|
||||
'url' => $this->url,
|
||||
'conversion_metric' => $this->sanitize_metric( $this->conversion_metric ),
|
||||
'date_start' => $this->date_start,
|
||||
'date_end' => $this->date_end,
|
||||
'date_created' => (int) $this->date_created,
|
||||
'attribute' => sanitize_text_field( $this->attribute ),
|
||||
'attribute_value' => sanitize_text_field( $this->attribute_value ),
|
||||
'hook' => sanitize_text_field( $this->hook ),
|
||||
];
|
||||
|
||||
// check if we have an id, and if so, check if this id exists in the database
|
||||
if ( $this->id > 0 ) {
|
||||
// if legacy property exists, update it so we can clear the contents after saving
|
||||
if ( $this->has_setup_column() ) {
|
||||
$args['setup'] = $this->setup;
|
||||
}
|
||||
$wpdb->update( $table_name, $args, [ 'ID' => $this->id ] );
|
||||
} elseif ( $this->can_add_goal() ) {
|
||||
$args['date_created'] = $this->date_created = time();
|
||||
$wpdb->insert( $table_name, $args );
|
||||
$this->id = (int) $wpdb->insert_id;
|
||||
}
|
||||
|
||||
// prevent loops by ensuring the save (for upgrading) doesn't get called again in the get method .
|
||||
$this->get( false );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the legacy column setup exists
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function has_setup_column(): bool {
|
||||
global $wpdb;
|
||||
$table_name = $wpdb->prefix . 'burst_goals';
|
||||
return (bool) $wpdb->get_var( "SHOW COLUMNS FROM $table_name LIKE 'setup'" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a goal and its statistics
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function delete(): bool {
|
||||
global $wpdb;
|
||||
$table_name = $wpdb->prefix . 'burst_goals';
|
||||
$result1 = $wpdb->delete( $table_name, [ 'ID' => $this->id ] );
|
||||
|
||||
$table_name_statistics = $wpdb->prefix . 'burst_goal_statistics';
|
||||
$result2 = $wpdb->delete( $table_name_statistics, [ 'goal_id' => $this->id ] );
|
||||
|
||||
// Check if both delete queries were successful
|
||||
return $result1 !== false && $result2 !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add predefined goal
|
||||
*
|
||||
* @param string $id
|
||||
*
|
||||
* @return burst_goal|bool
|
||||
*/
|
||||
public function add_predefined( string $id ): burst_goal {
|
||||
if ( ! burst_user_can_manage() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$id = sanitize_title( $id );
|
||||
$goals = BURST()->goals->get_predefined_goals();
|
||||
// filter out our goal by id
|
||||
$filtered_goals = array_filter(
|
||||
$goals,
|
||||
static function ( $goal ) use ( $id ) {
|
||||
return $goal['id'] === $id;
|
||||
}
|
||||
);
|
||||
|
||||
if ( count( $filtered_goals ) === 0 ) {
|
||||
return false;
|
||||
}
|
||||
// get first element of array
|
||||
$goal = array_shift( $filtered_goals );
|
||||
unset( $goal['id'], $goal['description'] );
|
||||
// add each item of this array to the current burst_goal object
|
||||
foreach ( $goal as $name => $value ) {
|
||||
if ( property_exists( $this, $name ) ) {
|
||||
$this->{$name} = $value;
|
||||
}
|
||||
}
|
||||
$this->save();
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitize a goal type
|
||||
*
|
||||
* @param mixed $type
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function sanitize_type( $type ): string {
|
||||
$available_goal_types = $this->get_available_goal_types();
|
||||
return isset( $available_goal_types[ $type ] ) ? $type : 'clicks';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a new goal can be added
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function can_add_goal(): bool {
|
||||
if ( burst_is_pro() ) {
|
||||
// @todo add licensing
|
||||
return true; // Allow unlimited goals in the pro version
|
||||
}
|
||||
|
||||
global $wpdb;
|
||||
// Check for existing active goals in the database
|
||||
$existing_goals = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}burst_goals", ARRAY_A );
|
||||
return count( $existing_goals ) <= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitize a metric
|
||||
*
|
||||
* @param mixed $metric
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function sanitize_metric( $metric ): string {
|
||||
$available_metrics = [ 'pageviews', 'visitors', 'sessions' ];
|
||||
return in_array( $metric, $available_metrics, true ) ? $metric : 'visitors';
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitize status
|
||||
*
|
||||
* @param mixed $status
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function sanitize_status( $status ): string {
|
||||
$statuses = array(
|
||||
'all',
|
||||
'active',
|
||||
'inactive',
|
||||
'archived',
|
||||
);
|
||||
return in_array( $status, $statuses, true ) ? $status : 'inactive';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the goal types. These are an option list from the goal_fields array
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function get_available_goal_types(): array {
|
||||
$fields = burst_goal_fields();
|
||||
// from the fields array, get the entry where id = 'type'
|
||||
$type_field = array_filter(
|
||||
$fields,
|
||||
static function ( $goal ) {
|
||||
return isset( $goal['id'] ) && $goal['id'] === 'type';
|
||||
}
|
||||
);
|
||||
|
||||
$type_field = reset( $type_field );
|
||||
return apply_filters( 'burst_goal_types', $type_field['options'] );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
defined( 'ABSPATH' ) or die();
|
||||
|
||||
if ( ! class_exists( "burst_goals_tracker" ) ) {
|
||||
class burst_goals_tracker {
|
||||
public function __construct() {
|
||||
add_action( 'init', array( $this, 'add_dynamic_hooks' ) );
|
||||
|
||||
}
|
||||
|
||||
public function add_dynamic_hooks(): void {
|
||||
$goals = burst_get_active_goals( true );
|
||||
require_once burst_path . 'goals/class-goal.php';
|
||||
foreach ( $goals as $goal ) {
|
||||
$goal = new burst_goal( $goal['ID'] );
|
||||
if ( $goal->type !== 'hook' ) {
|
||||
continue;
|
||||
}
|
||||
$hook = $goal->hook;
|
||||
if ( $hook ) {
|
||||
add_action( $hook, function() use ( $hook ) {
|
||||
$this->handle_hook( $hook );
|
||||
} );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the goal by hook name
|
||||
*
|
||||
* @param string $find_hook_name
|
||||
*
|
||||
* @return burst_goal|bool
|
||||
*/
|
||||
public function get_goal_by_hook_name( string $find_hook_name ) {
|
||||
$goals = burst_get_active_goals( true );
|
||||
require_once burst_path . 'goals/class-goal.php';
|
||||
|
||||
foreach ( $goals as $goal ) {
|
||||
$goal = new burst_goal( $goal['ID'] );
|
||||
if ( $goal->type !== 'hook' ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$hook = $goal->hook;
|
||||
if ( $hook === $find_hook_name ) {
|
||||
return $goal;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the execution of a hook as goal achieved
|
||||
*
|
||||
* @param string $hook_name
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle_hook( string $hook_name ): void {
|
||||
|
||||
// get cookie burst_uid
|
||||
$burst_uid = isset( $_COOKIE['burst_uid'] ) ? burst_sanitize_uid( $_COOKIE['burst_uid'] ) : false;
|
||||
// we assume there has at least been one interaction clientside, so there should be a uid.
|
||||
if ( $burst_uid ) {
|
||||
$statistic = burst_get_last_user_statistic( $burst_uid, false );
|
||||
$statistic_id = $statistic['ID'] ?? false;
|
||||
if ( ! $statistic_id ) {
|
||||
return;
|
||||
}
|
||||
$page_url = $statistic['page_url'] ?? '';
|
||||
$parameters = $statistic['parameters'] ?? '';
|
||||
$page_url .= $parameters;
|
||||
//get the goal by $hook_name.
|
||||
$goal = $this->get_goal_by_hook_name( $hook_name );
|
||||
if ( ! $goal ) {
|
||||
return;
|
||||
}
|
||||
//if the goal should be tracked on a specific page only, check if the current page is the page to track.
|
||||
if ( $goal->page_or_website === 'page' ) {
|
||||
//this is a relative url
|
||||
$tracking_page = $goal->specific_page;
|
||||
if ( !empty( $page_url ) && strpos( $page_url, $tracking_page ) === false ) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$goal_arr = array(
|
||||
'goal_id' => $goal->id,
|
||||
'statistic_id' => $statistic_id,
|
||||
);
|
||||
|
||||
burst_create_goal_statistic( $goal_arr );
|
||||
} else {
|
||||
burst_error_log( 'No burst_uid found in handle_hook' );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
<?php
|
||||
defined( 'ABSPATH' ) or die( 'you do not have access to this page!' );
|
||||
|
||||
if ( ! class_exists( 'burst_goals' ) ) {
|
||||
class burst_goals {
|
||||
public function __construct() {
|
||||
}
|
||||
|
||||
public function sanitize_orderby( $orderby ) {
|
||||
global $wpdb;
|
||||
|
||||
// Get all columns from {$wpdb->prefix}burst_goals table
|
||||
$table_name = $wpdb->prefix . 'burst_goals';
|
||||
$cols = $wpdb->get_results( "SHOW COLUMNS FROM $table_name", ARRAY_A );
|
||||
|
||||
// Extract the 'Field' values into an array
|
||||
$col_names = array_column( $cols, 'Field' );
|
||||
|
||||
// If $orderby is not in $col_names, set it to 'ID'
|
||||
if ( ! in_array( $orderby, $col_names, true ) ) {
|
||||
$orderby = 'ID';
|
||||
}
|
||||
|
||||
return $orderby;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get predefined goals from the integrations list
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_predefined_goals(): array {
|
||||
global $burst_integrations_list;
|
||||
$predefined_goals = [];
|
||||
foreach ( $burst_integrations_list as $plugin => $details ) {
|
||||
if ( ! isset( $details['goals'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( ! burst_integration_plugin_is_active( $plugin, true ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$predefined_goals = array_merge( $details['goals'], $predefined_goals );
|
||||
}
|
||||
|
||||
return $predefined_goals;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of goals
|
||||
*
|
||||
* @param $args
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_goals( array $args = [] ): array {
|
||||
if ( ! burst_user_can_view() ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
global $wpdb;
|
||||
$default_args = array(
|
||||
'status' => 'all',
|
||||
'limit' => 9999,
|
||||
'offset' => 0,
|
||||
'orderby' => 'ID',
|
||||
'order' => 'ASC',
|
||||
);
|
||||
// merge args
|
||||
$args = wp_parse_args( $args, $default_args );
|
||||
|
||||
// sanitize args
|
||||
$args['order'] = $args['order'] === 'DESC' ? 'DESC' : 'ASC';
|
||||
$args['orderby'] = $this->sanitize_orderby( $args['orderby'] );
|
||||
require_once burst_path . 'goals/class-goal.php';
|
||||
$goal = new burst_goal();
|
||||
$args['status'] = $goal->sanitize_status( $args['status'] );
|
||||
$args['limit'] = (int) $args['limit'];
|
||||
$args['offset'] = (int) $args['offset'];
|
||||
|
||||
$query = "SELECT * FROM {$wpdb->prefix}burst_goals";
|
||||
$where = array();
|
||||
if ( $args['status'] !== 'all' ) {
|
||||
$where[] = $wpdb->prepare( 'status = %s', $args['status'] );
|
||||
}
|
||||
if ( ! empty( $where ) ) {
|
||||
$query .= ' WHERE ' . implode( ' AND ', $where );
|
||||
}
|
||||
|
||||
$query .= " ORDER BY {$args['orderby']} {$args['order']}";// can only be columns or DESC/ASC because of sanitizing
|
||||
$query .= " LIMIT {$args['offset']}, {$args['limit']}"; // can only be integer because of sanitizing
|
||||
|
||||
$results = $wpdb->get_results( $query, ARRAY_A );
|
||||
|
||||
$goals = array_reduce(
|
||||
$results,
|
||||
static function ( $accumulator, $currentValue ) {
|
||||
$id = $currentValue['ID'];
|
||||
unset( $currentValue['ID'] );
|
||||
$accumulator[ $id ] = $currentValue;
|
||||
return $accumulator;
|
||||
},
|
||||
array()
|
||||
);
|
||||
|
||||
// loop through goals and add the fields and get then object for each goal
|
||||
require_once burst_path . 'goals/class-goal.php';
|
||||
$objects = array();
|
||||
foreach ( $goals as $goal_id => $goal ) {
|
||||
$goal = new burst_goal( $goal_id );
|
||||
$objects[] = $goal;
|
||||
}
|
||||
|
||||
return $objects;
|
||||
}
|
||||
} // class closure
|
||||
|
||||
} // class exists closure
|
||||
|
||||
/**
|
||||
* Install goal table
|
||||
* */
|
||||
|
||||
add_action( 'burst_install_tables', 'burst_install_goals_table', 10 );
|
||||
function burst_install_goals_table() {
|
||||
if ( get_option( 'burst_goals_db_version' ) !== burst_version ) {
|
||||
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
|
||||
|
||||
global $wpdb;
|
||||
$charset_collate = $wpdb->get_charset_collate();
|
||||
$table_name = $wpdb->prefix . 'burst_goals';
|
||||
$sql = "CREATE TABLE $table_name (
|
||||
`ID` int NOT NULL AUTO_INCREMENT,
|
||||
`title` varchar(255) NOT NULL,
|
||||
`type` varchar(30) NOT NULL,
|
||||
`status` varchar(30) NOT NULL,
|
||||
`server_side` tinyint NOT NULL,
|
||||
`url` varchar(255) NOT NULL,
|
||||
`conversion_metric` varchar(255) NOT NULL,
|
||||
`date_created` int NOT NULL,
|
||||
`date_start` int NOT NULL,
|
||||
`date_end` int NOT NULL,
|
||||
`attribute` varchar(255) NOT NULL,
|
||||
`attribute_value` varchar(255) NOT NULL,
|
||||
`hook` varchar(255) NOT NULL,
|
||||
PRIMARY KEY (ID)
|
||||
) $charset_collate;";
|
||||
dbDelta( $sql );
|
||||
|
||||
// insert default goal
|
||||
update_option( 'burst_goals_db_version', burst_version, false );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
// Silence is golden.
|
||||
Reference in New Issue
Block a user