PluginProbe
MainWP Dashboard: Self-hosted WordPress Management for Agencies / 6.2.2
MainWP Dashboard: Self-hosted WordPress Management for Agencies v6.2.2
6.2.3 6.2.2 6.2.1 6.2 6.1.8 6.1.7 6.1.6 6.1.5 6.1.4 6.1.3 6.1.2 6.1.1 6.1 6.0.12 6.0.11 4.6.0.1 5.0 5.0.1 5.0.2 5.0.3 5.0.3.1 5.0.3.2 5.1 5.1.1 5.2 All 156 releases
← All changes | modules/cost-tracker/classes/class-cost-tracker-db-query.php +251 -241 5.0.2 → 6.2.2 View file →
@@ -12,8 +12,14 @@
12 12 use MainWP\Dashboard\MainWP_Utility;
13 13 use MainWP\Dashboard\MainWP_DB;
14 14 use MainWP\Dashboard\MainWP_DB_Client;
15 15
16 +// Exit if accessed directly.
17 +if ( ! defined( 'ABSPATH' ) ) {
18 + exit;
19 +}
20 +
21 +
16 22 /**
17 23 * Class Cost_Tracker_DB_Query
18 24 */
19 25 class Cost_Tracker_DB_Query extends Cost_Tracker_DB {
@@ -18,285 +24,289 @@
18 24 */
19 25 class Cost_Tracker_DB_Query extends Cost_Tracker_DB {
20 26 //phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery
21 27
22 - /**
23 - * Private static variable to hold the single instance of the class.
24 - *
25 - * @static
26 - *
27 - * @var mixed Default null
28 - */
29 - private static $instance = null;
28 + /**
29 + * Private static variable to hold the single instance of the class.
30 + *
31 + * @static
32 + *
33 + * @var mixed Default null
34 + */
35 + private static $instance = null;
30 36
31 37
32 - /**
33 - * Method instance()
34 - *
35 - * Return public static instance.
36 - *
37 - * @static
38 - * @return instance of class.
39 - */
40 - public static function instance() {
41 - if ( null === self::$instance ) {
42 - self::$instance = new self();
43 - }
44 - return self::$instance;
45 - }
38 + /**
39 + * Method instance()
40 + *
41 + * Return public static instance.
42 + *
43 + * @static
44 + * @return instance of class.
45 + */
46 + public static function instance() {
47 + if ( null === static::$instance ) {
48 + static::$instance = new self();
49 + }
50 + return static::$instance;
51 + }
46 52
47 - /**
48 - * Query costs records
49 - *
50 - * @param array $args Arguments to filter the records by.
51 - *
52 - * @return array Records
53 - */
54 - public function query_costs( $args ) { //phpcs:ignore -- complex.
55 - global $wpdb;
53 + /**
54 + * Query costs records
55 + *
56 + * @param array $args Arguments to filter the records by.
57 + *
58 + * @return array Records
59 + */
60 + public function query_costs( $args ) { //phpcs:ignore -- NOSONAR - complex.
61 + global $wpdb;
56 62
57 - $all_defaults = Cost_Tracker_Admin::get_default_fields_values();
63 + $all_defaults = Cost_Tracker_Admin::get_default_fields_values();
58 64
59 - $filter_site_ids = ! empty( $args['filter_sites'] ) ? $args['filter_sites'] : array();
60 - $filter_client_ids = ! empty( $args['filter_clients'] ) ? $args['filter_clients'] : array();
65 + $filter_site_ids = ! empty( $args['filter_sites'] ) ? $args['filter_sites'] : array();
66 + $filter_client_ids = ! empty( $args['filter_clients'] ) ? $args['filter_clients'] : array();
61 67
62 - $filter_prod_type_slugs = ! empty( $args['filter_prods_types'] ) ? $args['filter_prods_types'] : false;
63 - $filter_cost_state = ! empty( $args['filter_states'] ) ? $args['filter_states'] : false;
68 + $filter_prod_type_slugs = ! empty( $args['filter_prods_types'] ) ? $args['filter_prods_types'] : false;
69 + $filter_cost_state = ! empty( $args['filter_states'] ) ? $args['filter_states'] : false;
64 70
65 - $filter_license_type = ! empty( $args['filter_license_type'] ) ? $args['filter_license_type'] : false;
66 - $filter_payment_method = ! empty( $args['filter_payment_method'] ) ? $args['filter_payment_method'] : false;
67 - $filter_renewal_type = ! empty( $args['filter_renewal_type'] ) ? $args['filter_renewal_type'] : false;
71 + $filter_license_type = ! empty( $args['filter_license_type'] ) ? $args['filter_license_type'] : false;
72 + $filter_payment_method = ! empty( $args['filter_payment_method'] ) ? $args['filter_payment_method'] : false;
73 + $filter_renewal_type = ! empty( $args['filter_renewal_type'] ) ? $args['filter_renewal_type'] : false;
68 74
69 - $filter_dtsstart = ! empty( $args['dtsstart'] ) ? strtotime( $args['dtsstart'] ) : false;
70 - $filter_dtsstop = ! empty( $args['dtsstop'] ) ? ( strtotime( $args['dtsstop'] ) + DAY_IN_SECONDS - 1 ) : false;
75 + $filter_dtsstart = ! empty( $args['dtsstart'] ) ? strtotime( $args['dtsstart'] ) : false;
76 + $filter_dtsstop = ! empty( $args['dtsstop'] ) ? ( strtotime( $args['dtsstop'] ) + DAY_IN_SECONDS - 1 ) : false;
71 77
72 - if ( ! empty( $filter_client_ids ) ) {
73 - $filter_client_ids = MainWP_Utility::array_numeric_filter( $filter_client_ids );
74 - }
75 - if ( ! empty( $filter_site_ids ) ) {
76 - $filter_site_ids = MainWP_Utility::array_numeric_filter( $filter_site_ids );
77 - }
78 + if ( ! empty( $filter_client_ids ) ) {
79 + $filter_client_ids = MainWP_Utility::array_numeric_filter( $filter_client_ids );
80 + }
81 + if ( ! empty( $filter_site_ids ) ) {
82 + $filter_site_ids = MainWP_Utility::array_numeric_filter( $filter_site_ids );
83 + }
78 84
79 - if ( ! empty( $filter_prod_type_slugs ) ) {
80 - $product_types = Cost_Tracker_Admin::get_product_types();
81 - $product_types = array_keys( $product_types );
82 - $filter_prod_type_slugs = array_filter(
83 - $filter_prod_type_slugs,
84 - function ( $e ) use ( $product_types ) {
85 - return is_string( $e ) && in_array( $e, $product_types, true ) ? true : false; // to valid.
86 - }
87 - );
88 - }
85 + if ( ! empty( $filter_prod_type_slugs ) ) {
86 + $product_types = Cost_Tracker_Admin::get_product_types();
87 + $product_types = array_keys( $product_types );
88 + $filter_prod_type_slugs = array_filter(
89 + $filter_prod_type_slugs,
90 + function ( $e ) use ( $product_types ) {
91 + return is_string( $e ) && in_array( $e, $product_types, true ) ? true : false; // to valid.
92 + }
93 + );
94 + }
89 95
90 - if ( ! empty( $filter_cost_state ) ) {
91 - $costs_state = Cost_Tracker_Admin::get_cost_status( false, true );
92 - $costs_state = array_keys( $costs_state );
93 - $filter_cost_state = array_filter(
94 - $filter_cost_state,
95 - function ( $e ) use ( $costs_state ) {
96 - return is_string( $e ) && in_array( $e, $costs_state, true ) ? true : false; // to valid.
97 - }
98 - );
99 - }
96 + if ( ! empty( $filter_cost_state ) ) {
97 + $costs_state = Cost_Tracker_Admin::get_cost_status();
98 + $costs_state = array_keys( $costs_state );
99 + $filter_cost_state = array_filter(
100 + $filter_cost_state,
101 + function ( $e ) use ( $costs_state ) {
102 + return is_string( $e ) && in_array( $e, $costs_state, true ) ? true : false; // to valid.
103 + }
104 + );
105 + }
100 106
101 - $license_types = $all_defaults['license_types'];
102 - $payment_methods = $all_defaults['payment_methods'];
103 - $renewal_frequency = $all_defaults['renewal_frequency'];
107 + $license_types = $all_defaults['license_types'];
108 + $payment_methods = $all_defaults['payment_methods'];
109 + $renewal_frequency = $all_defaults['renewal_frequency'];
104 110
105 - if ( ! empty( $filter_license_type ) ) {
106 - $license_types = array_keys( $license_types );
107 - $filter_license_type = array_filter(
108 - $filter_license_type,
109 - function ( $e ) use ( $license_types ) {
110 - return is_string( $e ) && in_array( $e, $license_types, true ) ? true : false; // to valid.
111 - }
112 - );
113 - }
114 - if ( ! empty( $filter_payment_method ) ) {
115 - $payment_methods = array_keys( $payment_methods );
116 - $filter_payment_method = array_filter(
117 - $filter_payment_method,
118 - function ( $e ) use ( $payment_methods ) {
119 - return is_string( $e ) && in_array( $e, $payment_methods, true ) ? true : false; // to valid.
120 - }
121 - );
122 - }
123 - if ( ! empty( $filter_renewal_type ) ) {
124 - $renewal_frequency = array_keys( $renewal_frequency );
125 - $filter_renewal_type = array_filter(
126 - $filter_renewal_type,
127 - function ( $e ) use ( $renewal_frequency ) {
128 - return is_string( $e ) && in_array( $e, $renewal_frequency, true ) ? true : false; // to valid.
129 - }
130 - );
131 - }
111 + if ( ! empty( $filter_license_type ) ) {
112 + $license_types = array_keys( $license_types );
113 + $filter_license_type = array_filter(
114 + $filter_license_type,
115 + function ( $e ) use ( $license_types ) {
116 + return is_string( $e ) && in_array( $e, $license_types, true ) ? true : false; // to valid.
117 + }
118 + );
119 + }
120 + if ( ! empty( $filter_payment_method ) ) {
121 + $payment_methods = array_keys( $payment_methods );
122 + $filter_payment_method = array_filter(
123 + $filter_payment_method,
124 + function ( $e ) use ( $payment_methods ) {
125 + return is_string( $e ) && in_array( $e, $payment_methods, true ) ? true : false; // to valid.
126 + }
127 + );
128 + }
129 + if ( ! empty( $filter_renewal_type ) ) {
130 + $renewal_frequency = array_keys( $renewal_frequency );
131 + $filter_renewal_type = array_filter(
132 + $filter_renewal_type,
133 + function ( $e ) use ( $renewal_frequency ) {
134 + return is_string( $e ) && in_array( $e, $renewal_frequency, true ) ? true : false; // to valid.
135 + }
136 + );
137 + }
132 138
133 - $where = '';
139 + $where = '';
134 140
135 - $allowed_search_fields = array( 'co.name', 'co.product_type', 'co.payment_method', 'co.type' );
141 + $allowed_search_fields = array( 'co.name', 'co.product_type', 'co.payment_method', 'co.type' );
136 142
137 - $where_search = array();
138 - if ( ! empty( $args['search'] ) ) {
139 - // Sanitize field.
140 - foreach ( $allowed_search_fields as $field ) {
141 - $where_search[] = $this->wpdb->prepare( " {$field} LIKE %s ", "%{$args['search']}%" ); //phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
142 - }
143 - }
143 + $where_search = array();
144 + if ( ! empty( $args['search'] ) ) {
145 + // Sanitize field.
146 + $search_term = '%' . esc_sql( $args['search'] ) . '%';
147 + foreach ( $allowed_search_fields as $field ) {
148 + $where_search[] = $this->wpdb->prepare( " {$field} LIKE %s ", $search_term );
149 + }
150 + }
144 151
145 - if ( ! empty( $where_search ) ) {
146 - $where .= ' AND (' . implode( ' OR ', $where_search ) . ')';
147 - }
148 - $join_lookup = '';
149 - $filter_lookup = ! empty( $filter_site_ids ) || ! empty( $filter_client_ids ) ? true : false;
152 + if ( ! empty( $where_search ) ) {
153 + $where .= ' AND (' . implode( ' OR ', $where_search ) . ')';
154 + }
155 + $join_lookup = '';
156 + $filter_lookup = ! empty( $filter_site_ids ) || ! empty( $filter_client_ids ) ? true : false;
150 157
151 - if ( $filter_lookup ) {
152 - $join_lookup = ' JOIN ' . $this->table_name( 'lookup_item_objects' ) . ' lco ON co.id = lco.item_id AND lco.item_name = "cost" ';
153 - $join_and = array();
158 + if ( $filter_lookup ) {
159 + $lookup_table = '`' . esc_sql( $this->table_name( 'lookup_item_objects' ) ) . '`';
160 + $join_lookup = " JOIN {$lookup_table} lco ON co.id = lco.item_id AND lco.item_name = 'cost' ";
161 + $join_and = array();
154 162
155 - $clients_sites_ids = array();
156 - if ( $filter_client_ids ) {
157 - $join_and[] = ' lco.object_name = "client" AND lco.object_id IN (' . implode( ',', $filter_client_ids ) . ') ';
163 + $clients_sites_ids = array();
164 + if ( $filter_client_ids ) {
165 + $safe_client_ids = array_map( 'intval', $filter_client_ids );
166 + $join_and[] = ' lco.object_name = "client" AND lco.object_id IN (' . implode( ',', $safe_client_ids ) . ') ';
158 167
159 - // if filter by clients need to get sites of the clients to search in lookup table.
160 - $cli_sites = MainWP_DB_Client::instance()->get_websites_by_client_ids( $filter_client_ids );
161 - if ( $cli_sites ) {
162 - foreach ( $cli_sites as $cli_site ) {
163 - $clients_sites_ids[] = $cli_site->id;
164 - }
165 - }
166 - }
168 + // if filter by clients need to get sites of the clients to search in lookup table.
169 + $cli_sites = MainWP_DB_Client::instance()->get_websites_by_client_ids( $filter_client_ids );
170 + if ( $cli_sites ) {
171 + foreach ( $cli_sites as $cli_site ) {
172 + $clients_sites_ids[] = $cli_site->id;
173 + }
174 + }
175 + }
167 176
168 - $filter_site_ids = array_unique( array_merge( $filter_site_ids, $clients_sites_ids ) );
177 + $filter_site_ids = array_unique( array_merge( $filter_site_ids, $clients_sites_ids ) );
169 178
170 - if ( $filter_site_ids ) {
171 - $join_and[] = ' lco.object_name = "site" AND lco.object_id IN (' . implode( ',', $filter_site_ids ) . ') ';
172 - }
179 + if ( $filter_site_ids ) {
180 + $safe_site_ids = array_map( 'intval', $filter_site_ids );
181 + $join_and[] = ' lco.object_name = "site" AND lco.object_id IN (' . implode( ',', $safe_site_ids ) . ') ';
182 + }
173 183
174 - if ( ! empty( $join_and ) ) {
175 - if ( 1 === count( $join_and ) ) {
176 - $join_lookup .= ' AND ' . $join_and[0];
177 - } elseif ( 2 === count( $join_and ) ) {
178 - $join_lookup .= ' AND ( ( ' . $join_and[0] . ' ) OR ( ' . $join_and[1] . ' ) )';
179 - } else {
180 - $join_lookup = '';
181 - }
182 - } else {
183 - $join_lookup = '';
184 - }
185 - }
184 + if ( ! empty( $join_and ) ) {
185 + if ( 1 === count( $join_and ) ) {
186 + $join_lookup .= ' AND ' . $join_and[0];
187 + } elseif ( 2 === count( $join_and ) ) {
188 + $join_lookup .= ' AND ( ( ' . $join_and[0] . ' ) OR ( ' . $join_and[1] . ' ) )';
189 + } else {
190 + $join_lookup = '';
191 + }
192 + } else {
193 + $join_lookup = '';
194 + }
195 + }
186 196
187 - if ( ! empty( $filter_prod_type_slugs ) && is_array( $filter_prod_type_slugs ) ) {
188 - $filter_prod_type_slugs = MainWP_DB::instance()->escape_array( $filter_prod_type_slugs );
189 - if ( ! empty( $filter_prod_type_slugs ) ) {
190 - $where .= ' AND co.product_type IN ("' . implode( '","', $filter_prod_type_slugs ) . '") ';
191 - }
192 - }
197 + if ( ! empty( $filter_prod_type_slugs ) && is_array( $filter_prod_type_slugs ) ) {
198 + $filter_prod_type_slugs = MainWP_DB::instance()->escape_array( $filter_prod_type_slugs );
199 + if ( ! empty( $filter_prod_type_slugs ) ) {
200 + $safe_prod_types = array_map( 'esc_sql', $filter_prod_type_slugs );
201 + $where .= ' AND co.product_type IN ("' . implode( '","', $safe_prod_types ) . '") ';
202 + }
203 + }
193 204
194 - if ( ! empty( $filter_cost_state ) && is_array( $filter_cost_state ) ) {
195 - $filter_cost_state = MainWP_DB::instance()->escape_array( $filter_cost_state );
196 - if ( ! empty( $filter_cost_state ) ) {
197 - $where .= ' AND co.cost_status IN ("' . implode( '","', $filter_cost_state ) . '") ';
198 - }
199 - }
205 + if ( ! empty( $filter_cost_state ) && is_array( $filter_cost_state ) ) {
206 + $filter_cost_state = MainWP_DB::instance()->escape_array( $filter_cost_state );
207 + if ( ! empty( $filter_cost_state ) ) {
208 + $safe_cost_states = array_map( 'esc_sql', $filter_cost_state );
209 + $where .= ' AND co.cost_status IN ("' . implode( '","', $safe_cost_states ) . '") ';
210 + }
211 + }
200 212
201 - $filter_next_renewal = false;
202 - if ( ! empty( $filter_dtsstart ) && is_numeric( $filter_dtsstart ) && ! empty( $filter_dtsstop ) && is_numeric( $filter_dtsstop ) && $filter_dtsstart < $filter_dtsstop ) {
203 - $filter_next_renewal = true;
204 - }
213 + $filter_next_renewal = false;
214 + if ( ! empty( $filter_dtsstart ) && is_numeric( $filter_dtsstart ) && ! empty( $filter_dtsstop ) && is_numeric( $filter_dtsstop ) && $filter_dtsstart < $filter_dtsstop ) {
215 + $filter_next_renewal = true;
216 + }
205 217
206 - if ( $filter_next_renewal ) {
207 - $stop_start = $filter_dtsstop - $filter_dtsstart;
208 - $where .= ' AND cost_status = "active" AND type = "subscription" AND ( CASE ';
209 - $where .= ' WHEN renewal_type = "weekly" AND ( ( next_renewal >= ' . intval( $filter_dtsstart ) . ' AND ( next_renewal <= ' . intval( $filter_dtsstop ) . ' ) ) OR ( next_renewal < ' . intval( $filter_dtsstart ) . ' AND ( MOD( ' . intval( $filter_dtsstop ) . ' - next_renewal, ' . intval( WEEK_IN_SECONDS ) . ' ) < ' . $stop_start . ' ) ) ) THEN true ';
210 - $where .= ' WHEN renewal_type = "monthly" AND ( ( next_renewal >= ' . intval( $filter_dtsstart ) . ' AND ( next_renewal <= ' . intval( $filter_dtsstop ) . ' ) ) OR ( next_renewal < ' . intval( $filter_dtsstart ) . ' AND ( MOD( ' . intval( $filter_dtsstop ) . ' - next_renewal, ' . intval( MONTH_IN_SECONDS ) . ' ) < ' . $stop_start . ' ) ) ) THEN true ';
211 - $where .= ' WHEN renewal_type = "yearly" AND ( ( next_renewal >= ' . intval( $filter_dtsstart ) . ' AND ( next_renewal <= ' . intval( $filter_dtsstop ) . ' ) ) OR ( next_renewal < ' . intval( $filter_dtsstart ) . ' AND ( MOD( ' . intval( $filter_dtsstop ) . ' - next_renewal, ' . intval( YEAR_IN_SECONDS ) . ' ) < ' . $stop_start . ' ) ) ) THEN true ';
212 - $where .= ' WHEN renewal_type = "quarterly" AND ( ( next_renewal >= ' . intval( $filter_dtsstart ) . ' AND ( next_renewal <= ' . intval( $filter_dtsstop ) . ' ) ) OR ( next_renewal < ' . intval( $filter_dtsstart ) . ' AND ( MOD( ' . intval( $filter_dtsstop ) . ' - next_renewal, ' . 3 * intval( MONTH_IN_SECONDS ) . ' ) < ' . $stop_start . ' ) ) ) THEN true ';
213 - $where .= ' ELSE false END ) ';
214 - }
218 + if ( $filter_next_renewal ) {
219 + $stop_start = $filter_dtsstop - $filter_dtsstart;
220 + $where .= ' AND cost_status = "active" AND type = "subscription" AND ( CASE ';
221 + $where .= ' WHEN renewal_type = "weekly" AND ( ( next_renewal >= ' . intval( $filter_dtsstart ) . ' AND ( next_renewal <= ' . intval( $filter_dtsstop ) . ' ) ) OR ( next_renewal < ' . intval( $filter_dtsstart ) . ' AND ( MOD( ' . intval( $filter_dtsstop ) . ' - next_renewal, ' . intval( WEEK_IN_SECONDS ) . ' ) < ' . $stop_start . ' ) ) ) THEN true ';
222 + $where .= ' WHEN renewal_type = "monthly" AND ( ( next_renewal >= ' . intval( $filter_dtsstart ) . ' AND ( next_renewal <= ' . intval( $filter_dtsstop ) . ' ) ) OR ( next_renewal < ' . intval( $filter_dtsstart ) . ' AND ( MOD( ' . intval( $filter_dtsstop ) . ' - next_renewal, ' . intval( MONTH_IN_SECONDS ) . ' ) < ' . $stop_start . ' ) ) ) THEN true ';
223 + $where .= ' WHEN renewal_type = "yearly" AND ( ( next_renewal >= ' . intval( $filter_dtsstart ) . ' AND ( next_renewal <= ' . intval( $filter_dtsstop ) . ' ) ) OR ( next_renewal < ' . intval( $filter_dtsstart ) . ' AND ( MOD( ' . intval( $filter_dtsstop ) . ' - next_renewal, ' . intval( YEAR_IN_SECONDS ) . ' ) < ' . $stop_start . ' ) ) ) THEN true ';
224 + $where .= ' WHEN renewal_type = "quarterly" AND ( ( next_renewal >= ' . intval( $filter_dtsstart ) . ' AND ( next_renewal <= ' . intval( $filter_dtsstop ) . ' ) ) OR ( next_renewal < ' . intval( $filter_dtsstart ) . ' AND ( MOD( ' . intval( $filter_dtsstop ) . ' - next_renewal, ' . 3 * intval( MONTH_IN_SECONDS ) . ' ) < ' . $stop_start . ' ) ) ) THEN true ';
225 + $where .= ' ELSE false END ) ';
226 + }
215 227
216 - if ( ! empty( $filter_license_type ) && is_array( $filter_license_type ) ) {
217 - $filter_license_type = MainWP_DB::instance()->escape_array( $filter_license_type );
218 - if ( ! empty( $filter_license_type ) ) {
219 - $where .= ' AND co.license_type IN ("' . implode( '","', $filter_license_type ) . '") ';
220 - }
221 - }
222 - if ( ! empty( $filter_payment_method ) && is_array( $filter_payment_method ) ) {
223 - $filter_payment_method = MainWP_DB::instance()->escape_array( $filter_payment_method );
224 - if ( ! empty( $filter_payment_method ) ) {
225 - $where .= ' AND co.payment_method IN ("' . implode( '","', $filter_payment_method ) . '") ';
226 - }
227 - }
228 - if ( ! empty( $filter_renewal_type ) && is_array( $filter_renewal_type ) ) {
229 - $filter_renewal_type = MainWP_DB::instance()->escape_array( $filter_renewal_type );
230 - if ( ! empty( $filter_renewal_type ) ) {
231 - $where .= ' AND co.renewal_type IN ("' . implode( '","', $filter_renewal_type ) . '") ';
232 - }
233 - }
228 + if ( ! empty( $filter_license_type ) && is_array( $filter_license_type ) ) {
229 + $filter_license_type = MainWP_DB::instance()->escape_array( $filter_license_type );
230 + if ( ! empty( $filter_license_type ) ) {
231 + $safe_license_types = array_map( 'esc_sql', $filter_license_type );
232 + $where .= ' AND co.license_type IN ("' . implode( '","', $safe_license_types ) . '") ';
233 + }
234 + }
235 + if ( ! empty( $filter_payment_method ) && is_array( $filter_payment_method ) ) {
236 + $filter_payment_method = MainWP_DB::instance()->escape_array( $filter_payment_method );
237 + if ( ! empty( $filter_payment_method ) ) {
238 + $safe_payment_methods = array_map( 'esc_sql', $filter_payment_method );
239 + $where .= ' AND co.payment_method IN ("' . implode( '","', $safe_payment_methods ) . '") ';
240 + }
241 + }
242 + if ( ! empty( $filter_renewal_type ) && is_array( $filter_renewal_type ) ) {
243 + $filter_renewal_type = MainWP_DB::instance()->escape_array( $filter_renewal_type );
244 + if ( ! empty( $filter_renewal_type ) ) {
245 + $safe_renewal_types = array_map( 'esc_sql', $filter_renewal_type );
246 + $where .= ' AND co.renewal_type IN ("' . implode( '","', $safe_renewal_types ) . '") ';
247 + }
248 + }
234 249
235 - /**
236 - * PARSE PAGINATION PARAMS
237 - */
238 - $limits = '';
239 - $start = isset( $args['start'] ) ? absint( $args['start'] ) : 0;
240 - $per_page = isset( $args['records_per_page'] ) ? absint( $args['records_per_page'] ) : 99999;
250 + /**
251 + * PARSE PAGINATION PARAMS
252 + */
253 + $limits = '';
254 + $start = isset( $args['start'] ) ? absint( $args['start'] ) : 0;
255 + $per_page = isset( $args['records_per_page'] ) ? absint( $args['records_per_page'] ) : 99999;
241 256
242 - if ( $per_page >= 0 ) {
243 - $limits = "LIMIT {$start}, {$per_page}";
244 - }
257 + if ( $per_page >= 0 ) {
258 + $limits = "LIMIT {$start}, {$per_page}";
259 + }
245 260
246 - // Default to sorting by record ID.
247 - $orderby = 'co.id';
261 + // Default to sorting by record ID.
262 + $orderby = 'co.id';
248 263
249 - $orderable = array( 'name', 'url', 'type', 'product_type', 'slug', 'license_type', 'cost_status', 'payment_method', 'price', 'renewal_type', 'last_renewal', 'next_renewal' );
250 - if ( isset( $args['orderby'] ) && in_array( $args['orderby'], $orderable, true ) ) {
251 - $prefix = 'co.';
252 - $orderby = sprintf( '%s%s', $prefix, $args['orderby'] );
253 - }
264 + $orderable = array( 'name', 'url', 'type', 'product_type', 'slug', 'license_type', 'cost_status', 'payment_method', 'price', 'renewal_type', 'last_renewal', 'next_renewal' );
265 + if ( isset( $args['orderby'] ) && in_array( $args['orderby'], $orderable, true ) ) {
266 + $_orderby = 'next_renewal' === $args['orderby'] ? 'next_renewal_today' : $args['orderby'];
267 + $prefix = 'co.';
268 + $orderby = sprintf( '%s%s', $prefix, $_orderby );
269 + }
254 270
255 - // Show the recent records first by default.
256 - $order = 'DESC';
257 - if ( isset( $args['order'] ) && 'ASC' === strtoupper( $args['order'] ) ) {
258 - $order = 'ASC';
259 - }
271 + // Show the recent records first by default.
272 + $order = 'DESC';
273 + if ( isset( $args['order'] ) && 'ASC' === strtoupper( $args['order'] ) ) {
274 + $order = 'ASC';
275 + }
260 276
261 - $orderby = sprintf( 'ORDER BY %s %s', $orderby, $order );
277 + $orderby = sprintf( 'ORDER BY %s %s', $orderby, $order );
262 278
263 - $selects = array();
264 - $selects[] = ' DISTINCT(co.id) dist_id '; // need at first.
265 - $selects[] = ' co.* ';
266 - $select = implode( ', ', $selects );
279 + $selects = array();
280 + $selects[] = ' DISTINCT(co.id) dist_id '; // need at first.
281 + $selects[] = ' co.* ';
282 + $select = implode( ', ', $selects );
267 283
268 - /**
269 - * BUILD THE FINAL QUERY
270 - */
271 - $query = "SELECT {$select}
272 - FROM " . $this->table_name( 'cost_tracker' ) . ' as co ' .
273 - $join_lookup .
274 - " WHERE 1 {$where}
275 - {$orderby}
276 - {$limits}";
284 + /**
285 + * BUILD THE FINAL QUERY
286 + */
287 + $cost_table = '`' . esc_sql( $this->table_name( 'cost_tracker' ) ) . '`';
288 + $query = "SELECT {$select}
289 + FROM {$cost_table} as co " .
290 + $join_lookup .
291 + " WHERE 1 {$where}
292 + {$orderby}
293 + {$limits}";
277 294
278 - //phpcs:disable Squiz.PHP.CommentedOutCode.Found
279 - // error_log( print_r( $args, true ) ); //.
280 - // error_log( $query ); //.
281 - //phpcs:enable Squiz.PHP.CommentedOutCode.Found
295 + // Build result count query.
296 + $count_query = "SELECT COUNT(DISTINCT(co.id)) as found
297 + FROM {$cost_table} as co " .
298 + $join_lookup .
299 + " WHERE 1 {$where}";
282 300
283 - // Build result count query.
284 - $count_query = 'SELECT COUNT(DISTINCT(co.id)) as found
285 - FROM ' . $this->table_name( 'cost_tracker' ) . ' as co ' .
286 - $join_lookup .
287 - " WHERE 1 {$where}";
301 + /**
302 + * QUERY THE DATABASE FOR RESULTS
303 + */
304 + $items = $this->wpdb->get_results( $query ); // phpcs:ignore -- ok.
305 + $total = absint( $this->wpdb->get_var( $count_query ) ); // phpcs:ignore -- ok.
288 306
289 - /**
290 - * QUERY THE DATABASE FOR RESULTS
291 - */
292 - $items = $this->wpdb->get_results( $query ); // phpcs:ignore -- ok.
293 - $total = absint( $this->wpdb->get_var( $count_query ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
294 -
295 - $result = array(
296 - 'items' => $items,
297 - 'count' => $total,
298 - );
299 -
300 - return $result;
301 - }
307 + return array(
308 + 'items' => $items,
309 + 'count' => $total,
310 + );
311 + }
302 312 }