1015 lines
40 KiB
PHP
1015 lines
40 KiB
PHP
<?php
|
|
/**
|
|
* MainWP Module Cost Tracker DB class.
|
|
*
|
|
* @package MainWP\Dashboard
|
|
* @version 4.6
|
|
*/
|
|
|
|
namespace MainWP\Dashboard\Module\CostTracker;
|
|
|
|
use MainWP\Dashboard\MainWP_Install;
|
|
use MainWP\Dashboard\MainWP_Utility;
|
|
use MainWP\Dashboard\MainWP_DB;
|
|
use MainWP\Dashboard\MainWP_DB_Client;
|
|
use MainWP\Dashboard\MainWP_Exception;
|
|
|
|
/**
|
|
* Class Cost_Tracker_DB
|
|
*/
|
|
class Cost_Tracker_DB extends MainWP_Install {
|
|
//phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery
|
|
/**
|
|
* Variable to hold the db version.
|
|
*
|
|
* @var string Version.
|
|
*/
|
|
private $cost_tracker_db_version = '1.0.18';
|
|
|
|
|
|
/**
|
|
* Static variable to hold the single instance of the class.
|
|
*
|
|
* @static
|
|
*
|
|
* @var mixed Default null
|
|
*/
|
|
private static $instance = null;
|
|
|
|
/**
|
|
* Get Instance
|
|
*
|
|
* Creates public static instance.
|
|
*
|
|
* @static
|
|
*
|
|
* @return Cost_Tracker_DB
|
|
*/
|
|
public static function get_instance() {
|
|
if ( null === static::$instance ) {
|
|
static::$instance = new self();
|
|
}
|
|
return static::$instance;
|
|
}
|
|
|
|
/**
|
|
* Init functions.
|
|
*/
|
|
public function init() {
|
|
$this->install();
|
|
}
|
|
|
|
/**
|
|
* Install db.
|
|
*/
|
|
public function install() {
|
|
global $wpdb;
|
|
|
|
$currentVersion = get_site_option( 'mainwp_module_cost_tracker_db_version' );
|
|
|
|
$rslt = $this->query( "SHOW TABLES LIKE '" . $this->table_name( 'cost_tracker' ) . "'" );
|
|
if ( empty( static::num_rows( $rslt ) ) ) {
|
|
$currentVersion = false;
|
|
}
|
|
|
|
if ( $currentVersion === $this->cost_tracker_db_version ) {
|
|
return;
|
|
}
|
|
|
|
$charset_collate = $wpdb->get_charset_collate();
|
|
$sql = array();
|
|
|
|
$tbl = 'CREATE TABLE `' . $this->table_name( 'cost_tracker' ) . '` (
|
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
`name` text NOT NULL,
|
|
`url` text NOT NULL,
|
|
`type` varchar(20) NOT NULL,
|
|
`product_type` varchar(20) NOT NULL,
|
|
`slug` varchar(191) NOT NULL DEFAULT "",
|
|
`license_type` varchar(20) NOT NULL,
|
|
`cost_status` varchar(20) NOT NULL,
|
|
`payment_method` varchar(50) NOT NULL,
|
|
`price` decimal(26,8) NOT NULL,
|
|
`renewal_type` varchar(20) NOT NULL,
|
|
`last_renewal` int(11) NOT NULL,
|
|
`next_renewal` int(11) NOT NULL,
|
|
`next_renewal_today` int(11) NOT NULL,
|
|
`last_alert` int(11) NOT NULL,
|
|
`cost_icon` varchar(64) NOT NULL DEFAULT "",
|
|
`cost_color` varchar(64) NOT NULL DEFAULT "",
|
|
`sites` text NOT NULL,
|
|
`groups` text NOT NULL,
|
|
`clients` text NOT NULL,
|
|
`note` text NOT NULL';
|
|
|
|
if ( empty( $currentVersion ) ) {
|
|
$tbl .= ',
|
|
PRIMARY KEY (`id`) ';
|
|
}
|
|
$tbl .= ') ' . $charset_collate;
|
|
$sql[] = $tbl;
|
|
|
|
require_once ABSPATH . 'wp-admin/includes/upgrade.php'; // NOSONAR - WP compatible.
|
|
foreach ( $sql as $query ) {
|
|
dbDelta( $query );
|
|
}
|
|
$this->update_db_cost( $currentVersion );
|
|
update_option( 'mainwp_module_cost_tracker_db_version', $this->cost_tracker_db_version );
|
|
}
|
|
|
|
|
|
/**
|
|
* Method update_db_cost().
|
|
*
|
|
* @param array $current_version DB version number.
|
|
*
|
|
* @return void
|
|
*/
|
|
public function update_db_cost( $current_version ) { //phpcs:ignore -- NOSONAR - complex.
|
|
if ( ! empty( $current_version ) ) {
|
|
if ( version_compare( $current_version, '1.0.8', '<' ) ) {
|
|
$table = esc_sql( $this->table_name( 'cost_tracker' ) );
|
|
$this->wpdb->query( "ALTER TABLE {$table} MODIFY COLUMN price decimal(26,8)" ); //phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
|
|
}
|
|
if ( version_compare( $current_version, '1.0.9', '<' ) ) {
|
|
$table = esc_sql( $this->table_name( 'cost_tracker' ) );
|
|
$this->wpdb->query( "ALTER TABLE {$table} DROP COLUMN author" ); //phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
|
|
}
|
|
|
|
if ( version_compare( $current_version, '1.0.13', '<' ) ) {
|
|
$costs = $this->get_cost_tracker_by( 'all' );
|
|
|
|
foreach ( $costs as $cost ) {
|
|
$obj_name = '';
|
|
if ( ! empty( $cost->sites ) ) {
|
|
$items = json_decode( $cost->sites, true );
|
|
$obj_name = 'site';
|
|
} elseif ( ! empty( $cost->groups ) ) {
|
|
$items = json_decode( $cost->groups, true );
|
|
$obj_name = 'tag';
|
|
} elseif ( ! empty( $cost->clients ) ) {
|
|
$items = json_decode( $cost->clients, true );
|
|
$obj_name = 'client';
|
|
} else {
|
|
continue;
|
|
}
|
|
|
|
if ( ! empty( $items ) ) {
|
|
foreach ( $items as $it_id ) {
|
|
$this->wpdb->insert(
|
|
$this->table_name( 'lookup_item_objects' ),
|
|
array(
|
|
'item_id' => $cost->id,
|
|
'item_name' => 'cost',
|
|
'object_id' => $it_id,
|
|
'object_name' => $obj_name,
|
|
)
|
|
);
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Method update_cost_tracker().
|
|
*
|
|
* @param array $update Cost tracker array data.
|
|
*
|
|
* @throws \MainWP_Exception Existed cost tracker error.
|
|
* @return mixed Result
|
|
*/
|
|
public function update_cost_tracker( $update ) { //phpcs:ignore -- NOSONAR - complex.
|
|
/**
|
|
* WP database.
|
|
*
|
|
* @global object
|
|
*/
|
|
global $wpdb;
|
|
|
|
if ( ! is_array( $update ) ) {
|
|
return false;
|
|
}
|
|
|
|
$id = isset( $update['id'] ) ? $update['id'] : 0;
|
|
|
|
if ( ! empty( $update['product_type'] ) && ! empty( $update['slug'] ) && in_array( $update['product_type'], array( 'plugin', 'theme' ), true ) ) {
|
|
// check existed cost tracker for this plugin / theme .
|
|
$current = $this->get_cost_tracker_by( 'slug', $update['slug'], $update['product_type'] );
|
|
if ( is_array( $current ) && ! empty( $current ) ) {
|
|
$existed = false;
|
|
if ( 1 === count( $current ) ) {
|
|
$current = current( $current );
|
|
if ( is_object( $current ) ) {
|
|
if ( ! empty( $update['id'] ) ) {
|
|
if ( ! empty( $current->id ) && (int) $current->id !== (int) $update['id'] ) {
|
|
$existed = true; // to fix.
|
|
} elseif ( ! empty( $current->id ) ) {
|
|
$id = $current->id; // to update.
|
|
}
|
|
} else {
|
|
$existed = true; // to fix: existed one.
|
|
}
|
|
}
|
|
} else {
|
|
$existed = true; // to fix found multi items.
|
|
}
|
|
|
|
if ( $existed ) {
|
|
$error = esc_html__( 'A cost tracker for this plugin already exists.', 'mainwp' );
|
|
if ( 'theme' === $update['product_type'] ) {
|
|
$error = esc_html__( 'A cost tracker for this theme already exists.', 'mainwp' );
|
|
}
|
|
throw new MainWP_Exception( esc_html( $error ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( isset( $update['id'] ) ) {
|
|
unset( $update['id'] );
|
|
}
|
|
|
|
if ( ! empty( $id ) ) {
|
|
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching -- write operation; caching not applicable for UPDATE.
|
|
$wpdb->update( $this->table_name( 'cost_tracker' ), $update, array( 'id' => intval( $id ) ) );
|
|
$this->invalidate_cost_tracker_caches( $id );
|
|
return $this->get_cost_tracker_by( 'id', $id );
|
|
} else {
|
|
if ( isset( $update['id'] ) ) {
|
|
unset( $update['id'] );
|
|
}
|
|
|
|
if ( $wpdb->insert( $this->table_name( 'cost_tracker' ), $update ) ) {
|
|
$this->invalidate_cost_tracker_caches();
|
|
return $this->get_cost_tracker_by( 'id', $wpdb->insert_id );
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Method update_selected_lookup_cost().
|
|
*
|
|
* @param int $item_id Cost id.
|
|
* @param array $selected_sites selected sites.
|
|
* @param array $selected_groups selected tags.
|
|
* @param array $selected_clients selected clients.
|
|
*
|
|
* @return mixed Result
|
|
*/
|
|
public function update_selected_lookup_cost( $item_id, $selected_sites = false, $selected_groups = false, $selected_clients = false ) {
|
|
|
|
if ( empty( $item_id ) ) {
|
|
return false;
|
|
}
|
|
|
|
$obj_name = '';
|
|
|
|
$new_obj_ids = array();
|
|
|
|
if ( ! empty( $selected_sites ) ) {
|
|
$obj_name = 'site';
|
|
$new_obj_ids = $selected_sites;
|
|
} elseif ( ! empty( $selected_groups ) ) {
|
|
$obj_name = 'tag';
|
|
$new_obj_ids = $selected_groups;
|
|
} elseif ( ! empty( $selected_clients ) ) {
|
|
$obj_name = 'client';
|
|
$new_obj_ids = $selected_clients;
|
|
}
|
|
|
|
if ( ! empty( $obj_name ) ) {
|
|
static::get_instance()->update_lookup_cost( $item_id, $obj_name, $new_obj_ids );
|
|
} else {
|
|
// to support saving cost without selected sites, tags, clients.
|
|
MainWP_DB::instance()->delete_lookup_items(
|
|
'object_name',
|
|
array(
|
|
'item_name' => 'cost',
|
|
'item_id' => $item_id,
|
|
'object_names' => array( 'site', 'tag', 'client' ),
|
|
)
|
|
);
|
|
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Method update_lookup_cost().
|
|
*
|
|
* @param int $item_id item id to insert lookup value.
|
|
* @param string $obj_name loockup object name.
|
|
* @param array $new_obj_ids New|Update object ids.
|
|
*
|
|
* @return mixed Result
|
|
*/
|
|
public function update_lookup_cost( $item_id, $obj_name, $new_obj_ids ) { //phpcs:ignore -- NOSONAR - complex.
|
|
|
|
$allows = array( 'site', 'tag', 'client' );
|
|
|
|
if ( empty( $item_id ) || ! is_array( $new_obj_ids ) || ! in_array( $obj_name, $allows ) ) {
|
|
return false;
|
|
}
|
|
|
|
$remove_obj_names = array_diff( $allows, array( $obj_name ) );
|
|
|
|
$found_look_ids = array();
|
|
$existed_look_id = array();
|
|
|
|
$results = MainWP_DB::instance()->get_lookup_items( 'cost', $item_id, $obj_name );
|
|
if ( $results ) {
|
|
foreach ( $results as $item ) {
|
|
$found_look_ids[] = $item->lookup_id;
|
|
if ( ! empty( $new_obj_ids ) && in_array( $item->object_id, $new_obj_ids ) ) {
|
|
$existed_look_id[ $item->object_id ] = $item->lookup_id;
|
|
}
|
|
}
|
|
}
|
|
|
|
$new_look_ids = array();
|
|
|
|
foreach ( $new_obj_ids as $obj_id ) {
|
|
if ( isset( $existed_look_id[ $obj_id ] ) ) {
|
|
$new_look_ids[] = $existed_look_id[ $obj_id ];
|
|
continue;
|
|
}
|
|
$insert_id = MainWP_DB::instance()->insert_lookup_item( 'cost', $item_id, $obj_name, $obj_id );
|
|
if ( $insert_id ) {
|
|
$new_look_ids[] = $this->wpdb->insert_id;
|
|
}
|
|
}
|
|
$remove_ids = array_diff( $found_look_ids, $new_look_ids );
|
|
if ( $remove_ids ) {
|
|
MainWP_DB::instance()->delete_lookup_items( 'lookup_id', array( 'lookup_ids' => $remove_ids ) );
|
|
}
|
|
|
|
if ( ! empty( $remove_obj_names ) ) {
|
|
MainWP_DB::instance()->delete_lookup_items(
|
|
'object_name',
|
|
array(
|
|
'item_name' => 'cost',
|
|
'item_id' => $item_id,
|
|
'object_names' => $remove_obj_names,
|
|
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Method get_cost_tracker_by().
|
|
*
|
|
* @param string $by Get by.
|
|
* @param mixed $value Value.
|
|
* @param array $params Others params.
|
|
*
|
|
* @return mixed Result
|
|
*/
|
|
public function get_cost_tracker_by( $by = 'id', $value = null, $params = array() ) { //phpcs:ignore -- NOSONAR - complex method.
|
|
global $wpdb;
|
|
|
|
if ( ! is_array( $params ) ) {
|
|
$params = array();
|
|
}
|
|
|
|
$s = '';
|
|
$exclude = array();
|
|
$include = array();
|
|
$status = array();
|
|
$types = array();
|
|
|
|
$where = '';
|
|
$limit = '';
|
|
|
|
if ( $params && is_array( $params ) ) {
|
|
$s = isset( $params['s'] ) ? $params['s'] : '';
|
|
$exclude = isset( $params['exclude'] ) && ! empty( $params['exclude'] ) ? wp_parse_id_list( $params['exclude'] ) : array();
|
|
$include = isset( $params['include'] ) && ! empty( $params['include'] ) ? wp_parse_id_list( $params['include'] ) : array();
|
|
|
|
$status = isset( $params['status'] ) && ! empty( $params['status'] ) ? wp_parse_list( $params['status'] ) : array();
|
|
$product_type = isset( $params['category'] ) && ! empty( $params['category'] ) ? wp_parse_list( $params['category'] ) : array();
|
|
$types = isset( $params['type'] ) && ! empty( $params['type'] ) ? wp_parse_list( $params['type'] ) : array();
|
|
|
|
$page = isset( $params['paged'] ) ? intval( $params['paged'] ) : false;
|
|
$per_page = isset( $params['items_per_page'] ) ? intval( $params['items_per_page'] ) : false;
|
|
|
|
if ( ! empty( $s ) ) {
|
|
$where .= ' AND ( ct.id LIKE "%' . $this->escape( $s ) . '%" OR ct.name LIKE "%' . $this->escape( $s ) . '%" ) ';
|
|
}
|
|
|
|
if ( ! empty( $exclude ) ) {
|
|
$where .= ' AND ct.id NOT IN (' . implode( ',', $exclude ) . ') ';
|
|
}
|
|
|
|
if ( ! empty( $include ) ) {
|
|
$where .= ' AND ct.id IN (' . implode( ',', $include ) . ') ';
|
|
}
|
|
|
|
if ( ! empty( $status ) ) {
|
|
$where .= ' AND ct.cost_status IN (' . $this->prepare_fields_array( $status ) . ') ';
|
|
}
|
|
|
|
if ( ! empty( $product_type ) && ! in_array( 'any', $product_type ) ) {
|
|
$where .= ' AND ct.product_type IN (' . $this->prepare_fields_array( $product_type ) . ') ';
|
|
}
|
|
|
|
if ( ! empty( $types ) && ! in_array( 'any', $types ) ) {
|
|
$where .= ' AND ct.type IN (' . $this->prepare_fields_array( $types ) . ') ';
|
|
}
|
|
|
|
if ( ! empty( $page ) && ! empty( $per_page ) ) {
|
|
$limit = ' LIMIT ' . ( $page - 1 ) * $per_page . ',' . $per_page;
|
|
}
|
|
}
|
|
|
|
$product_type = isset( $params['product_type'] ) ? $params['product_type'] : '';
|
|
$selected_ids = isset( $params['selected_ids'] ) ? $params['selected_ids'] : array();
|
|
|
|
if ( is_array( $selected_ids ) ) {
|
|
$selected_ids = MainWP_Utility::array_numeric_filter( $selected_ids );
|
|
} else {
|
|
$selected_ids = array();
|
|
}
|
|
|
|
if ( 'all' === $by ) {
|
|
if ( ! empty( $selected_ids ) ) {
|
|
$where .= ' AND ct.id IN (' . implode( ',', $selected_ids ) . ') ';
|
|
}
|
|
$table = esc_sql( $this->table_name( 'cost_tracker' ) );
|
|
// phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter -- $table is escaped with esc_sql(); $where and $limit are from internal arrays only
|
|
return $wpdb->get_results( "SELECT * FROM {$table} ct WHERE 1 {$where}{$limit}" );
|
|
}
|
|
|
|
$where = '';
|
|
$limit = '';
|
|
|
|
$sql = '';
|
|
if ( 'id' === $by && is_numeric( $value ) ) {
|
|
$cache_key = $this->get_cache_key_for_cost_tracker( $by, $value, $params );
|
|
$cached = wp_cache_get( $cache_key, 'mainwp_cost_tracker' );
|
|
if ( false !== $cached ) {
|
|
return $cached;
|
|
}
|
|
|
|
$table = esc_sql( $this->table_name( 'cost_tracker' ) );
|
|
$sql = $wpdb->prepare( "SELECT * FROM {$table} WHERE `id`=%d ", $value );
|
|
// phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter -- $sql is safely constructed with $wpdb->prepare() above; table name is escaped with esc_sql().
|
|
$result = $wpdb->get_row( $sql, OBJECT );
|
|
wp_cache_set( $cache_key, $result, 'mainwp_cost_tracker' );
|
|
return $result;
|
|
} elseif ( 'count' === $by ) {
|
|
$cache_key = 'mainwp_cost_tracker_' . md5( wp_json_encode( array( 'method' => 'get_cost_tracker_by', 'by' => 'count' ) ) ); // NOSONAR - MD5 used for cache key generation only, not cryptographic (security) purposes.
|
|
$cached = wp_cache_get( $cache_key, 'mainwp_cost_tracker' );
|
|
if ( false !== $cached ) {
|
|
return $cached;
|
|
}
|
|
|
|
$table = esc_sql( $this->table_name( 'cost_tracker' ) );
|
|
$sql = "SELECT count(*) FROM {$table}";
|
|
// phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter -- $sql is safely constructed with static table name that is escaped with esc_sql(); no dynamic input.
|
|
$result = $wpdb->get_var( $sql );
|
|
wp_cache_set( $cache_key, $result, 'mainwp_cost_tracker' );
|
|
return $result;
|
|
} elseif ( 'id' === $by && false !== strpos( $value, ',' ) ) {
|
|
$cost_ids = explode( ',', $value );
|
|
$cost_ids = MainWP_Utility::array_numeric_filter( $cost_ids );
|
|
if ( ! empty( $cost_ids ) ) {
|
|
$table = esc_sql( $this->table_name( 'cost_tracker' ) );
|
|
$sql = "SELECT * FROM {$table} WHERE `id` IN (" . implode( ',', $cost_ids ) . ' )';
|
|
}
|
|
} elseif ( 'site_id' === $by || 'client_id' === $by ) {
|
|
$table = esc_sql( $this->table_name( 'cost_tracker' ) );
|
|
$sql = "SELECT * FROM {$table}";
|
|
} elseif ( 'slug' === $by && is_string( $value ) ) {
|
|
if ( in_array( $product_type, array( 'plugin', 'theme' ), true ) ) {
|
|
$cache_key = $this->get_cache_key_for_cost_tracker( $by, $value, array( 'product_type' => $product_type ) );
|
|
$cached = wp_cache_get( $cache_key, 'mainwp_cost_tracker' );
|
|
if ( false !== $cached ) {
|
|
return $cached;
|
|
}
|
|
|
|
$table = esc_sql( $this->table_name( 'cost_tracker' ) );
|
|
$sql = $wpdb->prepare( "SELECT * FROM {$table} WHERE `slug`=%s AND product_type = %s ", $value, $product_type );
|
|
$result = $wpdb->get_row( $sql, OBJECT );
|
|
wp_cache_set( $cache_key, $result, 'mainwp_cost_tracker' );
|
|
return $result;
|
|
} else {
|
|
$where = '';
|
|
if ( ! empty( $product_type ) ) {
|
|
$where = $wpdb->prepare( ' AND product_type = %s ', $product_type );
|
|
}
|
|
$table = esc_sql( $this->table_name( 'cost_tracker' ) );
|
|
$sql = $wpdb->prepare( "SELECT * FROM {$table} WHERE `slug`=%s " . $where, $value );
|
|
}
|
|
}
|
|
|
|
$data = array();
|
|
if ( ! empty( $sql ) ) {
|
|
$cache_key = $this->get_cache_key_for_cost_tracker( $by, $value, $params );
|
|
$cached = wp_cache_get( $cache_key, 'mainwp_cost_tracker' );
|
|
if ( false !== $cached ) {
|
|
return $cached;
|
|
}
|
|
|
|
// phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter -- $sql is safely constructed from escaped table names and prepared statements above
|
|
$result = $wpdb->get_results( $sql, OBJECT );
|
|
wp_cache_set( $cache_key, $result, 'mainwp_cost_tracker' );
|
|
if ( $result ) {
|
|
if ( 'site_id' === $by ) {
|
|
$site_id = intval( $value );
|
|
foreach ( $result as $cost ) {
|
|
if ( empty( $cost->id ) ) {
|
|
continue;
|
|
}
|
|
$sites = ! empty( $cost->sites ) ? json_decode( $cost->sites, true ) : array();
|
|
if ( is_array( $sites ) && in_array( $site_id, $sites ) ) {
|
|
$data[] = $cost;
|
|
}
|
|
}
|
|
} elseif ( 'client_id' === $by ) {
|
|
$client_id = intval( $value );
|
|
foreach ( $result as $cost ) {
|
|
if ( empty( $cost->id ) ) {
|
|
continue;
|
|
}
|
|
$clients = ! empty( $cost->clients ) ? json_decode( $cost->clients, true ) : array();
|
|
if ( is_array( $clients ) && in_array( $client_id, $clients ) ) {
|
|
$data[] = $cost;
|
|
}
|
|
}
|
|
} else {
|
|
foreach ( $result as $cost ) {
|
|
if ( empty( $cost->id ) ) {
|
|
continue;
|
|
}
|
|
$data[] = $cost;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return $data;
|
|
}
|
|
|
|
/**
|
|
* Method prepare_fields_array().
|
|
*
|
|
* @param array $values array of string.
|
|
*
|
|
* @return string Escaped string result.
|
|
*/
|
|
public function prepare_fields_array( $values = array() ) {
|
|
$tmp = '';
|
|
foreach ( $values as $value ) {
|
|
$tmp .= '"' . $this->escape( $value ) . '",';
|
|
}
|
|
return rtrim( $tmp, ',' );
|
|
}
|
|
|
|
/**
|
|
* Method delete_cost_tracker().
|
|
*
|
|
* @param string $by Delete by.
|
|
* @param mixed $value Value.
|
|
*
|
|
* @return mixed Result
|
|
*/
|
|
public function delete_cost_tracker( $by = 'id', $value = null ) {
|
|
global $wpdb;
|
|
|
|
if ( empty( $value ) ) {
|
|
return false;
|
|
}
|
|
|
|
if ( 'id' !== $by && 'site_id' !== $by ) {
|
|
return false;
|
|
}
|
|
$deleted = false;
|
|
|
|
if ( 'id' === $by ) {
|
|
$table = esc_sql( $this->table_name( 'cost_tracker' ) );
|
|
if ( $wpdb->query( $wpdb->prepare( "DELETE FROM {$table} WHERE id=%d ", $value ) ) ) { //phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching -- delete operation that invalidates caches below.
|
|
$deleted = true;
|
|
}
|
|
} else {
|
|
$table = esc_sql( $this->table_name( 'cost_tracker' ) );
|
|
if ( $wpdb->query( $wpdb->prepare( "DELETE FROM {$table} WHERE site_id=%d ", $value ) ) ) { //phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching -- delete operation that invalidates caches below.
|
|
$deleted = true;
|
|
}
|
|
}
|
|
|
|
if ( $deleted ) {
|
|
$lookup_table = esc_sql( $this->table_name( 'lookup_item_objects' ) );
|
|
$wpdb->query( $wpdb->prepare( "DELETE FROM {$lookup_table} WHERE item_id=%d AND item_name = \"cost\"", $value ) ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching -- delete operation; caching is not applicable for write operations.
|
|
$this->invalidate_cost_tracker_caches( 'id' === $by ? $value : null );
|
|
}
|
|
|
|
return $deleted;
|
|
}
|
|
|
|
/**
|
|
* Method get_all_cost_trackers_by_clients().
|
|
*
|
|
* @param array $client_ids Client ids.
|
|
* @param array $params Orther params.
|
|
*
|
|
* @return mixed Result
|
|
*/
|
|
public function get_all_cost_trackers_by_clients( $client_ids, $params = array() ) { //phpcs:ignore -- NOSONAR - complex method.
|
|
|
|
if ( is_string( $client_ids ) ) {
|
|
$client_ids = explode( ',', $client_ids );
|
|
}
|
|
|
|
if ( ! is_array( $client_ids ) || empty( $client_ids ) ) {
|
|
return array();
|
|
}
|
|
|
|
if ( ! is_array( $params ) ) {
|
|
$params = array();
|
|
}
|
|
|
|
$get_sites_of_cost = isset( $params['get_cost_sites'] ) && $params['get_cost_sites'] ? true : false;
|
|
$clients_site_ids = array();
|
|
|
|
$client_sites = MainWP_DB_Client::instance()->get_websites_by_client_ids( $client_ids );
|
|
if ( $client_sites ) {
|
|
foreach ( $client_sites as $website ) {
|
|
if ( empty( $website->client_id ) ) {
|
|
continue;
|
|
}
|
|
if ( ! isset( $clients_site_ids[ $website->client_id ] ) ) {
|
|
$clients_site_ids[ $website->client_id ] = array();
|
|
}
|
|
$clients_site_ids[ $website->client_id ][] = $website->id;
|
|
}
|
|
}
|
|
|
|
global $wpdb;
|
|
|
|
$clients_costs = array();
|
|
$clients_costs_ids = array();
|
|
|
|
$cache_key = 'mainwp_cost_tracker_all';
|
|
$result = wp_cache_get( $cache_key, 'mainwp_cost_tracker' );
|
|
|
|
if ( false === $result ) {
|
|
$table = esc_sql( $this->table_name( 'cost_tracker' ) );
|
|
$sql = "SELECT * FROM {$table}";
|
|
// phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter -- $sql uses esc_sql() for table name; results cached immediately after retrieval
|
|
$result = $wpdb->get_results( $sql, OBJECT );
|
|
wp_cache_set( $cache_key, $result, 'mainwp_cost_tracker' );
|
|
}
|
|
|
|
if ( $result ) {
|
|
foreach ( $result as $cost ) {
|
|
$sites = ! empty( $cost->sites ) ? json_decode( $cost->sites, true ) : array();
|
|
$groups = ! empty( $cost->groups ) ? json_decode( $cost->groups, true ) : array();
|
|
$clients = ! empty( $cost->clients ) ? json_decode( $cost->clients, true ) : array();
|
|
|
|
if ( ! is_array( $sites ) ) {
|
|
$sites = array();
|
|
}
|
|
if ( ! is_array( $groups ) ) {
|
|
$groups = array();
|
|
}
|
|
if ( ! is_array( $clients ) ) {
|
|
$clients = array();
|
|
}
|
|
|
|
if ( empty( $sites ) && empty( $groups ) && empty( $clients ) ) {
|
|
continue;
|
|
}
|
|
|
|
// to reduce db queries for this case.
|
|
if ( ! empty( $sites ) && empty( $groups ) && empty( $clients ) ) {
|
|
foreach ( $clients_site_ids as $client_id => $client_site_ids ) {
|
|
foreach ( $sites as $siteid ) {
|
|
if ( in_array( $siteid, $client_site_ids ) ) {
|
|
if ( ! isset( $clients_costs[ $client_id ] ) ) {
|
|
$clients_costs[ $client_id ] = array();
|
|
}
|
|
|
|
if ( ! isset( $clients_costs_ids[ $client_id ] ) ) {
|
|
$clients_costs_ids[ $client_id ] = array();
|
|
}
|
|
|
|
if ( $get_sites_of_cost ) {
|
|
$cost->cost_sites_ids = $sites; // sites ids.
|
|
}
|
|
if ( ! in_array( $cost->id, $clients_costs_ids[ $client_id ] ) ) {
|
|
$cost->count_sites = count( $sites );
|
|
$cost->number_client_costs_sites = array_intersect( $client_site_ids, $sites );
|
|
$clients_costs[ $client_id ][] = $cost;
|
|
$clients_costs_ids[ $client_id ][] = $cost->id;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
continue;
|
|
}
|
|
|
|
$params = array(
|
|
'sites' => $sites,
|
|
'groups' => $groups,
|
|
'clients' => $clients,
|
|
);
|
|
|
|
// to do: should create relation of: costs, sites, groups, clients in other way.
|
|
// to make it more easier in queries.
|
|
$cost_sites = MainWP_DB::instance()->get_db_sites( $params ); // get sites of cost tracker.
|
|
$cost_sites_ids = array();
|
|
|
|
if ( is_array( $cost_sites ) ) {
|
|
|
|
foreach ( $cost_sites as $cost_site ) {
|
|
$cost_sites_ids[] = $cost_site->id; // sites ids of cost tracker.
|
|
}
|
|
|
|
foreach ( $clients_site_ids as $client_id => $client_site_ids ) {
|
|
foreach ( $cost_sites as $cost_site ) {
|
|
if ( in_array( $cost_site->id, $client_site_ids ) ) {
|
|
if ( ! isset( $clients_costs[ $client_id ] ) ) {
|
|
$clients_costs[ $client_id ] = array();
|
|
}
|
|
if ( ! isset( $clients_costs_ids[ $client_id ] ) ) {
|
|
$clients_costs_ids[ $client_id ] = array();
|
|
}
|
|
if ( $get_sites_of_cost ) {
|
|
$cost->cost_sites_ids = $cost_sites_ids;
|
|
}
|
|
if ( ! in_array( $cost->id, $clients_costs_ids[ $client_id ] ) ) {
|
|
$cost->count_sites = count( $cost_sites );
|
|
$cost->number_client_costs_sites = array_intersect( $client_site_ids, $cost_sites_ids );
|
|
$clients_costs[ $client_id ][] = $cost;
|
|
$clients_costs_ids[ $client_id ][] = $cost->id;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return $clients_costs;
|
|
}
|
|
|
|
/**
|
|
* Method get_sites_of_cost().
|
|
*
|
|
* Get sites of cost.
|
|
*
|
|
* @param object $cost Cost data.
|
|
*
|
|
* @return mixed Result
|
|
*/
|
|
public function get_sites_of_cost( $cost ) { //phpcs:ignore -- NOSONAR - complex method.
|
|
|
|
if ( empty( $cost ) || ! is_object( $cost ) ) {
|
|
return array();
|
|
}
|
|
|
|
$sites = ! empty( $cost->sites ) ? json_decode( $cost->sites, true ) : array(); // NOSONAR -- duplicate.
|
|
$groups = ! empty( $cost->groups ) ? json_decode( $cost->groups, true ) : array(); // NOSONAR -- duplicate.
|
|
$clients = ! empty( $cost->clients ) ? json_decode( $cost->clients, true ) : array(); // NOSONAR -- duplicate.
|
|
|
|
if ( ! is_array( $sites ) ) { // NOSONAR -- duplicate.
|
|
$sites = array(); // NOSONAR -- duplicate.
|
|
}
|
|
if ( ! is_array( $groups ) ) { // NOSONAR -- duplicate.
|
|
$groups = array(); // NOSONAR -- duplicate.
|
|
}
|
|
if ( ! is_array( $clients ) ) { // NOSONAR -- duplicate.
|
|
$clients = array(); // NOSONAR -- duplicate.
|
|
}
|
|
|
|
if ( empty( $sites ) && empty( $groups ) && empty( $clients ) ) { // NOSONAR -- duplicate.
|
|
return array(); // NOSONAR -- duplicate.
|
|
}
|
|
|
|
$params = array( // NOSONAR -- duplicate.
|
|
'sites' => $sites, // NOSONAR -- duplicate.
|
|
'groups' => $groups, // NOSONAR -- duplicate.
|
|
'clients' => $clients, // NOSONAR -- duplicate.
|
|
);
|
|
|
|
return MainWP_DB::instance()->get_db_sites( $params ); // NOSONAR - get sites of cost tracker.
|
|
}
|
|
|
|
|
|
/**
|
|
* Method get_all_cost_trackers_by_sites().
|
|
*
|
|
* @param array $sites_ids Sites ids.
|
|
*
|
|
* @return mixed Result
|
|
*/
|
|
public function get_all_cost_trackers_by_sites( $sites_ids ) { //phpcs:ignore -- NOSONAR - complex method.
|
|
|
|
if ( is_string( $sites_ids ) ) {
|
|
$sites_ids = explode( ',', $sites_ids );
|
|
}
|
|
|
|
if ( ! is_array( $sites_ids ) || empty( $sites_ids ) ) {
|
|
return array();
|
|
}
|
|
|
|
$sites_ids = array_map( 'intval', $sites_ids );
|
|
|
|
global $wpdb;
|
|
|
|
$sites_costs = array();
|
|
$sites_costs_ids = array();
|
|
|
|
$cache_key = 'mainwp_cost_tracker_all';
|
|
$result = wp_cache_get( $cache_key, 'mainwp_cost_tracker' );
|
|
|
|
if ( false === $result ) {
|
|
$table = esc_sql( $this->table_name( 'cost_tracker' ) );
|
|
$sql = "SELECT * FROM {$table}";
|
|
// phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter -- $sql uses esc_sql() for table name; results cached immediately after retrieval
|
|
$result = $wpdb->get_results( $sql, OBJECT );
|
|
wp_cache_set( $cache_key, $result, 'mainwp_cost_tracker' );
|
|
}
|
|
|
|
if ( $result ) {
|
|
foreach ( $result as $cost ) {
|
|
$sites = ! empty( $cost->sites ) ? json_decode( $cost->sites, true ) : array();
|
|
$groups = ! empty( $cost->groups ) ? json_decode( $cost->groups, true ) : array();
|
|
$clients = ! empty( $cost->clients ) ? json_decode( $cost->clients, true ) : array();
|
|
|
|
if ( ! is_array( $sites ) ) {
|
|
$sites = array();
|
|
}
|
|
if ( ! is_array( $groups ) ) {
|
|
$groups = array();
|
|
}
|
|
if ( ! is_array( $clients ) ) {
|
|
$clients = array();
|
|
}
|
|
|
|
if ( empty( $sites ) && empty( $groups ) && empty( $clients ) ) {
|
|
continue;
|
|
}
|
|
|
|
// to reduce db queries for this case.
|
|
if ( ! empty( $sites ) && empty( $groups ) && empty( $clients ) ) {
|
|
foreach ( $sites_ids as $site_id ) {
|
|
if ( in_array( $site_id, $sites ) ) {
|
|
if ( ! isset( $sites_costs[ $site_id ] ) ) {
|
|
$sites_costs[ $site_id ] = array();
|
|
}
|
|
|
|
if ( ! isset( $sites_costs_ids[ $site_id ] ) ) {
|
|
$sites_costs_ids[ $site_id ] = array();
|
|
}
|
|
|
|
if ( ! in_array( $cost->id, $sites_costs_ids[ $site_id ] ) ) {
|
|
$cost->count_sites = count( $sites );
|
|
$sites_costs[ $site_id ][] = $cost;
|
|
$sites_costs_ids[ $site_id ][] = $cost->id;
|
|
}
|
|
}
|
|
}
|
|
continue;
|
|
}
|
|
|
|
$params = array(
|
|
'sites' => $sites,
|
|
'groups' => $groups,
|
|
'clients' => $clients,
|
|
);
|
|
|
|
// to do: should create relation of: costs, sites, groups, clients in other way.
|
|
// to make it more easier in queries.
|
|
$cost_sites = MainWP_DB::instance()->get_db_sites( $params );
|
|
|
|
if ( is_array( $cost_sites ) ) {
|
|
foreach ( $sites_ids as $site_id ) {
|
|
foreach ( $cost_sites as $cost_site ) {
|
|
if ( (int) $cost_site->id === $site_id ) {
|
|
if ( ! isset( $sites_costs[ $site_id ] ) ) {
|
|
$sites_costs[ $site_id ] = array();
|
|
}
|
|
if ( ! isset( $sites_costs_ids[ $site_id ] ) ) {
|
|
$sites_costs_ids[ $site_id ] = array();
|
|
}
|
|
if ( ! in_array( $cost->id, $sites_costs_ids[ $site_id ] ) ) {
|
|
$cost->count_sites = count( $cost_sites );
|
|
$sites_costs[ $site_id ][] = $cost;
|
|
$sites_costs_ids[ $site_id ][] = $cost->id;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return $sites_costs;
|
|
}
|
|
|
|
/**
|
|
* Method get_summary_data().
|
|
*
|
|
* @param array $params Params.
|
|
*
|
|
* @return mixed Result
|
|
*/
|
|
public function get_summary_data( $params = array() ) {
|
|
if ( ! is_array( $params ) ) {
|
|
$params = array();
|
|
}
|
|
|
|
global $wpdb;
|
|
|
|
$sum_data = isset( $params['sum_data'] ) ? $params['sum_data'] : '';
|
|
$where = '';
|
|
$sql = '';
|
|
if ( 'all' === $sum_data ) {
|
|
$cache_key = 'mainwp_cost_tracker_' . md5( wp_json_encode( array( 'method' => 'get_summary_data', 'sum_data' => 'all' ) ) ); // NOSONAR - MD5 used for cache key generation only, not cryptographic (security) purposes.
|
|
$cached = wp_cache_get( $cache_key, 'mainwp_cost_tracker' );
|
|
if ( false !== $cached ) {
|
|
return $cached;
|
|
}
|
|
|
|
$where .= ' AND co.cost_status = "active" AND co.type = "subscription" ';
|
|
$table = esc_sql( $this->table_name( 'cost_tracker' ) );
|
|
$sql = "SELECT * FROM {$table} co WHERE 1 {$where} ORDER BY co.next_renewal ASC ";
|
|
// phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter -- $sql is safely constructed with esc_sql() table name and static WHERE clause
|
|
$result = $wpdb->get_results( $sql );
|
|
wp_cache_set( $cache_key, $result, 'mainwp_cost_tracker' );
|
|
return $result;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Method update_next_renewal_today()
|
|
*
|
|
* @return void
|
|
*/
|
|
public function update_next_renewal_today() {
|
|
|
|
$costs = $this->get_cost_tracker_by( 'all' );
|
|
if ( $costs ) {
|
|
foreach ( $costs as $cost ) {
|
|
$next_renewal = Cost_Tracker_Admin::get_next_renewal( $cost->last_renewal, $cost->renewal_type );
|
|
$next_today = Cost_Tracker_Admin::calc_next_renewal_today( $cost, $next_renewal );
|
|
if ( $next_today !== $cost->next_renewal_today ) {
|
|
$update = array(
|
|
'id' => $cost->id,
|
|
'next_renewal_today' => $next_today,
|
|
);
|
|
$this->update_cost_tracker( $update );
|
|
}
|
|
}
|
|
}
|
|
update_option( 'module_cost_tracker_calc_today_next_renewal', gmdate( 'Y-m-d' ) );
|
|
}
|
|
|
|
/**
|
|
* Generate cache key for get_cost_tracker_by queries.
|
|
*
|
|
* @param string $by Query type.
|
|
* @param mixed $value Query value.
|
|
* @param array $params Additional parameters.
|
|
*
|
|
* @return string Cache key.
|
|
*/
|
|
private function get_cache_key_for_cost_tracker( $by, $value, $params = array() ) {
|
|
$identifier = wp_json_encode(
|
|
array(
|
|
'method' => 'get_cost_tracker_by',
|
|
'by' => $by,
|
|
'value' => $value,
|
|
'params' => $params,
|
|
)
|
|
);
|
|
return 'mainwp_cost_tracker_' . md5( $identifier ); // NOSONAR - MD5 used for cache key generation only, not cryptographic (security) purposes.
|
|
}
|
|
|
|
/**
|
|
* Invalidate cost tracker caches.
|
|
*
|
|
* @param int|null $cost_id Cost ID to invalidate specific caches, or null for all caches.
|
|
*
|
|
* @return void
|
|
*/
|
|
private function invalidate_cost_tracker_caches( $cost_id = null ) {
|
|
wp_cache_delete( 'mainwp_cost_tracker_' . md5( wp_json_encode( array( 'method' => 'get_cost_tracker_by', 'by' => 'count' ) ) ), 'mainwp_cost_tracker' ); // NOSONAR - MD5 used for cache key generation only, not cryptographic (security) purposes.
|
|
wp_cache_delete( 'mainwp_cost_tracker_all', 'mainwp_cost_tracker' );
|
|
wp_cache_delete( 'mainwp_cost_tracker_' . md5( wp_json_encode( array( 'method' => 'get_summary_data', 'sum_data' => 'all' ) ) ), 'mainwp_cost_tracker' ); // NOSONAR - MD5 used for cache key generation only, not cryptographic (security) purposes.
|
|
|
|
if ( $cost_id ) {
|
|
$cost_id = absint( $cost_id );
|
|
wp_cache_delete( 'mainwp_cost_tracker_' . md5( wp_json_encode( array( 'method' => 'get_cost_tracker_by', 'by' => 'id', 'value' => $cost_id ) ) ), 'mainwp_cost_tracker' ); // NOSONAR - MD5 used for cache key generation only, not cryptographic (security) purposes.
|
|
}
|
|
}
|
|
}
|