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
mainwp / modules / cost-tracker / pages / page-cost-tracker-dashboard.php

page-cost-tracker-dashboard.php in MainWP Dashboard: Self-hosted WordPress Management for Agencies 6.2.2, at modules/cost-tracker/pages/page-cost-tracker-dashboard.php

1,848 lines 99.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * MainWP Module Cost Tracker Dashboard class.
4 *
5 * @package MainWP\Dashboard
6 * @version 4.6
7 */
8
9 namespace MainWP\Dashboard\Module\CostTracker;
10
11 use MainWP\Dashboard\MainWP_Post_Handler;
12 use MainWP\Dashboard\MainWP_DB;
13 use MainWP\Dashboard\MainWP_UI;
14 use MainWP\Dashboard\MainWP_Utility;
15 use MainWP\Dashboard\MainWP_DB_Client;
16 use MainWP\Dashboard\MainWP_Cache_Warm_Helper;
17
18 // Exit if accessed directly.
19 if ( ! defined( 'ABSPATH' ) ) {
20 exit;
21 }
22
23 /**
24 * Class Cost_Tracker_Dashboard
25 */
26 class Cost_Tracker_Dashboard { // phpcs:ignore -- NOSONAR - multi methods.
27 // phpcs:disable Generic.Metrics.CyclomaticComplexity -- complexity.
28 /**
29 * Variable to hold the items.
30 *
31 * @var mixed Default empty.
32 */
33 private $items = null;
34
35 /**
36 * Variable to hold the total items.
37 *
38 * @var mixed Default empty.
39 */
40 private $total_items = 0;
41
42 /**
43 * Variable to hold the order.
44 *
45 * @var mixed Default empty.
46 */
47 private static $order = '';
48
49 /**
50 * Variable to hold the order by.
51 *
52 * @var mixed Default empty.
53 */
54 private static $orderby = '';
55
56 /**
57 * Static variable to hold the single instance of the class.
58 *
59 * @static
60 *
61 * @var mixed Default null
62 */
63 private static $instance = null;
64
65 /**
66 * Get Instance
67 *
68 * Creates public static instance.
69 *
70 * @static
71 *
72 * @return Cost_Tracker_Dashboard
73 */
74 public static function get_instance() {
75 if ( null === static::$instance ) {
76 static::$instance = new self();
77 }
78 return static::$instance;
79 }
80
81 /**
82 * Constructor
83 *
84 * Runs each time the class is called.
85 */
86 public function __construct() {
87 add_action( 'admin_init', array( &$this, 'admin_init' ) );
88 }
89
90 /**
91 * Method admin_init()
92 *
93 * Admin init.
94 */
95 public function admin_init() {
96 MainWP_Post_Handler::instance()->add_action( 'mainwp_module_cost_tracker_notes_save', array( $this, 'ajax_notes_save' ) );
97 MainWP_Post_Handler::instance()->add_action( 'mainwp_module_cost_tracker_delete', array( $this, 'ajax_cost_tracker_delete' ) );
98 MainWP_Post_Handler::instance()->add_action( 'mainwp_module_cost_tracker_lists_display_rows', array( $this, 'ajax_display_rows' ) );
99 MainWP_Post_Handler::instance()->add_action( 'mainwp_module_cost_tracker_filter_save_segment', array( $this, 'ajax_costs_filter_save_segment' ) );
100 MainWP_Post_Handler::instance()->add_action( 'mainwp_module_cost_tracker_filter_load_segments', array( $this, 'ajax_costs_filter_load_segments' ) );
101 MainWP_Post_Handler::instance()->add_action( 'mainwp_module_cost_tracker_filter_delete_segment', array( $this, 'ajax_costs_filter_delete_segment' ) );
102 }
103
104
105 /**
106 * Get columns.
107 *
108 * @param bool $filtered With per site price column.
109 *
110 * @return array Array of column names.
111 */
112 public static function get_columns( $filtered = false ) {
113 $cols = array(
114 'cb' => true,
115 'cost_status' => esc_html__( 'Status', 'mainwp' ),
116 'icon' => esc_html__( 'Icon', 'mainwp' ),
117 'name' => esc_html__( 'Name', 'mainwp' ),
118 'per_site_price' => esc_html__( 'Price', 'mainwp' ),
119 'price' => esc_html__( 'Price', 'mainwp' ),
120 'license_type' => esc_html__( 'License', 'mainwp' ),
121 'product_type' => esc_html__( 'Category', 'mainwp' ),
122 'type' => esc_html__( 'Type', 'mainwp' ),
123 'last_renewal' => esc_html__( 'Last Renewal', 'mainwp' ),
124 'payment_method' => esc_html__( 'Payment method', 'mainwp' ),
125 'next_renewal' => esc_html__( 'Next Renewal', 'mainwp' ),
126 'sites' => esc_html__( 'Sites', 'mainwp' ),
127 'actions' => esc_html__( 'Action', 'mainwp' ),
128 );
129
130 if ( ! $filtered ) {
131 unset( $cols['per_site_price'] );
132 }
133 return $cols;
134 }
135
136
137 /**
138 * Get column defines.
139 *
140 * @return array $defines
141 */
142 public function get_columns_defines() {
143 $defines = array();
144 $defines[] = array(
145 'targets' => 'no-sort',
146 'orderable' => false,
147 );
148 $defines[] = array(
149 'targets' => 'title-column',
150 'className' => 'task-row-working',
151 );
152 $defines[] = array(
153 'targets' => 'date-column',
154 'className' => 'mainwp-date-cell',
155 );
156 $defines[] = array(
157 'targets' => 'state-column',
158 'className' => 'mainwp-state-cell',
159 );
160 $defines[] = array(
161 'targets' => array( 'column-sites', 'column-payment-method', 'column-license-type', 'column-icon' ),
162 'className' => 'center aligned',
163 );
164 $defines[] = array(
165 'targets' => array( 'column-site-price', 'column-price' ),
166 'className' => 'right aligned',
167 );
168 $defines[] = array(
169 'targets' => 'check-column',
170 'className' => 'check-column',
171 );
172 $defines[] = array(
173 'targets' => 'column-actions',
174 'className' => 'collapsing not-selectable',
175 );
176
177 return $defines;
178 }
179
180 /**
181 * Instantiate Columns.
182 *
183 * @param bool $filtered With per site price column.
184 *
185 * @return array $init_cols
186 */
187 public function get_columns_init( $filtered ) {
188 $cols = $this->get_columns( $filtered );
189 $init_cols = array();
190 foreach ( $cols as $key => $val ) {
191 $init_cols[] = array( 'data' => esc_html( $key ) );
192 }
193 return $init_cols;
194 }
195
196 /**
197 * Method invalidate_warm_cache()
198 */
199 public static function invalidate_warm_cache() {
200 MainWP_Cache_Warm_Helper::invalidate_manage_pages( array( 'ManageCostTracker', 'CostSummary' ) );
201 }
202
203 /**
204 * Renders overview.
205 *
206 * When the page loads render the body content.
207 */
208 public function render_overview_page() {
209 if ( ! \mainwp_current_user_can( 'dashboard', 'manage_cost_tracker' ) ) {
210 \mainwp_do_not_have_permissions( esc_html__( 'manage cost tracker', 'mainwp' ) );
211 return;
212 }
213
214 $sel_ids = isset( $_GET['selected_ids'] ) ? $_GET['selected_ids'] : ''; //phpcs:ignore -- ok.
215 $sel_ids = explode( ',', $sel_ids );
216
217 if ( ! empty( $sel_ids ) && is_array( $sel_ids ) ) {
218 global $current_user;
219 $sel_ids = MainWP_Utility::array_numeric_filter( $sel_ids );
220 if ( ! empty( $sel_ids ) ) {
221 update_user_option( $current_user->ID, 'mainwp_module_cost_tracker_onetime_filters_saved', $sel_ids );
222 }
223 }
224 $costs = Cost_Tracker_DB::get_instance()->get_cost_tracker_by( 'all' );
225 $costs_count = count( $costs );
226 Cost_Tracker_Admin::render_header();
227 ?>
228 <div id="mainwp-module-cost-tracker-dashboard-tab">
229 <?php if ( 1 > $costs_count ) : ?>
230 <div class="ui segment" style="margin-bottom:0px;">
231 <div class="ui icon message mainwp-welcome-message" style="margin-bottom:0px;">
232 <em data-emoji=":bar_chart:" class="big"></em>
233 <div class="content">
234 <div class="ui massive header"><?php esc_html_e( 'No costs tracked yet.', 'mainwp' ); ?></div>
235 <p><?php esc_html_e( 'Tracking your costs lets you forecast renewals and monitor expenses across all Child Sites.', 'mainwp' ); ?></p>
236 <a class="ui green button" href="admin.php?page=CostTrackerAdd"><?php esc_html_e( 'Start Tracking Now!', 'mainwp' ); ?></a>
237 </div>
238 </div>
239 </div>
240 <?php else : ?>
241 <?php $this->render_actions_bar(); ?>
242 <?php if ( isset( $_GET['message'] ) && 1 === (int) $_GET['message'] ) : //phpcs:ignore WordPress.Security.NonceVerification.Recommended ?>
243 <div class="ui segment">
244 <div class="ui green message" id="mainwp-module-cost-tracker-message-zone">
245 <?php esc_html_e( 'Cost saved successfully.', 'mainwp' ); ?>
246 <i class="ui close icon"></i>
247 </div>
248 </div>
249 <?php endif; ?>
250 <?php static::render_manage_tasks_table_top( $sel_ids ); ?>
251 <div class="ui padded segment">
252 <?php $this->render_dashboard_body(); ?>
253 </div>
254 <?php endif; ?>
255 </div>
256 <?php
257 }
258
259 /**
260 * Method ajax_display_rows()
261 *
262 * Handle display table rows.
263 */
264 public function ajax_display_rows() { //phpcs:ignore -- NOSONAR - complex.
265
266 MainWP_Post_Handler::instance()->check_security( 'mainwp_module_cost_tracker_lists_display_rows' );
267 $filtered_one_time_ids = get_user_option( 'mainwp_module_cost_tracker_onetime_filters_saved' );
268 if ( ! empty( $filtered_one_time_ids ) && is_array( $filtered_one_time_ids ) ) {
269 global $current_user;
270 delete_user_option( $current_user->ID, 'mainwp_module_cost_tracker_onetime_filters_saved' );
271 $filtered_one_time_ids = MainWP_Utility::array_numeric_filter( $filtered_one_time_ids );
272 }
273 $req_orderby = '';
274 $req_order = null;
275 // phpcs:disable WordPress.Security.NonceVerification
276 if ( isset( $_REQUEST['order'] ) ) {
277 $order_values = MainWP_Utility::instance()->get_table_orders( $_REQUEST );
278 $req_orderby = $order_values['orderby'];
279 $req_order = $order_values['order'];
280 }
281
282 $filters = static::get_cost_filter_params();
283
284 $get_saved = true;
285 foreach ( $filters as $filter ) {
286 if ( isset( $_REQUEST[ $filter ] ) ) {
287 $get_saved = false;
288 break;
289 }
290 }
291
292 $filter_sites_ids = '';
293 $filter_client_ids = '';
294 $filter_prod_type_slugs = '';
295 $filter_cost_state = '';
296 $filter_dtsstart = '';
297 $filter_dtsstop = '';
298
299 $filter_license_type = '';
300 $filter_payment_method = '';
301 $filter_sub_renewal_type = '';
302
303 if ( $get_saved ) {
304 $filters_saved = get_user_option( 'mainwp_module_cost_tracker_filters_saved' );
305 if ( ! is_array( $filters_saved ) ) {
306 $filters_saved = array();
307 }
308
309 $filter_sites_ids = isset( $filters_saved['sites_ids'] ) ? $filters_saved['sites_ids'] : false;
310 $filter_client_ids = isset( $filters_saved['client_ids'] ) ? $filters_saved['client_ids'] : false;
311 $filter_prod_type_slugs = isset( $filters_saved['prods_types'] ) ? $filters_saved['prods_types'] : false;
312 $filter_cost_state = isset( $filters_saved['costs_state'] ) ? $filters_saved['costs_state'] : '';
313 $filter_dtsstart = isset( $filters_saved['dtsstart'] ) ? $filters_saved['dtsstart'] : '';
314 $filter_dtsstop = isset( $filters_saved['dtsstop'] ) ? $filters_saved['dtsstop'] : '';
315
316 $filter_license_type = isset( $filters_saved['license_types'] ) && ! empty( $filters_saved['license_types'] ) ? $filters_saved['license_types'] : '';
317 $filter_sub_renewal_type = isset( $filters_saved['renewal_frequency'] ) && ! empty( $filters_saved['renewal_frequency'] ) ? $filters_saved['renewal_frequency'] : '';
318 $filter_payment_method = isset( $filters_saved['payment_methods'] ) && ! empty( $filters_saved['payment_methods'] ) ? $filters_saved['payment_methods'] : '';
319
320 } else {
321 // phpcs:disable WordPress.Security.NonceVerification
322 $filter_sites_ids = isset( $_REQUEST['sites'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['sites'] ) ) : '';
323 $filter_client_ids = isset( $_REQUEST['client'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['client'] ) ) : '';
324 $filter_prod_type_slugs = isset( $_REQUEST['prods_types'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['prods_types'] ) ) : '';
325 $filter_cost_state = isset( $_REQUEST['costs_state'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['costs_state'] ) ) : '';
326 $filter_dtsstart = isset( $_REQUEST['dtsstart'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['dtsstart'] ) ) : '';
327 $filter_dtsstop = isset( $_REQUEST['dtsstop'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['dtsstop'] ) ) : '';
328
329 $filter_license_type = isset( $_REQUEST['license_types'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['license_types'] ) ) : '';
330 $filter_sub_renewal_type = isset( $_REQUEST['renewal_frequency'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['renewal_frequency'] ) ) : '';
331 $filter_payment_method = isset( $_REQUEST['payment_methods'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['payment_methods'] ) ) : '';
332
333 // phpcs:enable WordPress.Security.NonceVerification
334 }
335
336 $array_sites_ids = array();
337 $array_clients_ids = array();
338 $array_prod_types_slugs = array();
339 $array_status_slugs = array();
340
341 $array_license_type = array();
342 $array_payment_method = array();
343 $array_sub_renewal_type = array();
344
345 if ( ! empty( $filter_sites_ids ) ) {
346 $array_sites_ids = explode( ',', $filter_sites_ids ); // convert to array.
347 if ( in_array( 'nosites', $array_sites_ids, true ) ) {
348 $array_sites_ids = false;
349 $filter_sites_ids = '';
350 }
351 }
352
353 if ( ! empty( $filter_client_ids ) ) {
354 $array_clients_ids = explode( ',', $filter_client_ids ); // convert to array.
355 if ( in_array( 'noclients', $array_clients_ids, true ) ) {
356 $array_clients_ids = false;
357 $filter_client_ids = '';
358 }
359 }
360
361 if ( ! empty( $filter_prod_type_slugs ) ) {
362 $array_prod_types_slugs = explode( ',', $filter_prod_type_slugs ); // convert to array.
363 if ( in_array( 'nocategories', $array_prod_types_slugs, true ) ) {
364 $array_prod_types_slugs = false;
365 $filter_prod_type_slugs = '';
366 }
367 }
368
369 if ( ! empty( $filter_cost_state ) ) {
370 $array_status_slugs = explode( ',', $filter_cost_state ); // convert to array.
371 if ( in_array( 'nostatus', $array_status_slugs, true ) ) {
372 $array_status_slugs = false;
373 $filter_cost_state = '';
374 }
375 }
376
377 if ( ! empty( $filter_license_type ) ) {
378 $array_license_type = explode( ',', $filter_license_type ); // convert to array.
379 if ( in_array( 'nolicensetypes', $array_license_type, true ) ) {
380 $array_license_type = false;
381 $filter_license_type = '';
382 }
383 }
384 if ( ! empty( $filter_payment_method ) ) {
385 $array_payment_method = explode( ',', $filter_payment_method ); // convert to array.
386 if ( in_array( 'nopaymentmenthods', $array_payment_method, true ) ) {
387 $array_payment_method = false;
388 $filter_payment_method = '';
389 }
390 }
391 if ( ! empty( $filter_sub_renewal_type ) ) {
392 $array_sub_renewal_type = explode( ',', $filter_sub_renewal_type ); // convert to array.
393 if ( in_array( 'norenewalfrequency', $array_sub_renewal_type, true ) ) {
394 $array_sub_renewal_type = false;
395 $filter_sub_renewal_type = '';
396 }
397 }
398
399 global $current_user;
400
401 if ( empty( $filtered_one_time_ids ) ) {
402 update_user_option(
403 $current_user->ID,
404 'mainwp_module_cost_tracker_filters_saved',
405 array(
406 'sites_ids' => $filter_sites_ids,
407 'client_ids' => $filter_client_ids,
408 'prods_types' => $filter_prod_type_slugs,
409 'costs_state' => $filter_cost_state,
410 'dtsstart' => $filter_dtsstart,
411 'dtsstop' => $filter_dtsstop,
412 'license_types' => $filter_license_type,
413 'payment_methods' => $filter_payment_method,
414 'renewal_frequency' => $filter_sub_renewal_type,
415 )
416 );
417 }
418
419 // phpcs:enable
420
421 // phpcs:disable WordPress.Security.NonceVerification
422 $per_page = isset( $_REQUEST['length'] ) ? intval( $_REQUEST['length'] ) : 25;
423
424 if ( -1 === $per_page ) {
425 $per_page = 9999;
426 }
427
428 $start = isset( $_REQUEST['start'] ) ? intval( $_REQUEST['start'] ) : 0;
429 $search = isset( $_REQUEST['search']['value'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['search']['value'] ) ) : '';
430
431 // phpcs:enable WordPress.Security.NonceVerification
432
433 $args = array(
434 'order' => ( 'asc' === $req_order ) ? 'asc' : 'desc',
435 'orderby' => $req_orderby,
436 'start' => $start,
437 'search' => $search,
438 'dtsstart' => ! empty( $filter_dtsstart ) ? $filter_dtsstart : false,
439 'dtsstop' => ! empty( $filter_dtsstop ) ? $filter_dtsstop : false,
440 'filter_clients' => $array_clients_ids,
441 'filter_sites' => $array_sites_ids,
442 'filter_prods_types' => $array_prod_types_slugs,
443 'filter_states' => $array_status_slugs,
444 'filter_license_type' => $array_license_type,
445 'filter_payment_method' => $array_payment_method,
446 'filter_renewal_type' => $array_sub_renewal_type,
447 );
448
449 $args['records_per_page'] = $per_page ? $per_page : 20;
450
451 if ( ! empty( $filtered_one_time_ids ) ) {
452 $items = Cost_Tracker_DB::get_instance()->get_cost_tracker_by( 'all', null, array( 'selected_ids' => $filtered_one_time_ids ) );
453 $this->items = ! empty( $items ) ? $items : array();
454 $this->total_items = ! empty( $items ) ? count( $items ) : 0;
455 } else {
456 $results = Cost_Tracker_DB_Query::instance()->query_costs( $args );
457 $this->items = $results['items'];
458 $this->total_items = $results['count'];
459 }
460 $output = $this->ajax_get_datatable_rows();
461 wp_send_json( $output );
462 }
463
464
465 /**
466 * Render the Dashboard tab
467 *
468 * Renders the dashboard tab content - Subscription table
469 */
470 public function render_dashboard_body() {
471 $_orderby = 'name';
472 $_order = 'desc';
473
474 static::$order = $_order;
475 static::$orderby = $_orderby;
476
477 if ( gmdate( 'Y-m-d' ) !== get_option( 'module_cost_tracker_calc_today_next_renewal', '' ) ) {
478 Cost_Tracker_DB::get_instance()->update_next_renewal_today();
479 }
480
481 $filtered = false;
482 if ( isset( $_GET['selected_ids'] ) && ! empty( $_GET['selected_ids'] ) ) { //phpcs:ignore -- ok.
483 $filtered = true;
484 }
485 ?>
486 <div id="mainwp-loading-sites" style="display: none;">
487 <div class="ui active page dimmer">
488 <div class="ui double text loader"><?php esc_html_e( 'Loading...', 'mainwp' ); ?></div>
489 </div>
490 </div>
491 <div id="mainwp-module-cost-tracker-sites-table-container" style="opacity:0;">
492 <table class="ui single line table" id="mainwp-module-cost-tracker-sites-table" style="width:100%">
493 <thead>
494 <tr>
495 <th scope="col" class="no-sort collapsing check-column column-check"><span class="ui checkbox"><input id="cb-select-all-top" type="checkbox"></span></th>
496 <th id="cost_status" class="collapsing column-status"><?php esc_html_e( 'Status', 'mainwp' ); ?></th>
497 <th id="icon" class="no-sort column-icon collapsing"></th>
498 <th id="name" class="column-name"><?php esc_html_e( 'Name', 'mainwp' ); ?></th>
499 <?php if ( $filtered ) : ?>
500 <th id="per_site_price" class="no-sort collapsing column-site-price"><?php esc_html_e( 'Per Site Price', 'mainwp' ); ?></th>
501 <th id="price" class="collapsing column-total-price"><?php esc_html_e( 'Total Price', 'mainwp' ); ?></th>
502 <?php else : ?>
503 <th id="price" class="collapsing column-price"><?php esc_html_e( 'Price', 'mainwp' ); ?></th>
504 <?php endif; ?>
505 <th id="license_type" class="collapsing column-license-type"><?php esc_html_e( 'License', 'mainwp' ); ?></th>
506 <th id="product_type" class="collapsing column-product-type"><?php esc_html_e( 'Category', 'mainwp' ); ?></th>
507 <th id="type" class="collapsing column-type"><?php esc_html_e( 'Type', 'mainwp' ); ?></th>
508 <th id="last_renewal" class="collapsing column-last-renewal"><?php esc_html_e( 'Purchased', 'mainwp' ); ?></th>
509 <th id="payment_method" class="collapsing center aligned column-payment-method"><?php esc_html_e( 'Method', 'mainwp' ); ?></th>
510 <th id="next_renewal" class="collapsing column-next-renewal"><?php esc_html_e( 'Renews', 'mainwp' ); ?></th>
511 <th id="sites" class="no-sort collapsing center aligned column-sites"><?php esc_html_e( 'Sites', 'mainwp' ); ?></th>
512 <th id="actions" class="no-sort collapsing right aligned column-actions"></th>
513 </tr>
514 </thead>
515 </table>
516 </div>
517
518 <?php
519 static::render_modal_edit_notes();
520 static::render_screen_options();
521 $sites_per_page = get_option( 'mainwp_default_sites_per_page', 25 );
522 $sites_per_page = intval( $sites_per_page );
523 $pages_length = array(
524 25 => '25',
525 10 => '10',
526 50 => '50',
527 100 => '100',
528 300 => '300',
529 );
530
531 $pages_length = $pages_length + array( $sites_per_page => $sites_per_page );
532
533 ksort( $pages_length );
534
535 if ( isset( $pages_length[-1] ) ) {
536 unset( $pages_length[-1] );
537 }
538
539 $pagelength_val = implode( ',', array_keys( $pages_length ) );
540 $pagelength_title = implode( ',', array_values( $pages_length ) );
541
542 $table_features = array(
543 'searching' => 'true',
544 'paging' => 'true',
545 'pagingType' => 'full_numbers',
546 'info' => 'true',
547 'colReorder' => '{columns:":not(.check-column):not(.column-actions)"}',
548 'stateSave' => 'true',
549 'stateDuration' => '60 * 60 * 24 * 30',
550 'order' => '[]',
551 'scrollX' => 'true',
552 'responsive' => 'true',
553 'fixedColumns' => '',
554 'searchDelay' => 350,
555 );
556
557 ?>
558 <script type="text/javascript">
559
560 jQuery( document ).ready( function( $ ) {
561 let responsive = <?php echo esc_js( $table_features['responsive'] ); ?>;
562 if( jQuery( window ).width() > 1140 ) {
563 responsive = false;
564 }
565
566 // to fix issue not loaded calendar js library
567 if (jQuery('.ui.calendar').length > 0) {
568 if (mainwpParams.use_wp_datepicker == 1) {
569 jQuery('#mainwp-module-cost-tracker-list-sub-header .ui.calendar input[type=text]').datepicker({ dateFormat: "yy-mm-dd" });
570 } else {
571 jQuery('#mainwp-module-cost-tracker-list-sub-header .ui.calendar').calendar({
572 type: 'date',
573 monthFirst: false,
574 today: true,
575 touchReadonly: false,
576 formatter: {
577 date : 'YYYY-MM-DD'
578 }
579 });
580 }
581 }
582 try {
583 $subscription_sites_table = jQuery( '#mainwp-module-cost-tracker-sites-table' ).on( 'processing.dt', function ( e, settings, processing ) {
584 jQuery( '#mainwp-loading-sites' ).css( 'display', processing ? 'block' : 'none' );
585 if (!processing) {
586 let tb = jQuery( '#mainwp-module-cost-tracker-sites-table' );
587 $( '#mainwp-module-cost-tracker-sites-table .ui.dropdown' ).dropdown();
588 $( '#mainwp-module-cost-tracker-sites-table .ui.checkbox' ).checkbox();
589 }
590 }).DataTable( {
591 "ajax": {
592 "url": ajaxurl,
593 "type": "POST",
594 "data": function ( d ) {
595 let data = mainwp_secure_data( {
596 action: 'mainwp_module_cost_tracker_lists_display_rows',
597 sites: $( '#mainwp-module-cost-tracker-costs-filter-sites').dropdown('get value'),
598 prods_types: $( '#mainwp-module-cost-tracker-costs-filter-cats').dropdown('get value'),
599 costs_state: $( '#mainwp-module-cost-tracker-costs-filter-status').dropdown('get value'),
600 license_types: $( '#mainwp-module-cost-tracker-costs-filter-license-types').dropdown('get value'),
601 renewal_frequency: $( '#mainwp-module-cost-tracker-costs-filter-renewal-frequency').dropdown('get value'),
602 payment_methods: $( '#mainwp-module-cost-tracker-costs-filter-payment-methods').dropdown('get value'),
603 client: $( '#mainwp-module-cost-tracker-costs-filter-clients').dropdown('get value'),
604 dtsstart: $('#mainwp-module-cost-tracker-costs-filter-dtsstart').val(),
605 dtsstop: $('#mainwp-module-cost-tracker-costs-filter-dtsstop').val(),
606 show_per_site_price: <?php echo $filtered ? 1 : 0; ?>,
607 } );
608 return $.extend( {}, d, data );
609 },
610 "dataSrc": function ( json ) {
611 for ( let i=0, ien=json.data.length ; i < ien ; i++ ) {
612 json.data[i].rowClass = json.rowsInfo[i].rowClass;
613 json.data[i].cost_id = json.rowsInfo[i].cost_id;
614 }
615 return json.data;
616 }
617 },
618 "responsive": responsive,
619 "searching" : <?php echo esc_js( $table_features['searching'] ); ?>,
620 "paging" : <?php echo esc_js( $table_features['paging'] ); ?>,
621 "pagingType" : "<?php echo esc_js( $table_features['pagingType'] ); ?>",
622 "info" : <?php echo esc_js( $table_features['info'] ); ?>,
623 "colReorder" : <?php echo $table_features['colReorder']; // phpcs:ignore -- specical chars. ?>,
624 "scrollX" : <?php echo esc_js( $table_features['scrollX'] ); ?>,
625 "stateSave" : <?php echo esc_js( $table_features['stateSave'] ); ?>,
626 "stateDuration" : <?php echo esc_js( $table_features['stateDuration'] ); ?>,
627 "order" : <?php echo $table_features['order']; // phpcs:ignore -- specical chars. ?>,
628 "fixedColumns" : <?php echo ! empty( $table_features['fixedColumns'] ) ? esc_js( $table_features['fixedColumns'] ) : '""'; ?>,
629 "lengthMenu" : [ [<?php echo esc_js( $pagelength_val ); ?>, -1 ], [<?php echo esc_js( $pagelength_title ); ?>, "All"] ],
630 "serverSide": true,
631 "pageLength": <?php echo intval( $sites_per_page ); ?>,
632 "columnDefs": <?php echo wp_json_encode( $this->get_columns_defines() ); ?>,
633 "columns": <?php echo wp_json_encode( $this->get_columns_init( $filtered ) ); ?>,
634 "language": {
635 "emptyTable": "<?php esc_html_e( 'No subscriptions found.', 'mainwp' ); ?>"
636 },
637 "drawCallback": function( settings ) {
638 this.api().tables().body().to$().attr( 'id', 'mainwp-module-cost-tracker-body-table' );
639 jQuery( '#mainwp-module-cost-tracker-sites-table-container' ).css( 'opacity', '1' );
640 mainwp_datatable_fix_menu_overflow('#mainwp-module-cost-tracker-sites-table');
641 },
642 "initComplete": function( settings, json ) {
643 },
644 rowCallback: function (row, data) {
645 jQuery( row ).addClass(data.rowClass);
646 jQuery( row ).attr( 'id', "cost-row-" + data.cost_id );
647 jQuery( row ).attr( 'item-id', data.cost_id );
648
649 },
650 'select': {
651 items: 'row',
652 style: 'multi+shift',
653 selector: 'tr>td.check-column'
654 },
655 stateSaveParams: function (settings, data) {
656 data._mwpv = mainwpParams.mainwpVersion || 'dev';
657 },
658 stateLoadParams: function (settings, data) {
659 if ((mainwpParams.mainwpVersion || 'dev') !== data._mwpv) return false;
660 },
661 search: { regex: false, smart: false },
662 orderMulti: false,
663 searchDelay: <?php echo intval( $table_features['searchDelay'] ); ?>
664 }).on('select', function (e, dt, type, indexes) {
665 if( 'row' == type ){
666 dt.rows(indexes)
667 .nodes()
668 .to$().find('td.check-column .ui.checkbox' ).checkbox('set checked');
669 let selectedCount = dt.rows({ selected: true }).count();
670 if (selectedCount > 0) {
671 jQuery('#mwp_cost_tracker_bulk_action').parent('.ui.dropdown').removeClass('disabled');
672 jQuery('#mainwp_module_cost_tracker_action_btn').removeClass('disabled');
673 }
674 }
675 }).on('deselect', function (e, dt, type, indexes) {
676 if( 'row' == type ){
677 dt.rows(indexes)
678 .nodes()
679 .to$().find('td.check-column .ui.checkbox' ).checkbox('set unchecked');
680 let selectedCount = dt.rows({ selected: true }).count();
681 if (selectedCount === 0) {
682 jQuery('#mwp_cost_tracker_bulk_action').parent('.ui.dropdown').addClass('disabled');
683 jQuery('#mainwp_module_cost_tracker_action_btn').addClass('disabled');
684 }
685 }
686 }).on( 'columns-reordered', function () {
687 setTimeout(() => {
688 $( '#mainwp-module-cost-tracker-sites-table .ui.dropdown' ).dropdown();
689 $( '#mainwp-module-cost-tracker-sites-table .ui.checkbox' ).checkbox();
690 mainwp_datatable_fix_menu_overflow('#mainwp-module-cost-tracker-sites-table');
691 }, 1000 );
692 } );
693 } catch(err) {
694 // to fix js error.
695 console.log(err);
696 }
697 _init_cost_tracker_sites_screen();
698 } );
699
700 mainwp_module_cost_tracker_manage_costs_filter = function() {
701 try {
702 let emptyFilter = ( '' == jQuery( '#mainwp-module-cost-tracker-costs-filter-sites').dropdown('get value') ) &&
703 ( '' == jQuery( '#mainwp-module-cost-tracker-costs-filter-cats').dropdown('get value') ) &&
704 ( '' == jQuery( '#mainwp-module-cost-tracker-costs-filter-status').dropdown('get value') ) &&
705 ( '' == jQuery( '#mainwp-module-cost-tracker-costs-filter-license-types').dropdown('get value') ) &&
706 ( '' == jQuery( '#mainwp-module-cost-tracker-costs-filter-renewal-frequency').dropdown('get value') ) &&
707 ( '' == jQuery( '#mainwp-module-cost-tracker-costs-filter-payment-methods').dropdown('get value') ) &&
708 ( '' == jQuery( '#mainwp-module-cost-tracker-costs-filter-clients').dropdown('get value') ) &&
709 ( '' == jQuery( '#mainwp-module-cost-tracker-costs-filter-dtsstart').dropdown('get value') ) &&
710 ( '' == jQuery( '#mainwp-module-cost-tracker-costs-filter-dtsstop').dropdown('get value') );
711
712 if(emptyFilter){
713 jQuery( '#mainwp_module_cost_tracker_manage_costs_reset_filters' ).attr('disabled', 'disabled');
714 } else {
715 jQuery( '#mainwp_module_cost_tracker_manage_costs_reset_filters' ).attr('disabled', false);
716 }
717
718 $subscription_sites_table.ajax.reload();
719
720 } catch(err) {
721 // to fix js error.
722 console.log(err);
723 }
724 };
725
726 mainwp_module_cost_tracker_manage_costs_reset_filters = function() {
727 try {
728 jQuery( '#mainwp-module-cost-tracker-costs-filter-clients').dropdown('clear');
729 jQuery( '#mainwp-module-cost-tracker-costs-filter-sites').dropdown('clear');
730 jQuery( '#mainwp-module-cost-tracker-costs-filter-cats').dropdown('clear');
731 jQuery( '#mainwp-module-cost-tracker-costs-filter-status').dropdown('clear');
732 jQuery( '#mainwp-module-cost-tracker-costs-filter-license-types').dropdown('clear');
733 jQuery( '#mainwp-module-cost-tracker-costs-filter-renewal-frequency').dropdown('clear');
734 jQuery( '#mainwp-module-cost-tracker-costs-filter-payment-methods').dropdown('clear');
735 jQuery('#mainwp-module-cost-tracker-costs-filter-dtsstart').val('');
736 jQuery('#mainwp-module-cost-tracker-costs-filter-dtsstop').val('');
737 $subscription_sites_table.ajax.reload();
738 jQuery( '#mainwp_module_cost_tracker_manage_costs_reset_filters' ).attr('disabled', 'disabled');
739 } catch(err) {
740 // to fix js error.
741 console.log(err);
742 }
743 };
744
745 _init_cost_tracker_sites_screen = function() {
746 jQuery( '#mainwp-module-cost-tracker-sites-screen-options-modal input[type=checkbox][id^="mainwp_show_column_"]' ).each( function() {
747 let check_id = jQuery( this ).attr( 'id' );
748 col_id = check_id.replace( "mainwp_show_column_", "" );
749 try {
750 $subscription_sites_table.column( '#' + col_id ).visible( jQuery(this).is( ':checked' ) );
751 if ( check_id.indexOf("mainwp_show_column_desktop") >= 0 ) {
752 col_id = check_id.replace( "mainwp_show_column_desktop", "" );
753 $subscription_sites_table.column( '#mobile' + col_id ).visible( jQuery(this).is( ':checked' ) ); // to set mobile columns.
754 }
755 } catch(err) {
756 // to fix js error.
757 }
758 } );
759 };
760
761 //@see hook_screen_options().
762 mainwp_module_cost_tracker_sites_screen_options = function () {
763 jQuery( '#mainwp-module-cost-tracker-sites-screen-options-modal' ).modal( {
764 allowMultiple: true,
765 onHide: function () {
766 }
767 } ).modal( 'show' );
768
769 jQuery( '#subscription-sites-screen-options-form' ).submit( function() {
770 if ( jQuery('input[name=reset_subscriptionsites_columns_order]').attr('value') == 1 ) {
771 $subscription_sites_table.colReorder.reset();
772 }
773 jQuery( '#mainwp-module-cost-tracker-sites-screen-options-modal' ).modal( 'hide' );
774 } );
775 return false;
776 };
777 </script>
778 <?php
779 }
780
781 /**
782 * Get table rows.
783 *
784 * Optimize for shared hosting or big networks.
785 *
786 * @return array Rows html.
787 */
788 public function ajax_get_datatable_rows() { //phpcs:ignore -- NOSONAR - complex.
789
790 $sel_ids = isset( $_GET['selected_ids'] ) ? $_GET['selected_ids'] : ''; //phpcs:ignore -- ok.
791 $sel_ids = explode( ',', $sel_ids );
792
793 $license_types = array(
794 'single_site' => '<span data-tooltip="Single-Site License" data-inverted="" data-position="left center"><i class="wordpress large icon"></i></span>',
795 'multi_site' => '<span data-tooltip="Multiple-Site License" data-inverted="" data-position="left center"><i class="icons"><i class="wordpress mini icon"></i><i class="top left corner large wordpress icon"></i><i class="bottom right corner large wordpress icon"></i></i></span>',
796 );
797
798 $product_types = Cost_Tracker_Admin::get_product_types();
799 $payment_methods = Cost_Tracker_Admin::get_payment_methods();
800
801 $show_per_site_price = false;
802 if ( isset( $_POST['show_per_site_price'] ) && ! empty( $_POST['show_per_site_price'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Missing
803 $show_per_site_price = true;
804 }
805
806 $current_time = time();
807 $upcoming1 = strtotime( gmdate( 'Y-m-d 00:00:00', $current_time ) );
808 $upcoming2 = strtotime( '+1 month', $current_time );
809
810 $all_rows = array();
811 $info_rows = array();
812
813 $columns = $this->get_columns( $show_per_site_price );
814
815 $product_types_icons = Cost_Tracker_Admin::get_product_type_icons();
816 $product_colors = Cost_Tracker_Admin::get_product_colors();
817
818 if ( $this->items ) {
819 foreach ( $this->items as $subscription ) {
820
821 $note = html_entity_decode( $subscription->note );
822 $esc_note = apply_filters( 'mainwp_escape_content', $note );
823 $strip_note = wp_strip_all_tags( $esc_note );
824 $last_renewal = $subscription ? $subscription->last_renewal : 0;
825
826 $sel_sites = ! empty( $subscription->sites ) ? json_decode( $subscription->sites, true ) : array();
827 $sel_groups = ! empty( $subscription->groups ) ? json_decode( $subscription->groups, true ) : array();
828 $sel_clients = ! empty( $subscription->clients ) ? json_decode( $subscription->clients, true ) : array();
829
830 if ( ! is_array( $sel_sites ) ) {
831 $sel_sites = array();
832 }
833 if ( ! is_array( $sel_groups ) ) {
834 $sel_groups = array();
835 }
836 if ( ! is_array( $sel_clients ) ) {
837 $sel_clients = array();
838 }
839
840 $url_manage_sites = '';
841
842 $params = array(
843 'sites' => $sel_sites,
844 'groups' => $sel_groups,
845 'clients' => $sel_clients,
846 );
847
848 $sub_sites = MainWP_DB::instance()->get_db_sites( $params );
849 $num_sites = count( $sub_sites );
850 if ( $num_sites > 0 ) {
851 $filter_sites = ! empty( $sel_sites ) ? '&selected_sites=' . implode( ',', $sel_sites ) : '';
852 $filter_groups = ! empty( $sel_groups ) ? '&g=' . implode( ',', $sel_groups ) : '';
853 $filter_clients = ! empty( $sel_clients ) ? '&client=' . implode( ',', $sel_clients ) : '';
854 $url_manage_sites = 'admin.php?page=managesites' . $filter_sites . $filter_groups . $filter_clients;
855 }
856
857 $rw_classes = 'cost-item cost-tracker-item-' . intval( $subscription->id ) . ' cost-tracker-type-' . ( isset( $product_types[ $subscription->product_type ] ) ? $product_types[ $subscription->product_type ] : '' );
858 $info_item = array(
859 'rowClass' => esc_html( $rw_classes ),
860 'cost_id' => intval( $subscription->id ),
861 );
862
863 $cols_data = array();
864
865 foreach ( $columns as $column_name => $column_display_name ) {
866 ob_start();
867 switch ( $column_name ) {
868 case 'cb':
869 ?>
870 <span class="ui checkbox" data-tooltip="<?php esc_attr_e( 'Click to select the site.', 'mainwp' ); ?>" data-inverted="" data-position="right center"><input type="checkbox" name="checked[]"></span>
871 <?php
872 break;
873 case 'cost_status':
874 ?>
875 <?php echo Cost_Tracker_Admin::get_cost_status_label( $subscription->cost_status ); //phpcs:ignore -- escaped. ?>
876 <?php
877 break;
878 case 'icon':
879 ?>
880 <?php echo Cost_Tracker_Admin::get_instance()->get_product_icon_display( $subscription ); //phpcs:ignore -- escaped.?>
881 <?php
882 break;
883 case 'name':
884 ?>
885 <a class="item" href="admin.php?page=CostTrackerAdd&id=<?php echo intval( $subscription->id ); ?>"><?php echo esc_html( $subscription->name ); ?></a>
886 <?php
887 break;
888 case 'per_site_price':
889 if ( 'single_site' === $subscription->license_type ) {
890 $per_site_price = $subscription->price;
891 } else {
892 $per_site_price = ( $num_sites > 0 ) ? ( $subscription->price / $num_sites ) : 0;
893 }
894
895 $next30_price = 0;
896 if ( 'active' === $subscription->cost_status && 'subscription' === $subscription->type ) {
897 $next_rl = $subscription->next_renewal;
898 if ( $next_rl <= $upcoming1 ) {
899 $next_rl = Cost_Tracker_Admin::get_next_renewal( $upcoming1, $subscription->renewal_type, false );
900 }
901 while ( $next_rl <= $upcoming2 ) {
902 if ( $next_rl > $upcoming1 && $next_rl <= $upcoming2 ) {
903 $next30_price += $per_site_price;
904 }
905 $next_rl = Cost_Tracker_Admin::get_next_renewal( $next_rl, $subscription->renewal_type, false );
906 }
907 }
908 ?>
909 <strong><?php Cost_Tracker_Utility::cost_tracker_format_price( $next30_price ); ?></strong>
910 <?php
911 break;
912 case 'price':
913 echo ! empty( $url_manage_sites ) ? '<a href="' . esc_url( $url_manage_sites ) . '">' . Cost_Tracker_Utility::cost_tracker_format_price( $subscription->price, true ) . '</a>' : Cost_Tracker_Utility::cost_tracker_format_price( $subscription->price ); //phpcs:ignore -- ok.
914 break;
915 case 'license_type':
916 ?>
917 <?php echo isset( $license_types[ $subscription->license_type ] ) ? $license_types[ $subscription->license_type ] : ''; //phpcs:ignore -- ok. ?>
918 <?php
919 break;
920 case 'type':
921 ?>
922 <?php echo 'lifetime' === $subscription->type ? '<span data-tooltip="Lifetime license" data-inverted="" data-position="left center"><div class="ui grey fluid label"><i class="infinity icon"></i>L</div></span>' : '<span data-tooltip="Recurring subscription" data-inverted="" data-position="left center"><div class="ui black fluid label"><i class="calendar alternate outline icon"></i><strong>' . esc_html( substr( ucfirst( $subscription->renewal_type ), 0, 1 ) ) . '</strong></div></span>'; ?>
923 <?php
924 break;
925 case 'product_type':
926 ?>
927 <?php echo isset( $product_types[ $subscription->product_type ] ) ? '<div class="ui label" style="color:#ffffff;background-color:' . esc_attr( Cost_Tracker_Admin::get_product_colors( $subscription->product_type ) ) . '"><i class="' . str_replace( 'deficon:', '', esc_attr( Cost_Tracker_Admin::get_product_type_icons( $subscription->product_type ) ) ) . ' icon"></i>' . esc_html( $product_types[ $subscription->product_type ] ) . '</div>' : ''; //phpcs:ignore -- ok. ?>
928 <?php
929 break;
930 case 'last_renewal':
931 ?>
932 <?php echo $last_renewal ? '<em>' . MainWP_Utility::format_date( $last_renewal ) . '</em>': ''; //phpcs:ignore -- escaped. ?>
933 <?php
934 break;
935 case 'payment_method':
936 ?>
937 <?php echo isset( $payment_methods[ $subscription->payment_method ] ) ? Cost_Tracker_Utility::get_payment_method_icon( $payment_methods[ $subscription->payment_method ] ) : ''; // phpcs:ignore -- ok.?>
938 <?php
939 break;
940 case 'next_renewal':
941 $next_renewal = Cost_Tracker_Admin::get_next_renewal( $subscription->last_renewal, $subscription->renewal_type );
942 Cost_Tracker_Admin::generate_next_renewal( $subscription, $next_renewal );
943 break;
944 case 'sites':
945 ?>
946 <?php echo ! empty( $url_manage_sites ) ? '<a href="' . esc_url( $url_manage_sites ) . '">' . '<div class="ui blue small label"><i class="wordpress icon"></i>' . count( $sub_sites ) . '</div>' . '</a>' : '<div class="ui small label"><i class="wordpress icon"></i> 0</div>'; //phpcs:ignore -- WP icon. ?>
947 <?php
948 break;
949 case 'actions':
950 ?>
951 <div class="ui right pointing dropdown">
952 <a href="javascript:void(0)" aria-label="<?php esc_attr_e( 'Actions menu', 'mainwp' ); ?>"><i class="ellipsis vertical icon"></i></a>
953 <div class="menu">
954 <a class="item" href="admin.php?page=CostTrackerAdd&id=<?php echo intval( $subscription->id ); ?>"><?php esc_html_e( 'Edit', 'mainwp' ); ?></a>
955 <?php if ( empty( $subscription->note ) ) : ?>
956 <a href="javascript:void(0)" class="item mainwp-edit-sub-note"><?php esc_html_e( 'Add Notes', 'mainwp' ); ?></a>
957 <?php else : ?>
958 <a href="javascript:void(0)" class="item mainwp-edit-sub-note" data-tooltip="<?php echo esc_attr( substr( wp_unslash( $strip_note ), 0, 100 ) ); ?>" data-position="left center" data-inverted=""><?php esc_html_e( 'View Notes', 'mainwp' ); ?></a>
959 <?php endif; ?>
960 <span style="display: none" id="sub-notes-<?php echo intval( $subscription->id ); ?>-note"><?php echo wp_unslash( $esc_note ); //phpcs:ignore -- escaped. ?></span>
961 <a class="item subscription_menu_item_delete" href="javascript:void(0)"><?php esc_html_e( 'Delete', 'mainwp' ); ?></a>
962 <a class="item subscription_menu_item_duplicate" href="admin.php?page=CostTrackerAdd&duplicate_id=<?php echo intval( $subscription->id ); ?>"><?php esc_html_e( 'Duplicate', 'mainwp' ); ?></a>
963 </div>
964 </div>
965 <?php
966 break;
967 default:
968 break;
969 }
970 $cols_data[ $column_name ] = ob_get_clean();
971 }
972 $all_rows[] = $cols_data;
973 $info_rows[] = $info_item;
974 }
975 }
976 return array(
977 'data' => $all_rows,
978 'recordsTotal' => $this->total_items,
979 'recordsFiltered' => $this->total_items,
980 'rowsInfo' => $info_rows,
981 );
982 }
983
984 /**
985 * Method ajax_notes_save()
986 *
987 * Post handler for save notes.
988 */
989 public function ajax_notes_save() {
990 MainWP_Post_Handler::instance()->check_security( 'mainwp_module_cost_tracker_notes_save' );
991 //phpcs:disable WordPress.Security.NonceVerification.Missing
992 $sub_id = isset( $_POST['subid'] ) ? intval( $_POST['subid'] ) : 0;
993 $sub = Cost_Tracker_DB::get_instance()->get_cost_tracker_by( 'id', $sub_id );
994 if ( $sub_id && $sub ) {
995 $note = isset( $_POST['note'] ) ? wp_unslash( $_POST['note'] ) : ''; //phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- mainwp_escape_content.
996 $esc_note = apply_filters( 'mainwp_escape_content', $note );
997 $update = array(
998 'id' => $sub_id,
999 'note' => $esc_note,
1000 );
1001 Cost_Tracker_DB::get_instance()->update_cost_tracker( $update );
1002 die(
1003 wp_json_encode(
1004 array(
1005 'result' => 'SUCCESS',
1006 'esc_note_content' => $esc_note,
1007 )
1008 )
1009 );
1010 } else {
1011 die( wp_json_encode( array( 'error' => esc_html__( 'Invalid cost tracker ID or item not found.', 'mainwp' ) ) ) );
1012 }
1013 //phpcs:enable
1014 }
1015
1016 /**
1017 * Method ajax_costs_filter_save_segment()
1018 *
1019 * Post handler for save segment.
1020 */
1021 public function ajax_costs_filter_save_segment() {
1022 MainWP_Post_Handler::instance()->check_security( 'mainwp_module_cost_tracker_filter_save_segment' );
1023 //phpcs:disable WordPress.Security.NonceVerification.Missing
1024
1025 $not_filters = array(
1026 'seg_sites' => 'nosites',
1027 'seg_clients' => 'noclients',
1028 'seg_prods_types' => 'nocategories',
1029 'seg_costs_state' => 'nostatus',
1030 'seg_license_types' => 'nolicensetypes',
1031 'seg_payment_methods' => 'nopaymentmenthods',
1032 'seg_renewal_frequency' => 'norenewalfrequency',
1033 );
1034
1035 $fields = array(
1036 'name',
1037 'seg_sites',
1038 'seg_clients',
1039 'seg_prods_types',
1040 'seg_costs_state',
1041 'seg_license_types',
1042 'seg_renewal_frequency',
1043 'seg_payment_methods',
1044 'seg_dtsstart',
1045 'seg_dtsstop',
1046 );
1047
1048 $save_fields = array();
1049
1050 foreach ( $fields as $field ) {
1051 if ( isset( $_POST[ $field ] ) ) {
1052 $val_seg = sanitize_text_field( wp_unslash( $_POST[ $field ] ) );
1053 if ( isset( $not_filters[ $field ] ) && false !== strpos( $val_seg, $not_filters[ $field ] ) ) {
1054 $val_seg = '';
1055 }
1056 $save_fields[ $field ] = $val_seg;
1057 }
1058 }
1059
1060 $seg_id = ! empty( $_POST['seg_id'] ) ? sanitize_text_field( wp_unslash( $_POST['seg_id'] ) ) : time();
1061 //phpcs:enable WordPress.Security.NonceVerification.Missing
1062
1063 $saved_segments = $this->set_get_cost_filter_segments();
1064 if ( ! is_array( $saved_segments ) ) {
1065 $saved_segments = array();
1066 }
1067 $saved_segments[ $seg_id ] = $save_fields;
1068 $this->set_get_cost_filter_segments( true, $saved_segments );
1069 die( wp_json_encode( array( 'result' => 'SUCCESS' ) ) );
1070 }
1071
1072
1073 /**
1074 * Method set_get_cost_filter_segments()
1075 *
1076 * @param bool $set_val Get or set value.
1077 * @param array $saved_segments segments value.
1078 */
1079 public function set_get_cost_filter_segments( $set_val = false, $saved_segments = array() ) {
1080 global $current_user;
1081 if ( $current_user && ! empty( $current_user->ID ) ) {
1082 if ( $set_val ) {
1083 update_user_option( $current_user->ID, 'mainwp_module_cost_tracker_filter_saved_segments', $saved_segments );
1084 } else {
1085 $values = get_user_option( 'mainwp_module_cost_tracker_filter_saved_segments' );
1086 if ( ! is_array( $values ) ) {
1087 $values = array();
1088 }
1089 return $values;
1090 }
1091 }
1092 return array();
1093 }
1094
1095 /**
1096 * Method ajax_costs_filter_load_segments()
1097 *
1098 * Post handler for save segment.
1099 */
1100 public function ajax_costs_filter_load_segments() {
1101 MainWP_Post_Handler::instance()->check_security( 'mainwp_module_cost_tracker_filter_load_segments' );
1102 $saved_segments = $this->set_get_cost_filter_segments();
1103 $list_segs = '';
1104 if ( is_array( $saved_segments ) && ! empty( $saved_segments ) ) {
1105 $list_segs .= '<select id="mainwp_module_cost_tracker_edit_payment_type" class="ui fluid dropdown">';
1106 $list_segs .= '<option segment-filters="" value="">' . esc_html__( 'Select a segment', 'mainwp' ) . '</option>';
1107 foreach ( $saved_segments as $sid => $values ) {
1108 if ( empty( $values['name'] ) ) {
1109 continue;
1110 }
1111 $list_segs .= '<option segment-filters="' . esc_attr( wp_json_encode( $values ) ) . '" value="' . esc_attr( $sid ) . '">' . esc_html( $values['name'] ) . '</option>';
1112 }
1113 $list_segs .= '</select>';
1114 }
1115 die( wp_json_encode( array( 'result' => $list_segs ) ) ); //phpcs:ignore -- ok.
1116 }
1117
1118 /**
1119 * Method ajax_costs_filter_delete_segment()
1120 *
1121 * Post handler for save segment.
1122 */
1123 public function ajax_costs_filter_delete_segment() {
1124 MainWP_Post_Handler::instance()->check_security( 'mainwp_module_cost_tracker_filter_delete_segment' );
1125 $seg_id = ! empty( $_POST['seg_id'] ) ? sanitize_text_field( wp_unslash( $_POST['seg_id'] ) ) : 0; //phpcs:ignore -- ok.
1126
1127 $saved_segments = $this->set_get_cost_filter_segments();
1128 if ( ! empty( $seg_id ) && is_array( $saved_segments ) && isset( $saved_segments[ $seg_id ] ) ) {
1129 unset( $saved_segments[ $seg_id ] );
1130 $this->set_get_cost_filter_segments( true, $saved_segments );
1131 die( wp_json_encode( array( 'result' =>'SUCCESS' ) ) ); //phpcs:ignore -- ok.
1132 }
1133 die( wp_json_encode( array( 'error' => esc_html__( 'Segment not found. Please try again.', 'mainwp' ) ) ) ); //phpcs:ignore -- ok.
1134 }
1135
1136
1137
1138 /**
1139 * Method ajax_cost_tracker_delete()
1140 *
1141 * Post handler for save notes.
1142 */
1143 public function ajax_cost_tracker_delete() {
1144 MainWP_Post_Handler::instance()->check_security( 'mainwp_module_cost_tracker_delete' );
1145 $sub_id = isset( $_POST['sub_id'] ) ? intval( $_POST['sub_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
1146
1147 if ( Cost_Tracker_DB::get_instance()->delete_cost_tracker( 'id', $sub_id ) ) {
1148 static::invalidate_warm_cache();
1149 die( wp_json_encode( array( 'status' => 'success' ) ) );
1150 } else {
1151 die( wp_json_encode( array( 'error' => esc_html__( 'Failed.', 'mainwp' ) ) ) );
1152 }
1153 }
1154
1155 /**
1156 * Render Actions Bar
1157 *
1158 * Renders the actions bar on the Dashboard tab.
1159 */
1160 public function render_actions_bar() {
1161 ?>
1162 <div class="mainwp-sub-header">
1163 <div class="ui two columns grid">
1164 <div class="column ui mini form">
1165 <select class="ui dropdown disabled" id="mwp_cost_tracker_bulk_action">
1166 <option value="-1"><?php esc_html_e( 'Bulk actions', 'mainwp' ); ?></option>
1167 <option value="delete-sub"><?php esc_html_e( 'Delete', 'mainwp' ); ?></option>
1168 </select>
1169 <input type="button" name="mainwp_module_cost_tracker_action_btn" id="mainwp_module_cost_tracker_action_btn" class="ui basic mini button disabled" value="<?php esc_html_e( 'Apply', 'mainwp' ); ?>"/>
1170 <?php do_action( 'mainwp_module_cost_tracker_actions_bar_left' ); ?>
1171 </div>
1172 <div class="right aligned middle aligned column">
1173 <div class="ui stackable grid">
1174 <div class="eight wide right aligned middle aligned column"><?php do_action( 'mainwp_module_cost_tracker_actions_bar_right' ); ?></div>
1175 <div class="eight wide right aligned middle aligned column"><a href="admin.php?page=CostTrackerAdd" class="ui mini green button" aria-label="<?php esc_attr_e( 'Add Cost', 'mainwp' ); ?>"><i class="plus icon"></i> <?php esc_html_e( 'Add Cost', 'mainwp' ); ?></a> <a href="#" class="ui mini basic button" id="mainwp-manage-costs-filter-toggle-button" aria-label="<?php esc_attr_e( 'Available filters.', 'mainwp' ); ?>"><i class="filter grey icon"></i> <?php esc_html_e( 'Filter Costs', 'mainwp' ); ?></a></div>
1176 </div>
1177 </div>
1178 </div>
1179 <script type="text/javascript">
1180 jQuery( document ).on( 'click', '#mainwp-manage-costs-filter-toggle-button', function () {
1181 jQuery( '#mainwp-module-cost-tracker-list-sub-header' ).toggle( 300 );
1182 return false;
1183 } );
1184 </script>
1185 </div>
1186 <?php
1187 }
1188
1189
1190 /**
1191 * Method get_cost_filter_params().
1192 *
1193 * @return array filters params.
1194 */
1195 public static function get_cost_filter_params() {
1196 return array( 'sites', 'client', 'prods_types', 'costs_state', 'dtsstart', 'dtsstop', 'license_types', 'renewal_frequency', 'payment_methods' );
1197 }
1198
1199 /**
1200 * Render Manage Tasks Table Top.
1201 *
1202 * @param bool $sel_one_time_ids selected one time ids.
1203 *
1204 * @return void
1205 */
1206 public static function render_manage_tasks_table_top( $sel_one_time_ids = false ) { //phpcs:ignore -- NOSONAR - complex.
1207
1208 $filters = static::get_cost_filter_params();
1209
1210 $get_saved = true;
1211 foreach ( $filters as $filter ) {
1212 if ( isset( $_REQUEST[ $filter ] ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended -- ok.
1213 $get_saved = false;
1214 break;
1215 }
1216 }
1217
1218 $filter_sites_ids = '';
1219 $filter_client_ids = '';
1220 $filter_prod_type_slugs = '';
1221 $filter_cost_state = '';
1222 $filter_dtsstart = '';
1223 $filter_dtsstop = '';
1224
1225 $filter_license_type = '';
1226 $filter_payment_method = '';
1227 $filter_sub_renewal_type = '';
1228
1229 $redirect_site_id = isset( $_GET['site_id'] ) ? intval( $_GET['site_id'] ) : 0; //phpcs:ignore -- ok.
1230
1231 if ( ! $sel_one_time_ids ) {
1232 if ( $get_saved ) {
1233 $filters_saved = get_user_option( 'mainwp_module_cost_tracker_filters_saved' );
1234 if ( ! is_array( $filters_saved ) ) {
1235 $filters_saved = array();
1236 }
1237 $filter_sites_ids = isset( $filters_saved['sites_ids'] ) && ! empty( $filters_saved['sites_ids'] ) ? $filters_saved['sites_ids'] : false;
1238 $filter_client_ids = isset( $filters_saved['client_ids'] ) && ! empty( $filters_saved['client_ids'] ) ? $filters_saved['client_ids'] : false;
1239 $filter_prod_type_slugs = isset( $filters_saved['prods_types'] ) && ! empty( $filters_saved['prods_types'] ) ? $filters_saved['prods_types'] : false;
1240 $filter_cost_state = isset( $filters_saved['costs_state'] ) && ! empty( $filters_saved['costs_state'] ) ? $filters_saved['costs_state'] : '';
1241 $filter_dtsstart = isset( $filters_saved['dtsstart'] ) && ! empty( $filters_saved['dtsstart'] ) ? $filters_saved['dtsstart'] : '';
1242 $filter_dtsstop = isset( $filters_saved['dtsstop'] ) && ! empty( $filters_saved['dtsstop'] ) ? $filters_saved['dtsstop'] : '';
1243
1244 $filter_license_type = isset( $filters_saved['license_types'] ) && ! empty( $filters_saved['license_types'] ) ? $filters_saved['license_types'] : '';
1245 $filter_sub_renewal_type = isset( $filters_saved['renewal_frequency'] ) && ! empty( $filters_saved['renewal_frequency'] ) ? $filters_saved['renewal_frequency'] : '';
1246 $filter_payment_method = isset( $filters_saved['payment_methods'] ) && ! empty( $filters_saved['payment_methods'] ) ? $filters_saved['payment_methods'] : '';
1247 } else {
1248 // phpcs:disable WordPress.Security.NonceVerification
1249 $filter_sites_ids = isset( $_REQUEST['sites_ids'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['sites_ids'] ) ) : '';
1250 $filter_client_ids = isset( $_REQUEST['client'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['client'] ) ) : '';
1251 $filter_prod_type_slugs = isset( $_REQUEST['prods_types'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['prods_types'] ) ) : '';
1252 $filter_cost_state = isset( $_REQUEST['costs_state'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['costs_state'] ) ) : '';
1253 $filter_dtsstart = isset( $_REQUEST['dtsstart'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['dtsstart'] ) ) : '';
1254 $filter_dtsstop = isset( $_REQUEST['dtsstop'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['dtsstop'] ) ) : '';
1255
1256 $filter_license_type = isset( $_REQUEST['license_types'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['license_types'] ) ) : '';
1257 $filter_sub_renewal_type = isset( $_REQUEST['renewal_frequency'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['renewal_frequency'] ) ) : '';
1258 $filter_payment_method = isset( $_REQUEST['payment_methods'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['payment_methods'] ) ) : '';
1259 // phpcs:enable WordPress.Security.NonceVerification
1260 }
1261 } elseif ( $redirect_site_id ) {
1262 $filter_sites_ids = $redirect_site_id;
1263 $filter_dtsstart = gmdate( 'Y-m-d' );
1264 $filter_dtsstop = gmdate( 'Y-m-d', time() + 30 * DAY_IN_SECONDS );
1265 }
1266
1267 $empty_filter = true;
1268 if ( ! $sel_one_time_ids ) {
1269 $empty_filter = empty( $filter_sites_ids ) && empty( $filter_client_ids ) && empty( $filter_prod_type_slugs ) && empty( $filter_cost_state ) && empty( $filter_dtsstart ) && empty( $filter_dtsstop ) && empty( $filter_license_type ) && empty( $filter_sub_renewal_type ) && empty( $filter_payment_method );
1270 }
1271
1272 $all_defaults = Cost_Tracker_Admin::get_default_fields_values();
1273 $product_types = $all_defaults['product_types'];
1274 $cost_status = $all_defaults['cost_status'];
1275
1276 $license_types = $all_defaults['license_types'];
1277 $renewal_frequency = $all_defaults['renewal_frequency'];
1278 $payment_methods = $all_defaults['payment_methods'];
1279
1280 $saved_segments = static::get_instance()->set_get_cost_filter_segments();
1281
1282 $filters_row_style = 'display:none';
1283
1284 if ( ! empty( $filter_sites_ids ) || ! empty( $filter_client_ids ) || ! empty( $filter_prod_type_slugs ) || ! empty( $filter_cost_state ) || ! empty( $filter_license_type ) || ! empty( $filter_sub_renewal_type ) || ! empty( $filter_payment_method ) || ! empty( $filter_dtsstart ) || ! empty( $filter_dtsstop ) ) {
1285 $filters_row_style = 'display:block';
1286 }
1287
1288 ?>
1289 <div class="mainwp-sub-header" id="mainwp-module-cost-tracker-list-sub-header" style="<?php echo esc_attr( $filters_row_style ); ?>">
1290 <div class="ui stackable compact grid mini form" id="mainwp-module-cost-tracker-costs-filters-row">
1291 <div class="thirteen wide column ui compact grid">
1292 <div class="three wide middle aligned column">
1293 <div id="mainwp-module-cost-tracker-costs-filter-sites" class="ui fluid selection multiple dropdown seg_sites">
1294 <input type="hidden" value="<?php echo esc_html( $filter_sites_ids ); ?>">
1295 <i class="dropdown icon"></i>
1296 <div class="default text"><?php esc_html_e( 'All sites', 'mainwp' ); ?></div>
1297 <div class="menu">
1298 <?php
1299 $websites = MainWP_DB::instance()->query( MainWP_DB::instance()->get_sql_wp_for_current_user() );
1300 foreach ( $websites as $site ) {
1301 ?>
1302 <div class="item" data-value="<?php echo intval( $site['id'] ); ?>"><?php echo esc_html( stripslashes( $site['name'] ) ); ?></div>
1303 <?php
1304 }
1305 ?>
1306 <div class="item" data-value="nosites"><?php esc_html_e( 'All sites', 'mainwp' ); ?></div>
1307 </div>
1308 </div>
1309 </div>
1310 <div class="three wide middle aligned column">
1311 <div id="mainwp-module-cost-tracker-costs-filter-clients" class="ui fluid selection multiple dropdown seg_clients">
1312 <input type="hidden" value="<?php echo esc_html( $filter_client_ids ); ?>">
1313 <i class="dropdown icon"></i>
1314 <div class="default text"><?php esc_html_e( 'All clients', 'mainwp' ); ?></div>
1315 <div class="menu">
1316 <?php
1317 $clients = MainWP_DB_Client::instance()->get_wp_client_by( 'all' );
1318
1319 foreach ( $clients as $client ) {
1320 ?>
1321 <div class="item" data-value="<?php echo intval( $client->client_id ); ?>"><?php echo esc_html( stripslashes( $client->name ) ); ?></div>
1322 <?php
1323 }
1324 ?>
1325 <div class="item" data-value="noclients"><?php esc_html_e( 'All clients', 'mainwp' ); ?></div>
1326 </div>
1327 </div>
1328 </div>
1329 <div class="three wide middle aligned column">
1330 <div id="mainwp-module-cost-tracker-costs-filter-cats" class="ui fluid selection multiple dropdown seg_prods_types">
1331 <input type="hidden" value="<?php echo esc_html( $filter_prod_type_slugs ); ?>">
1332 <i class="dropdown icon"></i>
1333 <div class="default text"><?php esc_html_e( 'All categories', 'mainwp' ); ?></div>
1334 <div class="menu">
1335 <?php
1336 foreach ( $product_types as $pro_type => $pro_name ) {
1337 ?>
1338 <div class="item" data-value="<?php echo esc_attr( $pro_type ); ?>"><?php echo esc_html( stripslashes( $pro_name ) ); ?></div>
1339 <?php
1340 }
1341 ?>
1342 <div class="item" data-value="nocategories"><?php esc_html_e( 'All categories', 'mainwp' ); ?></div>
1343 </div>
1344 </div>
1345 </div>
1346 <div class="three wide middle aligned column">
1347 <div id="mainwp-module-cost-tracker-costs-filter-status" class="ui fluid selection multiple dropdown seg_costs_state">
1348 <input type="hidden" value="<?php echo esc_html( $filter_cost_state ); ?>">
1349 <i class="dropdown icon"></i>
1350 <div class="default text"><?php esc_html_e( 'All statuses', 'mainwp' ); ?></div>
1351 <div class="menu">
1352 <?php
1353 foreach ( $cost_status as $status => $status_name ) {
1354 ?>
1355 <div class="item" data-value="<?php echo esc_attr( $status ); ?>"><?php echo esc_html( stripslashes( $status_name ) ); ?></div>
1356 <?php
1357 }
1358 ?>
1359 <div class="item" data-value="nostatus"><?php esc_html_e( 'All statuses', 'mainwp' ); ?></div>
1360 </div>
1361 </div>
1362 </div>
1363 <div class="three wide middle aligned column">
1364 <div id="mainwp-module-cost-tracker-costs-filter-license-types" class="ui fluid selection multiple dropdown seg_license_types">
1365 <input type="hidden" value="<?php echo esc_attr( $filter_license_type ); ?>">
1366 <i class="dropdown icon"></i>
1367 <div class="default text"><?php esc_html_e( 'All license types', 'mainwp' ); ?></div>
1368 <div class="menu">
1369 <?php
1370 foreach ( $license_types as $key => $title ) {
1371 ?>
1372 <div class="item" data-value="<?php echo esc_attr( $key ); ?>"><?php echo esc_html( $title ); ?></div>
1373 <?php
1374 }
1375 ?>
1376 <div class="item" data-value="nolicensetypes"><?php esc_html_e( 'All license types', 'mainwp' ); ?></div>
1377 </div>
1378 </div>
1379 </div>
1380 <div class="three wide middle aligned column">
1381 <div id="mainwp-module-cost-tracker-costs-filter-renewal-frequency" class="ui fluid selection multiple dropdown seg_renewal_frequency">
1382 <input type="hidden" value="<?php echo esc_attr( $filter_sub_renewal_type ); ?>">
1383 <i class="dropdown icon"></i>
1384 <div class="default text"><?php esc_html_e( 'All Subscription types', 'mainwp' ); ?></div>
1385 <div class="menu">
1386 <?php
1387 foreach ( $renewal_frequency as $key => $title ) {
1388 ?>
1389 <div class="item" data-value="<?php echo esc_attr( $key ); ?>"><?php echo esc_html( $title ); ?></div>
1390 <?php
1391 }
1392 ?>
1393 <div class="item" data-value="norenewalfrequency"><?php esc_html_e( 'All Subscription types', 'mainwp' ); ?></div>
1394 </div>
1395 </div>
1396 </div>
1397 <div class="three wide middle aligned column">
1398 <div id="mainwp-module-cost-tracker-costs-filter-payment-methods" class="ui fluid selection multiple dropdown seg_payment_methods">
1399 <input type="hidden" value="<?php echo esc_attr( $filter_payment_method ); ?>">
1400 <i class="dropdown icon"></i>
1401 <div class="default text"><?php esc_html_e( 'All methods', 'mainwp' ); ?></div>
1402 <div class="menu">
1403 <?php
1404 foreach ( $payment_methods as $key => $title ) {
1405 ?>
1406 <div class="item" data-value="<?php echo esc_attr( $key ); ?>"><?php echo esc_html( $title ); ?></div>
1407 <?php
1408 }
1409 ?>
1410 <div class="item" data-value="nopaymentmenthods"><?php esc_html_e( 'All methods', 'mainwp' ); ?></div>
1411 </div>
1412 </div>
1413 </div>
1414 <div class="three wide middle aligned column">
1415 <div class="ui calendar fluid mainwp_datepicker seg_dtsstart">
1416 <div class="ui fluid input left icon">
1417 <i class="calendar icon"></i>
1418 <input type="text" autocomplete="off" placeholder="<?php esc_attr_e( 'Renews period start date', 'mainwp' ); ?>" id="mainwp-module-cost-tracker-costs-filter-dtsstart" value="<?php echo ! empty( $filter_dtsstart ) ? esc_attr( $filter_dtsstart ) : ''; ?>"/>
1419 </div>
1420 </div>
1421 </div>
1422 <div class="three wide middle aligned column">
1423 <div class="ui calendar fluid mainwp_datepicker seg_dtsstop">
1424 <div class="ui fluid input left icon">
1425 <i class="calendar icon"></i>
1426 <input type="text" autocomplete="off" placeholder="<?php esc_attr_e( 'Renews period end date', 'mainwp' ); ?>" id="mainwp-module-cost-tracker-costs-filter-dtsstop" value="<?php echo ! empty( $filter_dtsstop ) ? esc_attr( $filter_dtsstop ) : ''; ?>"/>
1427 </div>
1428 </div>
1429 </div>
1430 <div class="three wide middle aligned right aligned column">
1431 <button onclick="mainwp_module_cost_tracker_manage_costs_filter()" class="ui mini green basic button"><i class="filter icon"></i> <?php esc_html_e( 'Filter', 'mainwp' ); ?></button>
1432 <button onclick="mainwp_module_cost_tracker_manage_costs_reset_filters()" id="mainwp_module_cost_tracker_manage_costs_reset_filters" class="ui mini button" <?php echo $empty_filter ? 'disabled' : ''; ?>><i class="times icon"></i> <?php esc_html_e( 'Reset', 'mainwp' ); ?></button>
1433 </div>
1434 </div>
1435 <div class="three wide top aligned right aligned column">
1436 <div class="ui compact stackable grid">
1437 <div class="eight wide column"></div>
1438 <div class="eight wide column">
1439 <button class="ui mini green fluid button" id="module-cost-tracker-filter-save-segment-button" selected-segment-id="" selected-segment-name=""><?php esc_html_e( 'Save Segment', 'mainwp' ); ?></button>
1440 <br/>
1441 <?php if ( ! empty( $saved_segments ) ) : ?>
1442 <button class="ui mini fluid button mainwp_module_cost_tracker_filter_choose_segment"><?php esc_html_e( 'Load Segment', 'mainwp' ); ?></button>
1443 <?php else : ?>
1444 <button class="ui mini fluid disabled button"><?php esc_html_e( 'Load Segment', 'mainwp' ); ?></button>
1445 <?php endif; ?>
1446 </div>
1447 </div>
1448
1449 </div>
1450 </div>
1451 </div>
1452 <style>
1453
1454 </style>
1455 <script type="text/javascript">
1456 jQuery( document ).ready( function( $ ) {
1457
1458 jQuery('#module-cost-tracker-filter-save-segment-button').on( 'click', function () {
1459 jQuery( '#mainwp-cost-tracker-segment-edit-fields' ).show();
1460 jQuery( '#mainwp-cost-tracker-edit-segment-save' ).show();
1461 jQuery( '#mainwp-cost-tracker-segment-select-fields' ).hide();
1462 jQuery( '#mainwp-cost-tracker-select-segment-choose-button' ).hide();
1463 jQuery( '#mainwp-cost-tracker-select-segment-delete-button' ).hide();
1464 jQuery('#mainwp-cost-tracker-edit-segment-name').val(jQuery(this).attr('selected-segment-name'));
1465 mainwp_module_cost_tracker_show_segments_modal();
1466 } );
1467
1468 jQuery('.mainwp_module_cost_tracker_filter_choose_segment').on( 'click', function () {
1469 jQuery( '#mainwp-cost-tracker-segment-edit-fields' ).hide();
1470 jQuery( '#mainwp-cost-tracker-edit-segment-save' ).hide();
1471 jQuery( '#mainwp-cost-tracker-segment-select-fields' ).show();
1472 jQuery( '#mainwp-cost-tracker-select-segment-choose-button' ).show();
1473 jQuery( '#mainwp-cost-tracker-select-segment-delete-button' ).show();
1474 mainwp_module_cost_tracker_show_segments_modal(true);
1475 } );
1476
1477 mainwp_module_cost_tracker_hide_segments_message = function () {
1478 jQuery('#mainwp-cost-tracker-edit-segment-status').removeClass('red green').hide();
1479 };
1480
1481 mainwp_module_cost_tracker_show_segments_modal = function (loadSeg) {
1482 mainwp_module_cost_tracker_hide_segments_message();
1483 jQuery( '#mainwp-module-cost-tracker-segment-modal' ).modal( {
1484 allowMultiple: false,
1485 onShow: function () {
1486 if(typeof loadSeg !== "undefined" && loadSeg){
1487 mainwp_module_cost_tracker_load_segments();
1488 }
1489 }
1490 } ).modal( 'show' );
1491 };
1492
1493 mainwp_module_cost_tracker_load_segments = function () {
1494 jQuery('#mainwp-cost-tracker-segment-select-fields').hide();
1495 let data = mainwp_secure_data({
1496 action: 'mainwp_module_cost_tracker_filter_load_segments',
1497 });
1498 jQuery('#mainwp-cost-tracker-edit-segment-status').html('<i class="notched circle loading icon"></i> ' + __('Loading segments. Please wait...')).show();
1499 jQuery.post(ajaxurl, data, function (response) {
1500 if (response.error != undefined) {
1501 jQuery('#mainwp-cost-tracker-edit-segment-status').html(response.error).addClass('red');
1502 } else if (response.result) {
1503 jQuery('#mainwp-cost-tracker-edit-segment-status').hide();
1504 jQuery('#mainwp-cost-tracker-segments-lists-wrapper').html(response.result);
1505 jQuery( '#mainwp-cost-tracker-segments-lists-wrapper .ui.dropdown' ).dropdown();
1506 jQuery('#mainwp-cost-tracker-segment-select-fields').show();
1507 } else {
1508 jQuery('#mainwp-cost-tracker-edit-segment-status').html(__('No saved segments.')).addClass('red');
1509 }
1510 }, 'json');
1511 };
1512
1513 jQuery('#mainwp-cost-tracker-edit-segment-save').on( 'click', function () {
1514
1515 mainwp_module_cost_tracker_hide_segments_message();
1516
1517 let seg_name = jQuery('#mainwp-cost-tracker-edit-segment-name').val().trim();
1518
1519 if('' == seg_name){
1520 jQuery('#mainwp-cost-tracker-edit-segment-status').html(__('Please enter segment name.')).addClass('red').show();
1521 return false;
1522 }
1523
1524 let data = mainwp_secure_data({
1525 action: 'mainwp_module_cost_tracker_filter_save_segment',
1526 name: seg_name,
1527 seg_sites: $( '#mainwp-module-cost-tracker-costs-filter-sites').dropdown('get value'),
1528 seg_clients: $( '#mainwp-module-cost-tracker-costs-filter-clients').dropdown('get value'),
1529 seg_prods_types: $( '#mainwp-module-cost-tracker-costs-filter-cats').dropdown('get value'),
1530 seg_costs_state: $( '#mainwp-module-cost-tracker-costs-filter-status').dropdown('get value'),
1531 seg_license_types: $( '#mainwp-module-cost-tracker-costs-filter-license-types').dropdown('get value'),
1532 seg_renewal_frequency: $( '#mainwp-module-cost-tracker-costs-filter-renewal-frequency').dropdown('get value'),
1533 seg_payment_methods: $( '#mainwp-module-cost-tracker-costs-filter-payment-methods').dropdown('get value'),
1534 seg_dtsstart: $('#mainwp-module-cost-tracker-costs-filter-dtsstart').val(),
1535 seg_dtsstop: $('#mainwp-module-cost-tracker-costs-filter-dtsstop').val(),
1536 seg_id:$('#module-cost-tracker-filter-save-segment-button').attr('selected-segment-id'),
1537 });
1538
1539 jQuery('#mainwp-cost-tracker-edit-segment-status').html('<i class="notched circle loading icon"></i> ' + __('Saving segment. Please wait...')).show();
1540
1541 jQuery.post(ajaxurl, data, function (response) {
1542 if (response.error != undefined) {
1543 jQuery('#mainwp-cost-tracker-edit-segment-status').html(response.error).addClass('red');
1544 } else if (response.result == 'SUCCESS') {
1545 jQuery('#mainwp-cost-tracker-edit-segment-status').html(__('Segment saved successfully.')).addClass('green');
1546 setTimeout(function () {
1547 jQuery('#mainwp-cost-tracker-edit-segment-status').fadeOut(300);
1548 jQuery( '#mainwp-module-cost-tracker-segment-modal' ).modal('hide');
1549 }, 2000);
1550 } else {
1551 jQuery('#mainwp-cost-tracker-edit-segment-status').html(__('Undefined error occurred while saving your segment!')).addClass('red');
1552 }
1553 }, 'json');
1554
1555
1556
1557 return false;
1558 });
1559
1560 jQuery('#mainwp-cost-tracker-select-segment-choose-button').on( 'click', function () {
1561 mainwp_module_cost_tracker_hide_segments_message();
1562 let seg_id = jQuery( '#mainwp-cost-tracker-segment-select-fields .ui.dropdown').dropdown('get value');
1563 let seg_values = '';
1564 if('' != seg_id ) {
1565 seg_values = jQuery( '#mainwp-cost-tracker-segment-select-fields select > option[value="' +seg_id+ '"]').attr('segment-filters');
1566 }
1567
1568 let valErr = true;
1569 let arrVal = '';
1570
1571 let fieldsAllows = [
1572 'seg_sites',
1573 'seg_clients',
1574 'seg_prods_types',
1575 'seg_costs_state',
1576 'seg_license_types',
1577 'seg_renewal_frequency',
1578 'seg_payment_methods',
1579 'seg_dtsstart',
1580 'seg_dtsstop',
1581 ];
1582 if('' != seg_values ) {
1583 try {
1584 seg_values = JSON.parse(seg_values);
1585 if('' != seg_values){
1586 jQuery( '#module-cost-tracker-filter-save-segment-button' ).attr('selected-segment-id',seg_id);
1587 jQuery( '#module-cost-tracker-filter-save-segment-button' ).attr('selected-segment-name',seg_values.name);
1588
1589 for (const [key, value] of Object.entries(seg_values)) {
1590 try {
1591 if(fieldsAllows.includes(key)){
1592 if( 'seg_dtsstart' !== key && 'seg_dtsstop' !== key ){
1593 jQuery( '#mainwp-module-cost-tracker-costs-filters-row .ui.dropdown.' + key ).dropdown('clear');
1594 arrVal = value.split(",");
1595 jQuery( '#mainwp-module-cost-tracker-costs-filters-row .ui.dropdown.' + key ).dropdown('set selected', arrVal);
1596 } else {
1597 jQuery( '#mainwp-module-cost-tracker-costs-filters-row .ui.calendar.' + key ).calendar('set date', value );
1598 }
1599 }
1600 } catch (err) {
1601 console.log(err);
1602 }
1603 }
1604 jQuery( '#mainwp-module-cost-tracker-segment-modal' ).modal('hide');
1605 mainwp_module_cost_tracker_manage_costs_filter();
1606 valErr = false;
1607 }
1608 } catch (err) {
1609 console.log(err);
1610 }
1611 }
1612 if(valErr){
1613 jQuery('#mainwp-cost-tracker-edit-segment-status').html(__('Undefined error segment values! Please try again.')).addClass('red').show();
1614 }
1615 });
1616
1617
1618 jQuery('#mainwp-cost-tracker-select-segment-delete-button').on( 'click', function () {
1619 mainwp_module_cost_tracker_hide_segments_message();
1620 let delBtn = this;
1621 let seg_id = jQuery( '#mainwp-cost-tracker-segment-select-fields .ui.dropdown').dropdown('get value');
1622 if('' == seg_id){
1623 return false;
1624 }
1625
1626 if('yes' === jQuery(delBtn).attr('running')){
1627 return false;
1628 }
1629
1630 jQuery(seg_id).attr('running', 'yes');
1631 let data = mainwp_secure_data({
1632 action: 'mainwp_module_cost_tracker_filter_delete_segment',
1633 seg_id: seg_id,
1634 });
1635 jQuery('#mainwp-cost-tracker-edit-segment-status').html('<i class="notched circle loading icon"></i> ' + __('Deleting segment. Please wait...')).show();
1636 jQuery.post(ajaxurl, data, function (response) {
1637
1638 jQuery(delBtn).removeAttr('running');
1639
1640 if (response.error != undefined) {
1641 jQuery('#mainwp-cost-tracker-edit-segment-status').html(response.error).addClass('red');
1642 } else if (response.result == 'SUCCESS') {
1643 jQuery('#mainwp-cost-tracker-edit-segment-status').html(__('Segment deleted successfully.')).addClass('green');
1644 setTimeout(function () {
1645 jQuery('#mainwp-cost-tracker-edit-segment-status').fadeOut(300);
1646 jQuery( '#mainwp-module-cost-tracker-segment-modal' ).modal('hide');
1647 }, 2000);
1648 } else {
1649 jQuery('#mainwp-cost-tracker-edit-segment-status').html(__('Undefined error occurred while deleting your segment!')).addClass('red');
1650 }
1651 }, 'json');
1652
1653 return false;
1654 });
1655
1656 } );
1657 </script>
1658 <?php
1659 static::render_modal_save_segment();
1660 }
1661
1662
1663 /**
1664 * Method render_modal_save_segment()
1665 *
1666 * Render modal window.
1667 *
1668 * @return void
1669 */
1670 public static function render_modal_save_segment() {
1671 ?>
1672 <div id="mainwp-module-cost-tracker-segment-modal" class="ui tiny modal">
1673 <i class="close icon" id="mainwp-notes-subs-cancel"></i>
1674 <div class="header"><?php esc_html_e( 'Save Segment', 'mainwp' ); ?></div>
1675 <div class="content" id="mainwp-cost-tracker-segment-content">
1676 <div id="mainwp-cost-tracker-edit-segment-status" class="ui message hidden"></div>
1677 <div id="mainwp-cost-tracker-segment-edit-fields" class="ui form">
1678 <div class="field">
1679 <label><?php esc_html_e( 'Enter the segment name', 'mainwp' ); ?></label>
1680 </div>
1681 <div class="field">
1682 <input type="text" id="mainwp-cost-tracker-edit-segment-name" value=""/>
1683 </div>
1684 </div>
1685 <div id="mainwp-cost-tracker-segment-select-fields" style="display:none;">
1686 <div class="field">
1687 <label><?php esc_html_e( 'Select a segment', 'mainwp' ); ?></label>
1688 </div>
1689 <div class="field">
1690 <div id="mainwp-cost-tracker-segments-lists-wrapper"></div>
1691 </div>
1692 </div>
1693 </div>
1694 <div class="actions">
1695 <div class="ui grid">
1696 <div class="eight wide left aligned middle aligned column">
1697 <input type="button" class="ui green button" id="mainwp-cost-tracker-edit-segment-save" value="<?php esc_attr_e( 'Save', 'mainwp' ); ?>"/>
1698 <input type="button" class="ui green button" id="mainwp-cost-tracker-select-segment-choose-button" value="<?php esc_attr_e( 'Choose', 'mainwp' ); ?>" style="display:none;"/>
1699 <input type="button" class="ui basic button" id="mainwp-cost-tracker-select-segment-delete-button" value="<?php esc_attr_e( 'Delete', 'mainwp' ); ?>" style="display:none;"/>
1700 </div>
1701 <div class="eight wide column">
1702
1703 </div>
1704 </div>
1705 </div>
1706 </div>
1707 <?php
1708 }
1709
1710 /**
1711 * Method render_modal_edit_notes()
1712 *
1713 * Render modal window for edit notes.
1714 *
1715 * @param string $what What modal window to render. Default = site.
1716 *
1717 * @return void
1718 */
1719 public static function render_modal_edit_notes( $what = 'site' ) {
1720 ?>
1721 <div id="mainwp-notes-subs-modal" class="ui modal">
1722 <i class="close icon" id="mainwp-notes-subs-cancel"></i>
1723 <div class="header"><?php esc_html_e( 'Notes', 'mainwp' ); ?></div>
1724 <div class="content" id="mainwp-notes-subs-content">
1725 <div id="mainwp-notes-subs-status" class="ui message hidden"></div>
1726 <div id="mainwp-notes-subs-html"></div>
1727 <div id="mainwp-notes-subs-editor" class="ui form" style="display:none;">
1728 <div class="field">
1729 <label><?php esc_html_e( 'Edit note', 'mainwp' ); ?></label>
1730 <textarea id="mainwp-notes-subs-note"></textarea>
1731 </div>
1732 <div><?php esc_html_e( 'Allowed HTML tags:', 'mainwp' ); ?> &lt;p&gt;, &lt;strong&gt;, &lt;em&gt;, &lt;br&gt;, &lt;hr&gt;, &lt;a&gt;, &lt;ul&gt;, &lt;ol&gt;, &lt;li&gt;, &lt;h1&gt;, &lt;h2&gt; </div>
1733 </div>
1734 </div>
1735 <div class="actions">
1736 <div class="ui grid">
1737 <div class="eight wide left aligned middle aligned column">
1738 <input type="button" class="ui green button" id="mainwp-notes-subs-save" value="<?php esc_attr_e( 'Save Note', 'mainwp' ); ?>" style="display:none;"/>
1739 <input type="button" class="ui green button" id="mainwp-notes-subs-edit" value="<?php esc_attr_e( 'Edit Note', 'mainwp' ); ?>"/>
1740 </div>
1741 <div class="eight wide column">
1742 <input type="hidden" id="mainwp-notes-subs-subid" value=""/>
1743 <input type="hidden" id="mainwp-notes-subs-slug" value=""/>
1744 <input type="hidden" id="mainwp-which-note" value="<?php echo esc_html( $what ); ?>"/>
1745 </div>
1746 </div>
1747 </div>
1748 </div>
1749
1750 <?php
1751 }
1752
1753 /**
1754 * Render Page Settings.
1755 */
1756 public static function render_screen_options() {
1757
1758 $columns = static::get_columns();
1759
1760 $show_cols = get_user_option( 'mainwp_module_costs_tracker_manage_showhide_columns' );
1761
1762 if ( ! is_array( $show_cols ) ) {
1763 $show_cols = array();
1764 }
1765
1766 ?>
1767 <div class="ui modal" id="mainwp-module-cost-tracker-sites-screen-options-modal">
1768 <div class="header"><?php esc_html_e( 'Page Settings', 'mainwp' ); ?></div>
1769 <div class="scrolling content ui form">
1770 <form method="POST" action="" id="subscription-sites-screen-options-form" name="subscription_sites_screen_options_form">
1771 <?php MainWP_UI::generate_wp_nonce( 'mainwp-admin-nonce' ); ?>
1772 <input type="hidden" name="wp_nonce" value="<?php echo esc_attr( wp_create_nonce( 'CostTrackerSitesScrOptions' ) ); ?>" />
1773 <div class="ui grid field">
1774 <label class="six wide column"><?php esc_html_e( 'Show columns', 'mainwp' ); ?></label>
1775 <div class="ten wide column">
1776 <ul class="mainwp_hide_wpmenu_checkboxes">
1777 <?php
1778 foreach ( $columns as $name => $title ) {
1779 if ( 'cb' === $name ) {
1780 continue;
1781 }
1782 ?>
1783 <li>
1784 <div class="ui checkbox">
1785 <input type="checkbox"
1786 <?php
1787 $show_col = ! isset( $show_cols[ $name ] ) || ( 1 === (int) $show_cols[ $name ] );
1788 if ( $show_col ) {
1789 echo 'checked="checked"';
1790 }
1791 ?>
1792 id="mainwp_show_column_<?php echo esc_attr( $name ); ?>" name="mainwp_show_column_<?php echo esc_attr( $name ); ?>" value="<?php echo esc_attr( $name ); ?>">
1793 <label for="mainwp_show_column_<?php echo esc_attr( $name ); ?>" ><?php echo $title; //phpcs:ignore ?></label>
1794 <input type="hidden" value="<?php echo esc_attr( $name ); ?>" name="show_columns_name[]" />
1795 </div>
1796 </li>
1797 <?php
1798 }
1799 ?>
1800 </ul>
1801 </div>
1802 </div>
1803 </div>
1804 <div class="actions">
1805 <div class="ui two columns grid">
1806 <div class="left aligned column">
1807 <span data-tooltip="<?php esc_attr_e( 'Returns this page to the state it was in when installed. The feature also restores any column you have moved through the drag and drop feature on the page.', 'mainwp' ); ?>" data-inverted="" data-position="top center"><input type="button" class="ui button" name="reset" id="reset-subscriptionsites-settings" value="<?php esc_attr_e( 'Reset Page', 'mainwp' ); ?>" /></span>
1808 </div>
1809 <div class="ui right aligned column">
1810 <input type="submit" class="ui green button" name="btnSubmit" id="submit-subscriptionsites-settings" value="<?php esc_attr_e( 'Save Settings', 'mainwp' ); ?>" />
1811 <div class="ui cancel button"><?php esc_html_e( 'Close', 'mainwp' ); ?></div>
1812 </div>
1813 </div>
1814 </div>
1815 <input type="hidden" name="reset_subscriptionsites_columns_order" value="0">
1816 </form>
1817 </div>
1818 <div class="ui small modal" id="mainwp-module-cost-tracker-sites-site-preview-screen-options-modal">
1819 <div class="header"><?php esc_html_e( 'Screen Options', 'mainwp' ); ?></div>
1820 <div class="scrolling content ui form">
1821 <span><?php esc_html_e( 'Would you like to turn on home screen previews? This function queries WordPress.com servers to capture a screenshot of your site the same way comments shows you preview of URLs.', 'mainwp' ); ?>
1822 </div>
1823 <div class="actions">
1824 <div class="ui ok button"><?php esc_html_e( 'Yes', 'mainwp' ); ?></div>
1825 <div class="ui cancel button"><?php esc_html_e( 'No', 'mainwp' ); ?></div>
1826 </div>
1827 </div>
1828 <script type="text/javascript">
1829 jQuery( document ).ready( function () {
1830 jQuery('#reset-subscriptionsites-settings').on( 'click', function () {
1831 mainwp_confirm(__( 'Are you sure?' ), function(){
1832 jQuery('.mainwp_hide_wpmenu_checkboxes input[id^="mainwp_show_column_"]').prop( 'checked', false );
1833 //default columns
1834 let cols = ['name','type','product_type','price','cost_status','license_type','last_renewal','next_renewal','payment_method','sites','actions'];
1835 jQuery.each( cols, function ( index, value ) {
1836 jQuery('.mainwp_hide_wpmenu_checkboxes input[id="mainwp_show_column_' + value + '"]').prop( 'checked', true );
1837 } );
1838 jQuery('input[name=reset_subscriptionsites_columns_order]').attr('value',1);
1839 jQuery('#submit-subscriptionsites-settings').click();
1840 }, false, false, true );
1841 return false;
1842 });
1843 } );
1844 </script>
1845 <?php
1846 }
1847 }
1848