<?php
if (!defined('ABSPATH'))
die('No direct access allowed');
final class WOOF_EXT_STAT extends WOOF_EXT {
private $table_stat_buffer = 'woof_stat_buffer';
private $table_stat_tmp = 'woof_stat_tmp';
public $type = 'application';
public $folder_name = 'stat'; //should be defined!!
//***
public $is_enabled = false;
public $cache_folder = '';
public $items_for_stat = array();
public $user_max_requests = 10;
public $request_max_deep = 5;
public $pdo = NULL; //for stat asembling
public $cron_system = 0; //wp by default
public $cron = NULL;
public $wp_cron_period = 'daily';
public $max_items_per_graph = 10;
public $updated_table = false;
public $meta_keys = array();
//***
public function __construct() {
parent::__construct();
global $wpdb;
$this->table_stat_buffer = $wpdb->prefix . $this->table_stat_buffer;
$this->table_stat_tmp = $wpdb->prefix . $this->table_stat_tmp;
//***
if (isset($this->woof_settings['woof_stat']['is_enabled'])) {
$this->is_enabled = (bool) $this->woof_settings['woof_stat']['is_enabled'];
}
//****
$this->updated_table = get_option('woof_stat_updated_table', false);
if (!$this->updated_table) {
global $wpdb;
$table_name = $this->table_stat_tmp;
if ($wpdb->get_var("SHOW TABLES LIKE '$table_name'") != $table_name) {
update_option('woof_stat_updated_table', true);
}
}
//***
$cache_folder = '_woof_stat_cache';
if (isset($this->woof_settings['woof_stat']['cache_folder']) AND!empty($this->woof_settings['woof_stat']['cache_folder'])) {
$cache_folder = sanitize_title($this->woof_settings['woof_stat']['cache_folder']);
}
//***
if (isset($this->woof_settings['woof_stat']['items_for_stat']) AND!empty($this->woof_settings['woof_stat']['items_for_stat'])) {
$this->items_for_stat = (array) $this->woof_settings['woof_stat']['items_for_stat'];
}
//***
if (isset($this->woof_settings['woof_stat']['user_max_requests']) AND!empty($this->woof_settings['woof_stat']['user_max_requests'])) {
$this->user_max_requests = intval($this->woof_settings['woof_stat']['user_max_requests']);
if ($this->user_max_requests <= 0) {
$this->user_max_requests = 10;
}
}
//***
if (isset($this->woof_settings['woof_stat']['request_max_deep']) AND!empty($this->woof_settings['woof_stat']['request_max_deep'])) {
$this->request_max_deep = intval($this->woof_settings['woof_stat']['request_max_deep']);
if ($this->request_max_deep <= 0) {
$this->request_max_deep = 5;
}
}
//***
if (isset($this->woof_settings['woof_stat']['cron_system']) AND!empty($this->woof_settings['woof_stat']['cron_system'])) {
$this->cron_system = intval($this->woof_settings['woof_stat']['cron_system']);
}
//***
if (isset($this->woof_settings['woof_stat']['wp_cron_period']) AND!empty($this->woof_settings['woof_stat']['wp_cron_period'])) {
$this->wp_cron_period = $this->woof_settings['woof_stat']['wp_cron_period'];
}
//***
if (isset($this->woof_settings['woof_stat']['max_items_per_graph']) AND!empty($this->woof_settings['woof_stat']['max_items_per_graph'])) {
$max_items_per_graph = (int) $this->woof_settings['woof_stat']['max_items_per_graph'];
if ($max_items_per_graph > 0) {
$this->max_items_per_graph = $max_items_per_graph;
}
}
//***
$this->cache_folder = WP_CONTENT_DIR . '/' . $cache_folder . '/';
add_filter('woof_get_request_data', array($this, 'woof_get_request_data'));
$this->meta_keys = $this->get_meta_keys();
//***
$this->init();
//***
if ($this->is_enabled) {
$this->cron = new PN_WP_CRON_WOOF('woof_stat_cron');
$this->init_pdo();
//***
if ($this->cron_system === 1) {
$this->woof_stat_wpcron_init(true);
if (isset($_GET['woof_stat_collection'])) {
$cron_secret_key = 'woof_stat_updating';
if (isset($this->woof_settings['woof_stat']['cron_secret_key']) AND!empty($this->woof_settings['woof_stat']['cron_secret_key'])) {
$cron_secret_key = sanitize_title($this->woof_settings['woof_stat']['cron_secret_key']);
}
if ($_GET['woof_stat_collection'] === $cron_secret_key) {
$this->assemble_stat();
die('woof stat assemble done!');
}
}
} else {
add_action('woof_stat_wpcron', array($this, 'assemble_stat'), 10);
$this->woof_stat_wpcron_init();
}
}
//***
$this->get_stat_tables();
add_action('wp_ajax_woof_write_stat', array($this, 'woof_write_stat'));
add_action('wp_ajax_nopriv_woof_write_stat', array($this, 'woof_write_stat'));
add_action('wp_ajax_woof_get_operative_tables', array($this, 'get_operative_tables'));
add_action('wp_ajax_woof_get_stat_data', array($this, 'woof_get_stat_data'));
add_action('wp_ajax_woof_get_top_terms', array($this, 'woof_get_top_terms'));
add_action('wp_ajax_woof_stat_check_connection', array($this, 'woof_stat_check_connection'));
add_action('wp_ajax_woof_stat_update_db', array($this, 'woof_stat_update_db'));
}
public function get_ext_path() {
return plugin_dir_path(__FILE__);
}
public function get_ext_override_path() {
return get_stylesheet_directory() . DIRECTORY_SEPARATOR . "woof" . DIRECTORY_SEPARATOR . "ext" . DIRECTORY_SEPARATOR . $this->folder_name . DIRECTORY_SEPARATOR;
}
public function get_ext_link() {
return plugin_dir_url(__FILE__);
}
public function init() {
add_action('woof_print_applications_tabs_' . $this->folder_name, array($this, 'woof_print_applications_tabs'), 10, 1);
add_action('woof_print_applications_tabs_content_' . $this->folder_name, array($this, 'woof_print_applications_tabs_content'), 10, 1);
self::$includes['js']['woof_stat_html_items'] = $this->get_ext_link() . 'js/stat.js';
}
//ajax
public function woof_stat_check_connection() {
$pdo_options = array();
$pdo_options['host'] = sanitize_text_field(WOOF_REQUEST::get('woof_stat_host'));
$pdo_options['host_db_name'] = sanitize_text_field(WOOF_REQUEST::get('woof_stat_name'));
$pdo_options['host_user'] = sanitize_text_field(WOOF_REQUEST::get('woof_stat_user'));
$pdo_options['host_pass'] = sanitize_text_field(WOOF_REQUEST::get('woof_stat_pswd'));
try {
$this->pdo = new PDO("mysql:host={$pdo_options['host']};dbname={$pdo_options['host_db_name']}", $pdo_options['host_user'], $pdo_options['host_pass']);
} catch (PDOException $e) {
die(esc_html__("Database not connected! ERROR! ", 'woocommerce-products-filter'));
}
die(esc_html__("Database successfully connected!!!", 'woocommerce-products-filter'));
}
public function woof_stat_update_db() {
global $wpdb;
$row = $wpdb->get_results("SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = '" . $this->table_stat_buffer . "' AND column_name = 'meta_value'");
if (empty($row)) {
$result = $wpdb->query("ALTER TABLE " . $this->table_stat_buffer . " ADD meta_value text COLLATE utf8_unicode_ci NOT NULL");
if ($result === false) {
die(esc_html__("Somthing wrong!", 'woocommerce-products-filter'));
}
}
update_option('woof_stat_updated_table', true);
die(esc_html__("Database successfully updated!!!", 'woocommerce-products-filter'));
}
public function woof_print_applications_tabs() {
?>
<li>
<a href="#tabs-stat">
<span class="icon-chart-bar"></span>
<span><?php esc_html_e("Statistic", 'woocommerce-products-filter') ?></span>
</a>
</li>
<?php
}
public function woof_print_applications_tabs_content() {
//woof_stat_calendar_date_format, woof_stat_week_first_day
wp_enqueue_script('woof_google_charts', 'https://www.gstatic.com/charts/loader.js');
wp_enqueue_script('jquery-ui-core');
//***
$data = array();
$data['stat_min_date'] = $this->get_stat_min_date_db();
//***
wp_register_script('woof_stat', $this->get_ext_link() . 'js/admin.js');
wp_enqueue_style('woof_stat-css', $this->get_ext_link() . 'css/stat.css', array(), WOOF_VERSION);
$localize_script = array(
'calendar_date_format' => 'DD, d MM, yy',
'week_first_day' => get_option('start_of_week'),
'max_items_per_graph' => $this->max_items_per_graph,
'woof_stat_leave_empty' => esc_html__('leave it empty to see all terms', 'woocommerce-products-filter'),
'woof_stat_sel_date_range' => esc_html__('Select date range for statistic!', 'woocommerce-products-filter'),
'woof_stat_calc' => esc_html__('Statistic calculation ...', 'woocommerce-products-filter'),
'woof_stat_get_oper_tbls' => esc_html__('getting of operative tables ...', 'woocommerce-products-filter'),
'woof_stat_oper_tbls_prep' => esc_html__('operative tables are prepared', 'woocommerce-products-filter'),
'woof_stat_getting_dftbls' => esc_html__('getting the data from the table', 'woocommerce-products-filter'),
'woof_stat_done' => esc_html__('done!', 'woocommerce-products-filter'),
'woof_stat_no_data' => esc_html__('No data for the selected time period!', 'woocommerce-products-filter'),
'woof_stat_google' => esc_html__('Google charts library not loaded! If site is on localhost just disable statistic extension in tab Extensions!', 'woocommerce-products-filter'),
'woof_stat_graphs' => esc_html__('drawing graphs ...', 'woocommerce-products-filter'),
'woof_stat_finished' => esc_html__('finished!', 'woocommerce-products-filter'),
'woof_stat_troubles' => esc_html__('Looks like troubles with JavaScript!', 'woocommerce-products-filter')
);
if (isset($data['stat_min_date'][0])) {
$localize_script['min_year'] = $data['stat_min_date'][0];
$localize_script['min_month'] = $data['stat_min_date'][1];
} else {
$localize_script['min_year'] = date('Y');
$localize_script['min_month'] = date('n');
}
wp_localize_script('woof_stat', 'woof_stat_vars', $localize_script);
wp_enqueue_script('woof_stat', array('jquery', 'jquery-ui-core'), [], WOOF_VERSION);
//***
if (!extension_loaded('pdo_mysql')) {
?>
<div class="error">
<p class="description">
<?php
printf(__('PHP extension PDO_MYSQL is not enabled on your server, not possible to collect statistic data! Contact your hosting support to about enabling PDO_MYSQL.', 'woocommerce-products-filter'));
?>
</p>
</div>
<?php
}
$min_memory_mb = 268435456;
$memory = wc_let_to_num(WP_MEMORY_LIMIT);
if (function_exists('memory_get_usage')) {
$system_memory = wc_let_to_num(@ini_get('memory_limit'));
$memory = max($memory, $system_memory);
}
if (version_compare($memory, $min_memory_mb, '<')) {
?>
<div class="error">
<p class="description">
<?php
printf(__('Very recommend for the statistic not less than %s of the memory to avoid malfunctionality. Now is on the site %s', 'woocommerce-products-filter'), size_format($min_memory_mb), size_format($memory));
?>
</p>
</div>
<?php
}
//***
$data['table_stat_buffer'] = $this->table_stat_buffer;
$data['table_stat_tmp'] = $this->table_stat_tmp;
$data['folder_name'] = $this->folder_name;
$data['woof_settings'] = $this->woof_settings;
$data['updated_table'] = $this->updated_table;
woof()->render_html_e($this->get_ext_path() . 'views/tabs_content.php', $data);
}
public function init_pdo() {
if (isset($this->woof_settings['woof_stat']['server_options'])) {
if (extension_loaded('pdo_mysql')) {
$pdo_options = $this->woof_settings['woof_stat']['server_options'];
if (!empty($pdo_options['host']) AND!empty($pdo_options['host_db_name']) AND!empty($pdo_options['host_user']) AND!empty($pdo_options['host_pass'])) {
try {
$this->pdo = new PDO("mysql:host={$pdo_options['host']};dbname={$pdo_options['host_db_name']}", $pdo_options['host_user'], $pdo_options['host_pass']);
} catch (Exception $e) {
?>
<div class="error">
<p class="description">
<?php
printf(__('Wrong data for "Server options for statistic stock" options', 'woocommerce-products-filter'));
?>
</p>
</div>
<?php
}
}
}
}
}
public function get_woof_cron_schedules($key = '') {
$schedules = array(
'hourly' => HOUR_IN_SECONDS,
'twicedaily' => HOUR_IN_SECONDS * 12,
'daily' => DAY_IN_SECONDS,
'week' => WEEK_IN_SECONDS,
'month' => WEEK_IN_SECONDS * 4,
'min1' => MINUTE_IN_SECONDS,
);
if (!empty($key)) {
return $schedules[$key];
}
return $schedules;
}
public function woof_stat_wpcron_init($reset = false) {
$hook = 'woof_stat_wpcron';
if ($reset) {
$this->cron->remove($hook);
return;
}
if ($this->cron_system === 0) {//wp cron
if (!$this->cron->is_attached($hook, $this->get_woof_cron_schedules($this->wp_cron_period))) {
$this->cron->attach($hook, time(), $this->get_woof_cron_schedules($this->wp_cron_period));
}
$this->cron->process();
}
}
//ajax
public function woof_write_stat() {
WOOF_REQUEST::set('woof_products_doing', 1);
$_GET = WOOF_REQUEST::get('woof_products_doing');
if ($this->is_enabled AND!is_null($this->pdo)) {
$this->woof_get_request_data(WOOF_REQUEST::get('woof_current_values'));
$this->cron->process();
} else {
esc_html_e('stat is not activated or PDO not inited', 'woocommerce-products-filter');
}
exit;
}
//ajax
public function get_operative_tables() {
if (current_user_can('create_users')) {
$calendar_from = intval(WOOF_REQUEST::get('calendar_from'));
$calendar_from = mktime(0, 0, 0, date('n', $calendar_from), date('d', $calendar_from), date('y', $calendar_from));
$calendar_to = intval(WOOF_REQUEST::get('calendar_to'));
$calendar_to = mktime(23, 59, 59, date('n', $calendar_to), date('d', $calendar_to), date('y', $calendar_to));
//+++
$tables = $this->get_stat_tables();
$request_tables = array();
$start_year = date('Y', $calendar_from);
$start_month = date('n', $calendar_from);
$finish_year = date('Y', $calendar_to);
$finish_month = date('n', $calendar_to);
//***
$current_y = $start_year;
$current_m = $start_month;
while (true) {
$t = $current_y . '_' . $current_m;
if (in_array($t, $tables)) {
$request_tables[] = $t;
}
if ($current_y >= $finish_year AND $current_m >= $finish_month) {
break;
}
$current_m++;
if ($current_m > 12) {
$current_m = 1;
$current_y++;
}
}
die(json_encode($request_tables));
}
die('not permitted');
}
//ajax
public function woof_get_stat_data() {
if (current_user_can('create_users')) {
$table = sanitize_text_field(WOOF_REQUEST::get('table'));
$calendar_from = intval(WOOF_REQUEST::get('calendar_from'));
$calendar_from = mktime(0, 0, 0, date('n', $calendar_from), date('d', $calendar_from), date('y', $calendar_from));
$calendar_to = intval(WOOF_REQUEST::get('calendar_to'));
$calendar_to = mktime(23, 59, 59, date('n', $calendar_to), date('d', $calendar_to), date('y', $calendar_to));
$taxonomies = array();
foreach (woof()->get_taxonomies() as $slug => $t) {
//missing taxonomies which are not selected in the stat options
if (!in_array(urldecode($slug), $this->items_for_stat)) {
continue;
}
//+++
$custom_name = '';
if (isset(woof()->settings['custom_tax_label'][$slug])) {
$custom_name = WOOF_HELPER::wpml_translate(null, woof()->settings['custom_tax_label'][$slug], 0);
}
if (!empty($custom_name)) {
$taxonomies[urldecode($slug)] = $custom_name;
} else {
$taxonomies[urldecode($slug)] = $t->labels->name;
}
}
$search_template = (array) WOOF_REQUEST::get('request_snippets');
$tax_array = array_keys($search_template);
if (!empty($search_template)) {
//this for under dev feature for working with dedicated terms, now not possible to set any terms for each taxonomy
foreach ($search_template as &$value) {
$value = explode(',', $value);
if (count($value) == 1 AND empty($value[0])) {
$value = array();
}
}
}
//+++
if (!is_null($this->pdo)) {
$sql = "SELECT taxonomy,value FROM {$table} WHERE time>=:calendar_from AND time<=:calendar_to";
//+++
if (!empty($tax_array)) {
$sql = "SELECT hash,taxonomy,value FROM {$table} WHERE time>=:calendar_from AND time<=:calendar_to";
$sql_tale = " AND (";
foreach ($tax_array as $k => $tax_slug) {
if ($k > 0) {
$sql_tale .= " OR ";
}
$sql_tale .= "taxonomy='" . $tax_slug . "'";
}
$sql_tale .= ')';
$sql .= $sql_tale;
}
//+++
$sth = $this->pdo->prepare($sql);
$sth->bindParam(':calendar_from', $calendar_from, PDO::PARAM_INT);
$sth->bindParam(':calendar_to', $calendar_to, PDO::PARAM_INT);
$sth->execute();
$operative_data1 = $sth->fetchAll(PDO::FETCH_ASSOC);
//if db table is empty
if (empty($operative_data1)) {
die(json_encode(array(), JSON_UNESCAPED_UNICODE));
}
//+++
if (empty($search_template)) {
//get top of terms
$operative_data2 = array();
if (!empty($operative_data1)) {
foreach ($operative_data1 as $block) {
if ($block['taxonomy'] == 'min_price' OR $block['taxonomy'] == 'max_price') {
continue;
}
//+++
$t = urldecode($block['taxonomy']);
$v = $block['value'];
//+++
if (!isset($operative_data2[$t])) {
$operative_data2[$t] = array();
}
if (!isset($operative_data2[$t][$v])) {
$operative_data2[$t][$v] = 0;
}
$operative_data2[$t][$v] += 1;
}
foreach ($operative_data2 as &$b) {
asort($b, SORT_NUMERIC);
}
die(json_encode($operative_data2, JSON_UNESCAPED_UNICODE));
}
} else {
$operative_data2 = array(); //grouping by hash key
if (!empty($operative_data1)) {
foreach ($operative_data1 as $key => $value) {
if ($value['taxonomy'] == 'min_price' OR $value['taxonomy'] == 'max_price') {
unset($operative_data1[$key]);
continue;
}
$value['taxonomy'] = urldecode($value['taxonomy']);
if (in_array($value['taxonomy'], $tax_array)) {
$tmp = $value;
unset($tmp['hash']);
$operative_data2[$value['hash']][] = $tmp;
unset($operative_data1[$key]); //remove it from memory
}
}
//***
$operative_data3 = array();
$search_template_count = count($search_template);
//+++
foreach ($operative_data2 as $key => $value) {
if (count($value) === $search_template_count) {
$is = true;
$tax_should_be = array_flip($tax_array);
foreach ($value as &$item) {
if ($item['value'] == 0) {
$is = false;
break;
}
if (class_exists('WOOF_META_FILTER') AND in_array($item['taxonomy'], $this->meta_keys)) {
$item['tax_name'] = WOOF_META_FILTER::get_meta_filter_name($item['taxonomy']);
$item['value_name'] = WOOF_META_FILTER::get_meta_filter_option_name($item['taxonomy'], $item['value']);
} else {
$item['tax_name'] = $taxonomies[$item['taxonomy']];
$t = get_term_by('id', $item['value'], $item['taxonomy']);
$item['value_name'] = $t->name;
}
unset($tax_should_be[$item['taxonomy']]);
}
//+++
if (!empty($tax_should_be)) {
$is = false;
}
//+++
if ($is) {
if (!empty($value)) {
$tmp = array();
foreach ($value as $it) {
$tmp[$it['taxonomy']] = $it;
}
//+++
ksort($tmp, SORT_STRING);
$tmp2 = array();
foreach ($tmp as $it) {
$tmp2[] = $it;
}
$operative_data3[] = $tmp2;
}
}
}
}
}
$operative_data4 = array();
if (!empty($operative_data3)) {
foreach ($operative_data3 as $v) {
$k4 = "";
$vn4 = "";
$tn4 = "";
foreach ($v as $kk => $vv) {
if ($kk > 0) {
$k4 .= "_";
$tn4 .= "+";
$vn4 .= " - ";
}
$k4 .= $vv['value'];
$tn4 .= $vv['tax_name'];
$vn4 .= $vv['value_name'];
}
$operative_data4[$k4]['val'] += 1;
$operative_data4[$k4]['tname'] = $tn4;
$operative_data4[$k4]['vname'] = $vn4;
}
}
//***
usort($operative_data4, array($this, "cmp"));
die(json_encode($operative_data4, JSON_UNESCAPED_UNICODE));
}
}
}
die('PHP PDO ext is not activated!');
}
//ajax
public function woof_get_top_terms() {
if (current_user_can('create_users')) {
$stat_data = WOOF_REQUEST::get('woof_stat_data');
$taxonomies = array();
foreach (woof()->get_taxonomies() as $slug => $t) {
//missing taxonomies which are not selected in the stat options
if (!in_array(urldecode($slug), $this->items_for_stat)) {
continue;
}
//+++
$custom_name = '';
if (isset(woof()->settings['custom_tax_label'][$slug])) {
$custom_name = WOOF_HELPER::wpml_translate(null, woof()->settings['custom_tax_label'][$slug], 0);
}
if (!empty($custom_name)) {
$taxonomies[urldecode($slug)] = $custom_name;
} else {
$taxonomies[urldecode($slug)] = $t->labels->name;
}
}
//meta filter
if (class_exists('WOOF_META_FILTER')) {
$meta_keys = array();
$meta_fields = $this->woof_settings['meta_filter'];
if (!empty($meta_fields)) {
foreach ($meta_fields as $key => $meta) {
if ($meta['meta_key'] == "__META_KEY__") {
continue;
}
$slug = $meta["search_view"] . "_" . $meta['meta_key'];
if (!in_array($slug, $this->items_for_stat)) {
continue;
}
$meta_keys[] = $slug;
$taxonomies[urldecode($slug)] = WOOF_HELPER::wpml_translate(null, $meta['title'], 0);
}
}
}
//***
if (!empty($stat_data)) {
$operative_data1 = array();
if (count($stat_data) > 1) {
$operative_data1 = $stat_data[0];
foreach ($stat_data as $i => $block) {
if ($i == 0) {
continue;
}
//+++
if (!empty($block)) {
foreach ($block as $tax_slug => $terms) {
if (!empty($terms)) {
foreach ($terms as $term_id => $count) {
if (!isset($operative_data1[$tax_slug])) {
$operative_data1[$tax_slug] = array();
}
if (!isset($operative_data1[$tax_slug][$term_id])) {
$operative_data1[$tax_slug][$term_id] = 0;
}
$operative_data1[$tax_slug][$term_id] += $count;
}
}
}
}
}
} else {
$operative_data1 = $stat_data[0];
}
$block_tax_diff = array();
$block_tax_each = array();
foreach ($operative_data1 as $tax_slug => $terms) {
if (isset($taxonomies[$tax_slug])) {
$tn = $taxonomies[$tax_slug];
foreach ($terms as $term_id => $count) {
if (!isset($block_tax_diff[$tn])) {
$block_tax_diff[$tn] = 0;
}
$block_tax_diff[$tn] += $count;
}
} else {
}
}
asort($block_tax_diff, SORT_NUMERIC);
$block_tax_diff = array_reverse($block_tax_diff, true);
//+++
foreach ($operative_data1 as $tax_slug => $block) {
asort($block, SORT_NUMERIC);
$block = array_reverse($block, true);
//$block = array_slice($block, 0, $this->max_items_per_graph, true);
if (isset($taxonomies[$tax_slug])) {
$block_tax_each[$tax_slug]['tax_name'] = $taxonomies[$tax_slug];
$block_tax_each[$tax_slug]['terms'] = array();
if (!empty($block)) {
if (class_exists('WOOF_META_FILTER')) {
if (in_array($tax_slug, $meta_keys)) {
foreach ($block as $term_id => $count) {
$val_name = WOOF_META_FILTER::get_meta_filter_option_name($tax_slug, $term_id);
if ($val_name) {
$block_tax_each[$tax_slug]['terms'][$val_name] = $count;
} else {
$block_tax_each[$tax_slug]['terms'][$term_id] = $count;
}
}
continue;
}
}
foreach ($block as $term_id => $count) {
$t = get_term_by('id', $term_id, $tax_slug);
if (!empty($t->name)) {
$block_tax_each[$tax_slug]['terms'][$t->name] = $count;
}
}
}
}
}
die(json_encode(array($block_tax_diff, $block_tax_each), JSON_UNESCAPED_UNICODE));
}
}
}
private function cmp($a, $b) {
return $a["val"] < $b["val"];
}
//writing all search request from the customers
public function woof_get_request_data($data) {
if (!$this->is_enabled) {
return $data;
}
//***
global $wpdb;
static $done = false;
$do = true;
if (defined('DOING_AJAX') && !WOOF_REQUEST::isset('woof_products_doing')) {
$do = false;
}
if (!woof()->is_isset_in_request_data(woof()->get_swoof_search_slug(), FALSE)) {
$do = false;
}
if ($done) {
$do = false;
}
//***
if ($do) {
$user_ip = $this->get_the_user_ip();
$type = 'shop';
$tax_page = '';
$tax_page_term_id = 0;
if (woof()->is_really_current_term_exists()) {
$t = woof()->get_really_current_term();
$type = 'tax_page';
if (isset($t->taxonomy)) {
$tax_page = $t->taxonomy;
$tax_page_term_id = $t->term_id;
}
}
$request = $data;
//disable unnecessary data
unset($request[woof()->get_swoof_search_slug()]);
unset($request['paged']);
unset($request['page']);
unset($request['orderby']);
unset($request['min_rating']);
unset($request['currency']);
//***
$this->items_for_stat[] = 'really_curr_tax';
if (!empty($request)) {
foreach ($request as $key => $value) {
$slug = urldecode($key);
if (!in_array($slug, $this->items_for_stat)) {
unset($request[$slug]);
}
}
}
if (!empty($request) AND ( $this->get_user_requests_count($user_ip) < $this->user_max_requests)) {
//lets control here max deep
if (count($request) > $this->request_max_deep) {
$new_request = array();
$tmp_data = array();
if (isset($request['min_price']) AND in_array('min_price', $this->items_for_stat)) {
$tmp_data['min_price'] = $request['min_price'];
}
if (isset($request['max_price']) AND in_array('max_price', $this->items_for_stat)) {
$tmp_data['max_price'] = $request['max_price'];
}
//+++
$counter = 0;
foreach ($request as $key => $value) {
if ($counter > $this->request_max_deep) {
break;
}
$slug = urldecode($key);
$new_request[$slug] = urldecode($value);
if ($slug != 'min_price' AND $slug != 'max_price' AND $slug != 'really_curr_tax') {
$counter++;
}
}
$request = array_merge($new_request, $tmp_data);
}
//***
$hash = md5(json_encode($request) . $user_ip . date('d-m-Y'));
unset($request['really_curr_tax']);
//lets check for the same request from the same user
$data_sql = array(
array(
'type' => 'string',
'val' => $user_ip,
),
array(
'type' => 'string',
'val' => $hash,
)
);
$the_same_hash = $wpdb->get_var(WOOF_HELPER::woof_prepare("SELECT hash FROM $this->table_stat_tmp WHERE user_ip = %s AND hash = %s", $data_sql));
//***
if (empty($the_same_hash)) {
$request = json_encode($request, JSON_UNESCAPED_UNICODE);
$time = time();
$data_sql = array(
array(
'type' => 'string',
'val' => $user_ip,
),
array(
'type' => 'string',
'val' => $type,
),
array(
'type' => 'string',
'val' => $request,
),
array(
'type' => 'string',
'val' => $hash,
),
array(
'type' => 'string',
'val' => $tax_page,
),
array(
'type' => 'int',
'val' => $tax_page_term_id,
),
array(
'type' => 'int',
'val' => $time,
),
);
$insert = WOOF_HELPER::woof_prepare("(%s, %s, %s, %s, %s, %d, %d)", $data_sql);
$wpdb->query("INSERT INTO {$this->table_stat_tmp} (user_ip,page,request,hash,tax_page,tax_page_term_id,time) VALUES " . $insert);
}
}
$done = true;
}
return $data;
}
//stat assembling by cron
public function assemble_stat() {
if (!$this->is_enabled) {
return;
}
//***
global $wpdb;
$terms = array();
$step_num = 0;
$step = 100;
$data_sql = array(
array(
'type' => 'int',
'val' => 0,
)
);
$count = $wpdb->get_var(WOOF_HELPER::woof_prepare("SELECT COUNT(*)
FROM {$this->table_stat_tmp} WHERE is_collected = %d
ORDER BY user_ip", $data_sql));
while (true) {
$next = $step * ($step_num + 1);
$data_sql = array(
array(
'type' => 'int',
'val' => 0,
),
array(
'type' => 'int',
'val' => $step_num,
),
array(
'type' => 'int',
'val' => $next,
),
);
$res = $wpdb->get_results(WOOF_HELPER::woof_prepare("SELECT *
FROM {$this->table_stat_tmp} WHERE is_collected = %d
LIMIT %d,%d", $data_sql), ARRAY_A);
if (!empty($res)) {
foreach ($res as $row) {
$data = json_decode($row['request'], true);
if (!empty($data)) {
foreach ($data as $taxonomy => $term_slugs) {
$terms = explode(',', $term_slugs);
foreach ($terms as $term_slug) {
$value = 0;
$meta_value = "";
$term_slug = urldecode($term_slug);
$taxonomy = urldecode($taxonomy);
$exclude = array('min_price', 'max_price');
$meta_key = array();
if (class_exists('WOOF_META_FILTER')) {
$meta_fields = $this->woof_settings['meta_filter'];
if (!empty($meta_fields)) {
foreach ($meta_fields as $key => $meta) {
if ($meta['meta_key'] == "__META_KEY__") {
continue;
}
$slug = $meta["search_view"] . "_" . $meta['meta_key'];
$meta_key[] = urldecode($slug);
$exclude = array_merge($exclude, $meta_key);
}
}
}
if (!in_array($taxonomy, $exclude)) {
if (!isset($terms[$taxonomy . '_' . $term_slug])) {
$data_sql = array(
array(
'type' => 'string',
'val' => urlencode($term_slug),
),
);
$value = (int) $wpdb->get_var(WOOF_HELPER::woof_prepare("SELECT term_id FROM {$wpdb->prefix}terms WHERE slug = %s", $data_sql));
//terms caching
$terms[$taxonomy . '_' . $term_slug] = $value;
} else {
$value = $terms[$taxonomy . '_' . $term_slug];
}
} else {
if (in_array($taxonomy, $meta_key)) {
$meta_value = $term_slug; // do that
$value = 0;
} else {
$value = $term_slug;
}
}
$data_sql = array(
array(
'type' => 'string',
'val' => $row['hash'],
),
array(
'type' => 'string',
'val' => $row['user_ip'],
),
array(
'type' => 'string',
'val' => $taxonomy,
),
array(
'type' => 'int',
'val' => $value,
),
array(
'type' => 'string',
'val' => $meta_value,
),
array(
'type' => 'string',
'val' => $row['page'],
),
array(
'type' => 'int',
'val' => $row['tax_page_term_id'],
),
array(
'type' => 'int',
'val' => $row['time'],
),
);
$insert = WOOF_HELPER::woof_prepare("(%s, %s, %s, %d,%s,%s, %d, %d)", $data_sql);
$wpdb->query("INSERT INTO {$this->table_stat_buffer} (hash,user_ip,taxonomy,value,meta_value,page,tax_page_term_id,time) VALUES " . $insert);
}
}
}
$data_sql = array(
array(
'type' => 'int',
'val' => 1,
),
array(
'type' => 'string',
'val' => $row['hash'],
),
);
$wpdb->query(WOOF_HELPER::woof_prepare("UPDATE {$this->table_stat_tmp} SET is_collected = %d WHERE hash = %s", $data_sql));
}
}
//***
if ($next > $count) {
break;
}
}
//***
$data_sql = array(
array(
'type' => 'int',
'val' => 1,
),
);
$wpdb->query(WOOF_HELPER::woof_prepare("DELETE FROM {$this->table_stat_tmp} WHERE is_collected = %d", $data_sql));
if ($this->place_statdata_into_db()) {//placing data into dedicated DB
//remove data from woof_stat
$wpdb->query("TRUNCATE TABLE {$this->table_stat_buffer}");
}
//***
return false;
}
public function place_statdata_into_db() {
if (!$this->is_enabled) {
return;
}
//***
global $wpdb;
try {
//get all distinct hash keys to get data blocks. 1 block == 1 user search request
$res = $wpdb->get_results("SELECT DISTINCT hash FROM {$this->table_stat_buffer}", ARRAY_N);
$hash_array = array();
if (!empty($res)) {
foreach ($res as $value) {
$hash_array[] = $value[0];
}
//***
foreach ($hash_array as $hash) {
$data_sql = array(
array(
'type' => 'string',
'val' => $hash,
),
);
$res = $wpdb->get_results(WOOF_HELPER::woof_prepare("SELECT * FROM {$this->table_stat_buffer} WHERE hash = %s", $data_sql), ARRAY_A);
if (!empty($res)) {
$time = $res[0]['time'];
//PDO here
if (!is_null($this->pdo)) {
$table = date('Y', $time) . '_' . date('n', $time);
$sql = "CREATE TABLE IF NOT EXISTS `{$table}` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`hash` text COLLATE utf8_unicode_ci NOT NULL,
`user_ip` text COLLATE utf8_unicode_ci NOT NULL COMMENT 'user IP',
`taxonomy` text COLLATE utf8_unicode_ci NOT NULL COMMENT 'taxonomy,price, etc ...',
`value` text COLLATE utf8_unicode_ci NOT NULL COMMENT 'value',
`page` text COLLATE utf8_unicode_ci NOT NULL COMMENT 'page',
`tax_page_term_id` int(11) NOT NULL,
`time` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;
";
$stmt = $this->pdo->prepare($sql);
$stmt->execute();
//***
$sql = "INSERT INTO {$table}(
hash,
user_ip,
taxonomy,
value,
page,
tax_page_term_id,
time) VALUES (
:hash,
:user_ip,
:taxonomy,
:value,
:page,
:tax_page_term_id,
:time)";
foreach ($res as $row) {
if (class_exists('WOOF_META_FILTER')) {
if (in_array($row['taxonomy'], $this->meta_keys)) {
if ($row['value'] == 0) {
$row['value'] = $row['meta_value'];
}
}
}
$tax = urlencode($row['taxonomy']);
$stmt = $this->pdo->prepare($sql);
$stmt->bindParam(':hash', $row['hash'], PDO::PARAM_STR);
$stmt->bindParam(':user_ip', $row['user_ip'], PDO::PARAM_STR);
$stmt->bindParam(':taxonomy', $tax, PDO::PARAM_STR);
$stmt->bindParam(':value', $row['value'], PDO::PARAM_STR);
$stmt->bindParam(':page', $row['page'], PDO::PARAM_STR);
$stmt->bindParam(':tax_page_term_id', $row['tax_page_term_id'], PDO::PARAM_INT);
$stmt->bindParam(':time', $row['time'], PDO::PARAM_INT);
$stmt->execute();
}
}
}
}
}
return true;
} catch (Exception $ex) {
return false;
}
return true;
}
public function get_stat_tables() {
if ($this->pdo) {
$sth = $this->pdo->prepare("SHOW TABLES");
$sth->execute();
return $sth->fetchAll(PDO::FETCH_COLUMN);
}
return array();
}
public function get_stat_min_date_db() {
$res = get_option('woof_stat_start_data', 0);
if (!$res) {
$res = array();
$tables = $this->get_stat_tables();
natsort($tables);
$tables = array_values($tables);
if (!empty($tables)) {
$res = explode('_', $tables[0]);
update_option('woof_stat_start_data', $res);
}
}
return $res;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public function place_statdata_into_files() {
if (!$this->is_enabled) {
return;
}
//***
global $wpdb;
$results = array();
//***
try {
//get all distinct hash keys to get data blocks. 1 block == 1 user search request
$res = $wpdb->get_results("SELECT DISTINCT hash FROM {$this->table_stat_buffer}", ARRAY_N);
$hash_array = array();
if (!empty($res)) {
foreach ($res as $value) {
$hash_array[] = $value[0];
}
//***
foreach ($hash_array as $hash) {
$data_sql = array(
array(
'type' => 'string',
'val' => $hash,
),
);
$res = $wpdb->get_results(WOOF_HELPER::woof_prepare("SELECT * FROM {$this->table_stat_buffer} WHERE hash = %s", $data_sql), ARRAY_A);
if (!empty($res)) {
$time = $res[0]['time'];
if (!isset($results[date('Y', $time)])) {
$results[date('Y', $time)] = array();
}
if (!isset($results[date('Y', $time)][date('n', $time)])) {
$results[date('Y', $time)][date('n', $time)] = array();
}
if (!isset($results[date('Y', $time)][date('n', $time)][date('d', $time)])) {
$results[date('Y', $time)][date('n', $time)][date('d', $time)] = array();
}
//remove unnecessary field time
foreach ($res as $k => $v) {
unset($res[$k]['time']);
}
$results[date('Y', $time)][date('n', $time)][date('d', $time)][] = $res;
}
}
//***
if (!empty($results)) {
foreach ($results as $year => $data1) {
foreach ($data1 as $month => $data2) {
foreach ($data2 as $day => $data3) {
if ($this->create_stat_file($year, $month, $day)) {
$this->push_data_into_file($data3, $year, $month, $day);
}
}
}
}
}
}
return true;
} catch (Exception $ex) {
return false;
}
return false;
}
private function push_data_into_file($data, $year, $month, $day) {
$yf = $this->cache_folder . $year . '/';
$mf = $yf . $month . '/';
$file = $mf . $day . '.json';
try {
clearstatcache(true, $file);
} catch (Exception $e) {
}
//***
if ($fh = fopen($file, 'a+')) {
if ($fh) {
$contents = '';
$file_size = filesize($file);
if ($file_size > 0) {
$contents = fread($fh, $file_size);
}
//***
if (!empty($contents)) {
$contents = json_decode(trim($contents), true);
if (json_last_error() === JSON_ERROR_NONE) {
$data = array_merge($contents, $data);
}
}
//***
ftruncate($fh, 0);
fwrite($fh, json_encode($data));
fclose($fh);
return true;
}
}
return false;
}
private function create_stat_file($year, $month, $day) {
$yf = $this->cache_folder . $year . '/';
$mf = $yf . $month . '/';
$file = $mf . $day . '.json';
//***
WOOF_REQUEST::set('woof_stat_errors', []);
if (!is_dir($yf)) {
if (!mkdir($yf, 0777, true)) {
WOOF_REQUEST::push('woof_stat_errors', sprintf(__('Its not possible to create folder: %s', 'woocommerce-products-filter'), $yf));
return FALSE;
}
}
if (!is_dir($mf)) {
if (!mkdir($mf, 0777, true)) {
WOOF_REQUEST::push('woof_stat_errors', sprintf(__('Its not possible to create folder: %s', 'woocommerce-products-filter'), $mf));
return FALSE;
}
}
if (!file_exists($file)) {
if ($fh = fopen($file, 'w')) {
if (!$fh) {
WOOF_REQUEST::push('woof_stat_errors', sprintf(__('Its not possible to create file: %s', 'woocommerce-products-filter'), $file));
return FALSE;
} else {
fclose($fh);
}
}
}
return true;
}
//for file system
public function get_stat_files_structure() {
if (!is_dir($this->cache_folder)) {
if (!mkdir($this->cache_folder)) {
return array();
}
}
$y_folders = glob($this->cache_folder . '*', GLOB_ONLYDIR);
$data = array();
$monthes = array();
$days = array();
if (!empty($y_folders)) {
foreach ($y_folders as $key => $value) {
$y = (int) str_replace($this->cache_folder, '', $value);
$data[$y] = array();
$m_folders = glob($this->cache_folder . $y . '/*', GLOB_ONLYDIR);
if (!empty($m_folders)) {
foreach ($m_folders as $km => $m_path) {
$m = (int) str_replace($this->cache_folder . $y . '/', '', $m_path);
$data[$y][$m] = array();
$d_folders = glob($this->cache_folder . $y . '/' . $m . '/*');
foreach ($d_folders as $kd => $d_path) {
$data[$y][$m][] = (int) str_replace($this->cache_folder . $y . '/' . $m . '/', '', $d_path);
}
}
}
}
}
return $data;
}
//for file system
public function get_stat_min_date() {
$structure = $this->get_stat_files_structure();
if (!empty($structure)) {
$min_year = (int) min(array_keys($structure));
$min_month = (int) min(array_keys($structure[$min_year]));
$min_day = 0;
$days = array_values($structure[$min_year][$min_month]);
if (!empty($days)) {
$min_day = (int) min($days);
}
//***
while (true) {
if ($min_day > 0) {
break;
} else {
$min_month++;
if ($min_month > 12) {
$min_month = 1;
$min_year++;
}
$min_day = (int) min(array_values($structure[$min_year][$min_month]));
}
}
return compact('min_day', 'min_month', 'min_year');
}
return array();
}
//for $this->user_max_requests
private function get_user_requests_count($user_ip) {
global $wpdb;
$data_sql = array(
array(
'type' => 'string',
'val' => $user_ip,
),
);
return (int) $wpdb->get_var(WOOF_HELPER::woof_prepare("SELECT COUNT(*) as count FROM $this->table_stat_tmp WHERE user_ip = %s", $data_sql));
}
public function get_the_user_ip() {
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
//*** check ip from share internet
$ip = wc_clean(WOOF_HELPER::get_server_var('HTTP_CLIENT_IP'));
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
//*** to check ip is pass from proxy
$ip = wc_clean(WOOF_HELPER::get_server_var('HTTP_X_FORWARDED_FOR'));
} else {
$ip = wc_clean(WOOF_HELPER::get_server_var('REMOTE_ADDR'));
}
return $ip;
}
public function get_meta_keys() {
if (class_exists('WOOF_META_FILTER')) {
$meta_keys = array();
$meta_fields = array();
if (isset($this->woof_settings['meta_filter'])) {
$meta_fields = $this->woof_settings['meta_filter'];
}
if (!empty($meta_fields)) {
foreach ($meta_fields as $key => $meta) {
if ($meta['meta_key'] == "__META_KEY__") {
continue;
}
$slug = $meta["search_view"] . "_" . $meta['meta_key'];
if (!in_array($slug, $this->items_for_stat)) {
continue;
}
$meta_keys[] = $slug;
}
}
return $meta_keys;
} else {
return array();
}
}
}
WOOF_EXT::$includes['applications']['stat'] = new WOOF_EXT_STAT();