PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.4.3
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.4.3
4.0.8 4.0.7 4.0.6 4.0.5 4.0.4 4.0.3 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.1 3.1.2 3.1.3 3.10.0 3.10.1 3.10.10 3.10.11 3.10.12 3.10.13 3.10.14 3.10.15 3.10.2 3.10.3 All 149 releases
← All changes | classes/Visualizer/Module/Chart.php +95 -434 4.0.53.4.3 View file →
@@ -69,8 +69,9 @@
69 69
70 70 $this->_addAjaxAction( Visualizer_Plugin::ACTION_SAVE_FILTER_QUERY, 'saveFilter' );
71 71
72 72 $this->_addFilter( 'visualizer_get_sidebar', 'getSidebar', 10, 2 );
73 +
73 74 }
74 75
75 76 /**
76 77 * Generates the HTML of the sidebar for the chart.
@@ -133,30 +134,12 @@
133 134 ),
134 135 )
135 136 );
136 137
137 - if ( Visualizer_Module::is_pro() ) {
138 - $is_woocommerce_report = filter_input(
139 - INPUT_POST,
140 - 'is_woocommerce_report',
141 - FILTER_VALIDATE_BOOLEAN
142 - );
143 -
144 - if ( $is_woocommerce_report ) {
145 - update_post_meta( $chart_id, Visualizer_Plugin::CF_IS_WOOCOMMERCE_SOURCE, true );
146 - } else {
147 - delete_post_meta( $chart_id, Visualizer_Plugin::CF_IS_WOOCOMMERCE_SOURCE );
148 - }
149 - }
150 -
151 138 delete_post_meta( $chart_id, Visualizer_Plugin::CF_JSON_SCHEDULE );
152 139
153 140 if ( -1 < $time ) {
154 141 add_post_meta( $chart_id, Visualizer_Plugin::CF_JSON_SCHEDULE, $time );
155 - // Update schedules.
156 - $schedules = get_option( Visualizer_Plugin::CF_JSON_SCHEDULE, array() );
157 - $schedules[ $chart_id ] = time() + $time * HOUR_IN_SECONDS;
158 - update_option( Visualizer_Plugin::CF_JSON_SCHEDULE, $schedules );
159 142 }
160 143 wp_send_json_success();
161 144 }
162 145
@@ -169,12 +152,8 @@
169 152 */
170 153 public function getJsonRoots() {
171 154 check_ajax_referer( Visualizer_Plugin::ACTION_JSON_GET_ROOTS . Visualizer_Plugin::VERSION, 'security' );
172 155
173 - if ( ! current_user_can( 'edit_posts' ) ) {
174 - wp_send_json_error( array( 'msg' => esc_html__( 'You do not have permission to perform this action.', 'visualizer' ) ) );
175 - }
176 -
177 156 $params = wp_parse_args( $_POST['params'] );
178 157
179 158 $source = new Visualizer_Source_Json( $params );
180 159
@@ -195,12 +174,8 @@
195 174 */
196 175 public function getJsonData() {
197 176 check_ajax_referer( Visualizer_Plugin::ACTION_JSON_GET_DATA . Visualizer_Plugin::VERSION, 'security' );
198 177
199 - if ( ! current_user_can( 'edit_posts' ) ) {
200 - wp_send_json_error( array( 'msg' => esc_html__( 'You do not have permission to perform this action.', 'visualizer' ) ) );
201 - }
202 -
203 178 $params = wp_parse_args( $_POST['params'] );
204 179
205 180 $chart_id = $params['chart'];
206 181
@@ -239,12 +214,11 @@
239 214
240 215 $chart = get_post( $chart_id );
241 216
242 217 $source = new Visualizer_Source_Json( $params );
243 - update_post_meta( $chart->ID, Visualizer_Plugin::CF_EDITABLE_TABLE, true );
244 218 $source->fetchFromEditableTable();
245 219
246 - $content = $source->getData( get_post_meta( $chart->ID, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) );
220 + $content = $source->getData();
247 221 $chart->post_content = $content;
248 222 wp_update_post( $chart->to_array() );
249 223 update_post_meta( $chart->ID, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
250 224 update_post_meta( $chart->ID, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() );
@@ -266,16 +240,8 @@
266 240 if ( ! empty( $params['paging'] ) ) {
267 241 add_post_meta( $chart->ID, Visualizer_Plugin::CF_JSON_PAGING, $params['paging'] );
268 242 }
269 243
270 - if ( Visualizer_Module::is_pro() ) {
271 - if ( ! empty( $params['vz_woo_source'] ) ) {
272 - update_post_meta( $chart->ID, Visualizer_Plugin::CF_JSON_WOOCOMMERCE_SOURCE, $params['vz_woo_source'] );
273 - } else {
274 - delete_post_meta( $chart->ID, Visualizer_Plugin::CF_JSON_WOOCOMMERCE_SOURCE );
275 - }
276 - }
277 -
278 244 $time = filter_input(
279 245 INPUT_POST,
280 246 'time',
281 247 FILTER_VALIDATE_INT,
@@ -299,13 +265,13 @@
299 265 delete_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_SCHEDULE );
300 266
301 267 $render = new Visualizer_Render_Page_Update();
302 268 $render->id = $chart->ID;
303 - $render->data = json_encode( $source->getRawData( get_post_meta( $chart_id, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) ) );
269 + $render->data = json_encode( $source->getRawData() );
304 270 $render->series = json_encode( $source->getSeries() );
305 271 $render->render();
306 272
307 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
273 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
308 274 }
309 275
310 276
311 277 /**
@@ -381,13 +347,13 @@
381 347 * @since 1.0.0
382 348 *
383 349 * @access private
384 350 *
385 - * @param WP_Post|null $chart The chart object.
351 + * @param WP_Post $chart The chart object.
386 352 *
387 353 * @return array The array of chart data.
388 354 */
389 - private function _getChartArray( $chart = null ) {
355 + private function _getChartArray( WP_Post $chart = null ) {
390 356 if ( is_null( $chart ) ) {
391 357 $chart = $this->_chart;
392 358 }
393 359 $type = get_post_meta( $chart->ID, Visualizer_Plugin::CF_CHART_TYPE, true );
@@ -409,13 +375,8 @@
409 375 }
410 376
411 377 $date_formats = Visualizer_Source::get_date_formats_if_exists( $series, $data );
412 378
413 - $code = '';
414 - if ( 'd3' === $library ) {
415 - $code = get_post_meta( $chart->ID, Visualizer_Module_AIBuilder::CF_D3_CODE, true );
416 - }
417 -
418 379 return array(
419 380 'type' => $type,
420 381 'series' => $series,
421 382 'settings' => $settings,
@@ -420,9 +381,8 @@
420 381 'series' => $series,
421 382 'settings' => $settings,
422 383 'data' => $data,
423 384 'library' => $library,
424 - 'code' => $code,
425 385 'css' => $css,
426 386 'date_formats' => $date_formats,
427 387 );
428 388 }
@@ -439,9 +399,9 @@
439 399 public static function _sendResponse( $results ) {
440 400 header( 'Content-type: application/json' );
441 401 nocache_headers();
442 402 echo json_encode( $results );
443 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
403 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
444 404 }
445 405
446 406 /**
447 407 * Deletes a chart from database.
@@ -473,22 +433,9 @@
473 433 $success = $chart && $chart->post_type === Visualizer_Plugin::CPT_VISUALIZER;
474 434 }
475 435 }
476 436 if ( $success ) {
477 - global $sitepress;
478 - if ( Visualizer_Module::is_pro() && ( function_exists( 'icl_get_languages' ) && $sitepress instanceof \SitePress ) ) {
479 - $trid = $sitepress->get_element_trid( $chart_id, 'post_' . Visualizer_Plugin::CPT_VISUALIZER );
480 - $translations = $sitepress->get_element_translations( $trid );
481 - if ( ! empty( $translations ) ) {
482 - foreach ( $translations as $translated_post ) {
483 - wp_delete_post( $translated_post->element_id, true );
484 - }
485 - } else {
486 - wp_delete_post( $chart_id, true );
487 - }
488 - } else {
489 - wp_delete_post( $chart_id, true );
490 - }
437 + wp_delete_post( $chart_id, true );
491 438 }
492 439 if ( $is_post ) {
493 440 self::_sendResponse(
494 441 array(
@@ -536,108 +483,44 @@
536 483 *
537 484 * @access public
538 485 */
539 486 public function renderChartPages() {
540 - if ( ! current_user_can( 'edit_posts' ) ) {
541 - wp_die( __( 'You do not have permission to access this page.', 'visualizer' ) );
542 - }
543 -
544 487 defined( 'IFRAME_REQUEST' ) || define( 'IFRAME_REQUEST', 1 );
545 - if ( ! defined( 'ET_BUILDER_PRODUCT_VERSION' ) && function_exists( 'et_get_theme_version' ) ) {
546 - define( 'ET_BUILDER_PRODUCT_VERSION', et_get_theme_version() );
547 - }
548 - // Set current screen for the render chart.
549 - set_current_screen( 'visualizer_render_chart' );
550 488 // check chart, if chart not exists, will create new one and redirects to the same page with proper chart id
551 489 $chart_id = isset( $_GET['chart'] ) ? filter_var( $_GET['chart'], FILTER_VALIDATE_INT ) : '';
552 - if ( ! empty( $_POST ) ) {
553 - $_POST = map_deep( $_POST, 'wp_strip_all_tags' );
554 - }
555 - $chart = $chart_id ? get_post( $chart_id ) : null;
556 - if ( ! $chart_id || ! $chart || $chart->post_type !== Visualizer_Plugin::CPT_VISUALIZER ) {
557 - if ( empty( $_GET['lang'] ) || empty( $_GET['parent_chart_id'] ) ) {
558 - $this->deleteOldCharts();
559 - $default_type = isset( $_GET['type'] ) && ! empty( $_GET['type'] ) ? $_GET['type'] : 'line';
560 - $chart_status = Visualizer_Module_Admin::checkChartStatus( $default_type );
561 - if ( ! $chart_status ) {
562 - $default_type = 'line';
563 - }
564 - $source = new Visualizer_Source_Csv( VISUALIZER_ABSPATH . DIRECTORY_SEPARATOR . 'samples' . DIRECTORY_SEPARATOR . $default_type . '.csv' );
565 - $source->fetch();
566 - $chart_id = wp_insert_post(
490 + if ( ! $chart_id || ! ( $chart = get_post( $chart_id ) ) || $chart->post_type !== Visualizer_Plugin::CPT_VISUALIZER ) {
491 + $this->deleteOldCharts();
492 + $default_type = isset( $_GET['type'] ) && ! empty( $_GET['type'] ) ? $_GET['type'] : 'line';
493 + $source = new Visualizer_Source_Csv( VISUALIZER_ABSPATH . DIRECTORY_SEPARATOR . 'samples' . DIRECTORY_SEPARATOR . $default_type . '.csv' );
494 + $source->fetch();
495 + $chart_id = wp_insert_post(
496 + array(
497 + 'post_type' => Visualizer_Plugin::CPT_VISUALIZER,
498 + 'post_title' => 'Visualization',
499 + 'post_author' => get_current_user_id(),
500 + 'post_status' => 'auto-draft',
501 + 'post_content' => $source->getData(),
502 + )
503 + );
504 + if ( $chart_id && ! is_wp_error( $chart_id ) ) {
505 + add_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_TYPE, $default_type );
506 + add_post_meta( $chart_id, Visualizer_Plugin::CF_DEFAULT_DATA, 1 );
507 + add_post_meta( $chart_id, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() );
508 + add_post_meta( $chart_id, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
509 + add_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_LIBRARY, '' );
510 + add_post_meta(
511 + $chart_id,
512 + Visualizer_Plugin::CF_SETTINGS,
567 513 array(
568 - 'post_type' => Visualizer_Plugin::CPT_VISUALIZER,
569 - 'post_title' => 'Visualization',
570 - 'post_author' => get_current_user_id(),
571 - 'post_status' => 'auto-draft',
572 - 'post_content' => $source->getData( get_post_meta( $chart_id, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) ),
514 + 'focusTarget' => 'datum',
573 515 )
574 516 );
575 - if ( $chart_id && ! is_wp_error( $chart_id ) ) {
576 - add_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_TYPE, $default_type );
577 - add_post_meta( $chart_id, Visualizer_Plugin::CF_DEFAULT_DATA, 1 );
578 - add_post_meta( $chart_id, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() );
579 - add_post_meta( $chart_id, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
580 - add_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_LIBRARY, '' );
581 - add_post_meta(
582 - $chart_id,
583 - Visualizer_Plugin::CF_SETTINGS,
584 - array(
585 - 'focusTarget' => 'datum',
586 - )
587 - );
588 -
589 - do_action( 'visualizer_pro_new_chart_defaults', $chart_id );
590 - }
591 - } else {
592 - $parent_chart_id = filter_var( $_GET['parent_chart_id'], FILTER_VALIDATE_INT );
593 - $success = false;
594 - if ( $parent_chart_id ) {
595 - $parent_chart = get_post( $parent_chart_id );
596 - $success = $parent_chart && $parent_chart->post_type === Visualizer_Plugin::CPT_VISUALIZER;
597 - }
598 - if ( $success ) {
599 - $new_chart_id = wp_insert_post(
600 - array(
601 - 'post_type' => Visualizer_Plugin::CPT_VISUALIZER,
602 - 'post_title' => 'Visualization',
603 - 'post_author' => get_current_user_id(),
604 - 'post_status' => $parent_chart->post_status,
605 - 'post_content' => $parent_chart->post_content,
606 - )
607 - );
608 -
609 - if ( is_wp_error( $new_chart_id ) ) {
610 - do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( 'Error while cloning chart %d = %s', $parent_chart_id, print_r( $new_chart_id, true ) ), 'error', __FILE__, __LINE__ );
611 - } else {
612 - $post_meta = get_post_meta( $parent_chart_id );
613 - $chart_id = $new_chart_id;
614 - foreach ( $post_meta as $key => $value ) {
615 - if ( strpos( $key, 'visualizer-' ) !== false ) {
616 - add_post_meta( $new_chart_id, $key, maybe_unserialize( $value[0] ) );
617 - }
618 - }
619 - }
620 - }
621 517 do_action( 'visualizer_pro_new_chart_defaults', $chart_id );
622 518 }
623 - wp_redirect( esc_url_raw( add_query_arg( 'chart', (int) $chart_id ) ) );
624 -
625 - if ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) {
626 - wp_die();
627 - }
628 - exit();
519 + wp_redirect( add_query_arg( 'chart', (int) $chart_id ) );
520 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
629 521 }
630 522
631 - $_POST['save_chart_image'] = isset( $_POST['save_chart_image'] ) && 'yes' === $_POST['save_chart_image'] ? true : false;
632 - $_POST['lazy_load_chart'] = isset( $_POST['lazy_load_chart'] ) && 'yes' === $_POST['lazy_load_chart'] ? true : false;
633 -
634 - if ( isset( $_POST['chart-img'] ) && ! empty( $_POST['chart-img'] ) ) {
635 - $attachment_id = $this->save_chart_image( $_POST['chart-img'], $chart_id, $_POST['save_chart_image'] );
636 - if ( $attachment_id ) {
637 - update_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_IMAGE, $attachment_id );
638 - }
639 - }
640 523 $lib = $this->load_chart_type( $chart_id );
641 524
642 525 // the alpha color picker (RGBA) is not supported by google.
643 526 $color_picker_dep = 'wp-color-picker';
@@ -699,16 +582,8 @@
699 582 // if the edit button is clicked.
700 583 $this->_chart = $this->handleExistingRevisions( $chart_id, $this->_chart );
701 584 }
702 585
703 - // Clear existing chart cache.
704 - if ( isset( $_POST['save'] ) && 1 === intval( $_POST['save'] ) ) {
705 - $cache_key = Visualizer_Plugin::CF_CHART_CACHE . '_' . $chart_id;
706 - if ( get_transient( $cache_key ) ) {
707 - delete_transient( $cache_key );
708 - }
709 - }
710 -
711 586 switch ( $tab ) {
712 587 case 'settings':
713 588 $this->_handleDataAndSettingsPage();
714 589 break;
@@ -719,9 +594,9 @@
719 594 default:
720 595 // this should never happen.
721 596 break;
722 597 }
723 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
598 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
724 599 }
725 600
726 601 /**
727 602 * Load code editor assets.
@@ -733,9 +608,9 @@
733 608
734 609 // data tables assets.
735 610 wp_register_script( 'visualizer-datatables', VISUALIZER_ABSURL . 'js/lib/datatables.min.js', array( 'jquery-ui-core' ), Visualizer_Plugin::VERSION );
736 611 wp_register_style( 'visualizer-datatables', VISUALIZER_ABSURL . 'css/lib/datatables.min.css', array(), Visualizer_Plugin::VERSION );
737 - wp_register_style( 'visualizer-jquery-ui', sprintf( '//code.jquery.com/ui/%s/themes/smoothness/jquery-ui.css', $wp_scripts->registered['jquery-ui-core']->ver ), array( 'visualizer-datatables' ), Visualizer_Plugin::VERSION );
612 + wp_register_style( 'visualizer-jquery-ui', sprintf( '//ajax.googleapis.com/ajax/libs/jqueryui/%s/themes/smoothness/jquery-ui.css', $wp_scripts->registered['jquery-ui-core']->ver ), array( 'visualizer-datatables' ), Visualizer_Plugin::VERSION );
738 613 wp_enqueue_script( 'visualizer-datatables' );
739 614 wp_enqueue_style( 'visualizer-jquery-ui' );
740 615
741 616 if ( ! Visualizer_Module::is_pro() ) {
@@ -751,9 +626,9 @@
751 626 wp_register_script( 'visualizer-codemirror-matchbrackets', '//codemirror.net/addon/edit/matchbrackets.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
752 627 wp_register_script( 'visualizer-codemirror-closebrackets', '//codemirror.net/addon/edit/closebrackets.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
753 628 wp_register_script( 'visualizer-codemirror-sql', '//codemirror.net/mode/sql/sql.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
754 629 wp_register_script( 'visualizer-codemirror-sql-hint', '//codemirror.net/addon/hint/sql-hint.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
755 - wp_register_script( 'visualizer-codemirror-hint', '//codemirror.net/addon/hint/show-hint.js', array( 'visualizer-codemirror-sql', 'visualizer-codemirror-sql-hint', 'visualizer-codemirror-placeholder', 'visualizer-codemirror-matchbrackets', 'visualizer-codemirror-closebrackets' ), Visualizer_Plugin::VERSION );
630 + wp_register_script( 'visualizer-codemirror-hint', '//codemirror.net/addon/hint/show-hint.js', array( 'visualizer-codemirror-sql', 'visualizer-codemirror-sql-hint', 'visualizer-codemirror-placeholder', 'visualizer-codemirror-matchbrackets', 'visualizer-codemirror-closebrackets' ), Visualizer_Plugin::VERSION );
756 631 wp_register_style( 'visualizer-codemirror-core', '//codemirror.net/lib/codemirror.css', array(), Visualizer_Plugin::VERSION );
757 632 wp_register_style( 'visualizer-codemirror-hint', '//codemirror.net/addon/hint/show-hint.css', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
758 633
759 634 wp_enqueue_script( 'visualizer-codemirror-hint' );
@@ -767,9 +642,9 @@
767 642 'lineWrapping' => true,
768 643 'dragDrop' => false,
769 644 'matchBrackets' => true,
770 645 'autoCloseBrackets' => true,
771 - 'extraKeys' => array( 'Shift-Space' => 'autocomplete' ),
646 + 'extraKeys' => array( 'Ctrl-Space' => 'autocomplete' ),
772 647 'hintOptions' => array( 'tables' => $table_col_mapping ),
773 648 ),
774 649 )
775 650 );
@@ -803,28 +678,19 @@
803 678 update_option( 'visualizer-map-api-key', $_POST['map_api_key'] );
804 679 }
805 680
806 681 if ( $_SERVER['REQUEST_METHOD'] === 'POST' && isset( $_GET['nonce'] ) && wp_verify_nonce( $_GET['nonce'] ) ) {
807 - $is_canceled = isset( $_POST['cancel'] ) && 1 === intval( $_POST['cancel'] );
808 - $is_newly_created = $this->_chart->post_status === 'auto-draft';
809 -
810 - if ( $is_newly_created && ! $is_canceled ) {
682 + if ( $this->_chart->post_status === 'auto-draft' ) {
811 683 $this->_chart->post_status = 'publish';
812 684
813 685 // ensure that a revision is not created. If a revision is created it will have the proper data and the parent of the revision will have default data.
814 686 // we do not want any difference in data so disable revisions temporarily.
815 - $this->disableRevisionsTemporarily();
816 -
687 + add_filter( 'wp_revisions_to_keep', '__return_false' );
817 688 wp_update_post( $this->_chart->to_array() );
818 689 }
819 690 // save meta data only when it is NOT being canceled.
820 - if ( ! $is_canceled ) {
821 - $post_settings = $_POST;
822 - $existing = get_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SETTINGS, true );
823 - if ( isset( $existing['colors'] ) && is_array( $existing['colors'] ) && ! isset( $post_settings['colors'] ) ) {
824 - $post_settings['colors'] = $existing['colors'];
825 - }
826 - update_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SETTINGS, $post_settings );
691 + if ( ! ( isset( $_POST['cancel'] ) && 1 === intval( $_POST['cancel'] ) ) ) {
692 + update_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SETTINGS, $_POST );
827 693
828 694 // we will keep a parameter called 'internal_title' that will be set to the given title or, if empty, the chart ID
829 695 // this will help in searching with the chart id.
830 696 $settings = get_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SETTINGS, true );
@@ -838,14 +704,8 @@
838 704 if ( empty( $title ) ) {
839 705 $title = $this->_chart->ID;
840 706 }
841 707 $settings['internal_title'] = $title;
842 - $settings_label = isset( $settings['pieResidueSliceLabel'] ) ? $settings['pieResidueSliceLabel'] : '';
843 - if ( empty( $settings_label ) ) {
844 - $settings['pieResidueSliceLabel'] = esc_html__( 'Other', 'visualizer' );
845 - } else {
846 - $settings['pieResidueSliceLabel'] = $settings_label;
847 - }
848 708 update_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SETTINGS, $settings );
849 709 }
850 710 $render = new Visualizer_Render_Page_Send();
851 711 $render->text = sprintf( '[visualizer id="%d"]', $this->_chart->ID );
@@ -871,9 +731,8 @@
871 731 wp_enqueue_style( 'visualizer-frame' );
872 732 wp_enqueue_script( 'visualizer-preview' );
873 733 wp_enqueue_script( 'visualizer-chosen' );
874 734 wp_enqueue_script( 'visualizer-render' );
875 - wp_enqueue_code_editor( array( 'type' => 'application/json' ) );
876 735
877 736 if ( Visualizer_Module::can_show_feature( 'simple-editor' ) ) {
878 737 wp_enqueue_script( 'visualizer-editor-simple' );
879 738 wp_localize_script(
@@ -881,10 +740,12 @@
881 740 'visualizer1',
882 741 array(
883 742 'ajax' => array(
884 743 'url' => admin_url( 'admin-ajax.php' ),
885 - 'nonces' => array(),
886 - 'actions' => array(),
744 + 'nonces' => array(
745 + ),
746 + 'actions' => array(
747 + ),
887 748 ),
888 749 )
889 750 );
890 751 }
@@ -895,15 +756,13 @@
895 756 'visualizer-render',
896 757 'visualizer',
897 758 array(
898 759 'l10n' => array(
899 - 'invalid_source' => esc_html__( 'The URL you entered is invalid. Please enter a valid URL.', 'visualizer' ),
900 - 'loading' => esc_html__( 'Loading...', 'visualizer' ),
901 - 'json_error' => esc_html__( 'An error occured in fetching data.', 'visualizer' ),
902 - 'select_columns' => esc_html__( 'Please select a few columns to include in the chart.', 'visualizer' ),
903 - 'save_settings' => __( 'You have modified the chart\'s settings. To modify the source/data again, you must save this chart and reopen it for editing. If you continue without saving the chart, you may lose your changes.', 'visualizer' ),
904 - 'copied' => __( 'The data has been copied to your clipboard. Hit Ctrl-V/Cmd-V in your spreadsheet editor to paste the data.', 'visualizer' ),
905 - 'invalid_format' => esc_html__( 'This format pattern is not supported in the series settings field. Use the Manual Configuration option instead.', 'visualizer' ),
760 + 'invalid_source' => esc_html__( 'You have entered an invalid URL. Please provide a valid URL.', 'visualizer' ),
761 + 'loading' => esc_html__( 'Loading...', 'visualizer' ),
762 + 'json_error' => esc_html__( 'An error occured in fetching data.', 'visualizer' ),
763 + 'select_columns' => esc_html__( 'Please select a few columns to include in the chart.', 'visualizer' ),
764 + 'save_settings' => __( 'You have modified the chart\'s settings. To modify the source/data again, you must save this chart and reopen it for editing. If you continue without saving the chart, you may lose your changes.', 'visualizer' ),
906 765 ),
907 766 'charts' => array(
908 767 'canvas' => $data,
909 768 'id' => $this->_chart->ID,
@@ -934,9 +793,8 @@
934 793 'page_type' => 'chart',
935 794 'json_tag_separator' => Visualizer_Source_Json::TAG_SEPARATOR,
936 795 'json_tag_separator_view' => Visualizer_Source_Json::TAG_SEPARATOR_VIEW,
937 796 'is_front' => false,
938 - 'rest_base' => get_rest_url( null, 'wc/v3/reports/' ),
939 797 )
940 798 );
941 799
942 800 $render = new Visualizer_Render_Page_Data();
@@ -947,10 +805,11 @@
947 805 if ( filter_input( INPUT_GET, 'library', FILTER_VALIDATE_BOOLEAN ) ) {
948 806 $render->button = filter_input( INPUT_GET, 'action' ) === Visualizer_Plugin::ACTION_EDIT_CHART
949 807 ? esc_html__( 'Save Chart', 'visualizer' )
950 808 : esc_html__( 'Create Chart', 'visualizer' );
951 -
952 - $render->cancel_button = esc_html__( 'Cancel', 'visualizer' );
809 + if ( filter_input( INPUT_GET, 'action' ) === Visualizer_Plugin::ACTION_EDIT_CHART ) {
810 + $render->cancel_button = esc_html__( 'Cancel', 'visualizer' );
811 + }
953 812 } else {
954 813 $render->button = esc_attr__( 'Insert Chart', 'visualizer' );
955 814 }
956 815
@@ -973,12 +832,12 @@
973 832 * @access private
974 833 */
975 834 private function _handleTypesPage() {
976 835 // process post request
977 - if ( $_SERVER['REQUEST_METHOD'] === 'POST' && wp_verify_nonce( filter_input( INPUT_POST, 'nonce' ), 'visualizer-upload-data' ) ) {
836 + if ( $_SERVER['REQUEST_METHOD'] === 'POST' && wp_verify_nonce( filter_input( INPUT_POST, 'nonce' ) ) ) {
978 837 $type = filter_input( INPUT_POST, 'type' );
979 838 $library = filter_input( INPUT_POST, 'chart-library' );
980 - if ( Visualizer_Module_Admin::checkChartStatus( $type ) ) {
839 + if ( in_array( $type, Visualizer_Plugin::getChartTypes(), true ) ) {
981 840 if ( empty( $library ) ) {
982 841 // library cannot be empty.
983 842 do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, 'Chart library empty while creating the chart! Aborting...', 'error', __FILE__, __LINE__ );
984 843 return;
@@ -990,9 +849,9 @@
990 849 // if the chart has default data, update it with appropriate default data for new type
991 850 if ( filter_var( get_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_DEFAULT_DATA, true ), FILTER_VALIDATE_BOOLEAN ) ) {
992 851 $source = new Visualizer_Source_Csv( VISUALIZER_ABSPATH . DIRECTORY_SEPARATOR . 'samples' . DIRECTORY_SEPARATOR . $type . '.csv' );
993 852 $source->fetch();
994 - $this->_chart->post_content = $source->getData( get_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) );
853 + $this->_chart->post_content = $source->getData();
995 854 wp_update_post( $this->_chart->to_array() );
996 855 update_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
997 856 }
998 857
@@ -999,9 +858,9 @@
999 858 Visualizer_Module_Utility::set_defaults( $this->_chart );
1000 859
1001 860 // redirect to next tab
1002 861 // changed by Ash/Upwork
1003 - wp_redirect( esc_url_raw( add_query_arg( 'tab', 'settings' ) ) );
862 + wp_redirect( add_query_arg( 'tab', 'settings' ) );
1004 863
1005 864 return;
1006 865 }
1007 866 }
@@ -1030,80 +889,8 @@
1030 889 * Processes the CSV that is sent in the request as a string.
1031 890 *
1032 891 * @since 3.2.0
1033 892 */
1034 - /**
1035 - * Determines whether a remote URL serves an XLSX file.
1036 - *
1037 - * Used as a fallback when the URL path has no recognisable file extension
1038 - * (e.g. SharePoint, signed S3 URLs, or "download?id=…" endpoints).
1039 - *
1040 - * Uses wp_safe_remote_get() to block requests to private/loopback addresses,
1041 - * and streams the response to a temp file so no body data is held in memory
1042 - * regardless of whether the server honours the Range header.
1043 - *
1044 - * The check relies on the ZIP magic number (PK\x03\x04) that every XLSX
1045 - * file begins with, making it immune to misleading Content-Type headers
1046 - * such as application/octet-stream. Content-Type is used as a last-resort
1047 - * fallback only when the temp file is empty (e.g. a HEAD-only server).
1048 - *
1049 - * @access private
1050 - * @param string $url The remote URL to probe.
1051 - * @return bool TRUE if the file appears to be XLSX, FALSE otherwise.
1052 - */
1053 - private static function _url_is_xlsx( $url ) {
1054 - $tmpfile = wp_tempnam( 'visualizer_xlsx_probe' );
1055 - if ( ! $tmpfile ) {
1056 - return false;
1057 - }
1058 -
1059 - $response = wp_safe_remote_get(
1060 - $url,
1061 - array(
1062 - 'timeout' => 10,
1063 - 'user-agent' => 'WordPress/' . get_bloginfo( 'version' ),
1064 - 'headers' => array( 'Range' => 'bytes=0-3' ),
1065 - 'stream' => true,
1066 - 'filename' => $tmpfile,
1067 - )
1068 - );
1069 -
1070 - if ( is_wp_error( $response ) ) {
1071 - @unlink( $tmpfile ); // phpcs:ignore WordPress.PHP.NoSilencedErrors
1072 - return false;
1073 - }
1074 -
1075 - $magic = '';
1076 - // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fopen
1077 - $fh = @fopen( $tmpfile, 'rb' ); // phpcs:ignore WordPress.PHP.NoSilencedErrors
1078 - if ( $fh ) {
1079 - $magic = fread( $fh, 4 ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fread
1080 - fclose( $fh ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose
1081 - }
1082 - @unlink( $tmpfile ); // phpcs:ignore WordPress.PHP.NoSilencedErrors
1083 -
1084 - if ( strlen( $magic ) >= 4 ) {
1085 - // XLSX (and all ZIP-based Office formats) start with PK\x03\x04.
1086 - return $magic === "PK\x03\x04";
1087 - }
1088 -
1089 - // Last resort: server returned an empty body (e.g. ignored Range and
1090 - // returned only headers). Check Content-Type from the same response.
1091 - // application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
1092 - return false !== strpos(
1093 - wp_remote_retrieve_header( $response, 'content-type' ),
1094 - 'spreadsheetml'
1095 - );
1096 - }
1097 -
1098 - /**
1099 - * Parses a raw CSV string or editor payload and returns a source object.
1100 - *
1101 - * @access private
1102 - * @param string $data The raw CSV data string.
1103 - * @param string $editor_type The editor type ('text' or 'tabular').
1104 - * @return Visualizer_Source|null The populated source object, or null on failure.
1105 - */
1106 893 private function handleCSVasString( $data, $editor_type ) {
1107 894 $source = null;
1108 895
1109 896 switch ( $editor_type ) {
@@ -1116,16 +903,8 @@
1116 903 foreach ( $values as $row ) {
1117 904 if ( empty( $row ) ) {
1118 905 continue;
1119 906 }
1120 - $row = explode( ',', $row );
1121 - $row = array_map(
1122 - function ( $r ) {
1123 - return '' === $r ? ' ' : $r;
1124 - },
1125 - $row
1126 - );
1127 - $row = implode( ',', $row );
1128 907 // don't use fpucsv here because we need to just dump the data
1129 908 // minus the empty rows
1130 909 // because fputcsv needs to tokenize
1131 910 // we can standardize the CSV enclosure here and replace all ' with "
@@ -1169,9 +948,9 @@
1169 948 foreach ( $types as $type ) {
1170 949 if ( empty( $type ) ) {
1171 950 $exclude[] = $index;
1172 951 }
1173 - ++$index;
952 + $index++;
1174 953 }
1175 954
1176 955 // when N headers are being renamed, the number of headers increases by N
1177 956 // because of the way datatable duplicates header information
@@ -1231,13 +1010,9 @@
1231 1010 // otherwise, assume this is a normal web request.
1232 1011 $can_die = ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE );
1233 1012
1234 1013 // validate nonce
1235 - if (
1236 - ! isset( $_GET['nonce'] ) ||
1237 - ! wp_verify_nonce( $_GET['nonce'], 'visualizer-upload-data' ) ||
1238 - ! current_user_can( 'edit_posts' )
1239 - ) {
1014 + if ( ! isset( $_GET['nonce'] ) || ! wp_verify_nonce( $_GET['nonce'] ) ) {
1240 1015 if ( ! $can_die ) {
1241 1016 return;
1242 1017 }
1243 1018 status_header( 403 );
@@ -1246,15 +1021,9 @@
1246 1021
1247 1022 // check chart, if chart exists
1248 1023 // do not use filter_input as it does not work for phpunit test cases, use filter_var instead
1249 1024 $chart_id = isset( $_GET['chart'] ) ? filter_var( $_GET['chart'], FILTER_VALIDATE_INT ) : '';
1250 - $chart = $chart_id ? get_post( $chart_id ) : null;
1251 - if (
1252 - ! $chart_id ||
1253 - ! $chart ||
1254 - $chart->post_type !== Visualizer_Plugin::CPT_VISUALIZER ||
1255 - ! current_user_can( 'edit_post', $chart_id )
1256 - ) {
1025 + if ( ! $chart_id || ! ( $chart = get_post( $chart_id ) ) || $chart->post_type !== Visualizer_Plugin::CPT_VISUALIZER ) {
1257 1026 if ( ! $can_die ) {
1258 1027 return;
1259 1028 }
1260 1029 status_header( 400 );
@@ -1290,35 +1059,18 @@
1290 1059
1291 1060 // delete editor related data.
1292 1061 delete_post_meta( $chart_id, Visualizer_Plugin::CF_EDITOR );
1293 1062
1294 - // delete this so that a JSON import can be later edited manually without a problem.
1295 - delete_post_meta( $chart_id, Visualizer_Plugin::CF_EDITABLE_TABLE );
1296 -
1297 1063 $source = null;
1298 1064 $render = new Visualizer_Render_Page_Update();
1299 -
1300 - $remote_data = false;
1301 - if ( isset( $_POST['remote_data'] ) && function_exists( 'wp_http_validate_url' ) ) {
1302 - $remote_data = wp_http_validate_url( $_POST['remote_data'] );
1303 - }
1304 - if ( false !== $remote_data ) {
1305 - $remote_ext = strtolower( pathinfo( parse_url( $remote_data, PHP_URL_PATH ), PATHINFO_EXTENSION ) );
1306 - if ( 'xlsx' === $remote_ext || ( 'csv' !== $remote_ext && self::_url_is_xlsx( $remote_data ) ) ) {
1307 - $source = new Visualizer_Source_Xlsx_Remote( $remote_data );
1308 - } else {
1309 - $source = new Visualizer_Source_Csv_Remote( $remote_data );
1310 - }
1065 + if ( isset( $_POST['remote_data'] ) && filter_var( $_POST['remote_data'], FILTER_VALIDATE_URL ) ) {
1066 + $source = new Visualizer_Source_Csv_Remote( $_POST['remote_data'] );
1311 1067 if ( isset( $_POST['vz-import-time'] ) ) {
1312 - apply_filters( 'visualizer_pro_chart_schedule', $chart_id, $remote_data, $_POST['vz-import-time'] );
1068 + apply_filters( 'visualizer_pro_chart_schedule', $chart_id, $_POST['remote_data'], $_POST['vz-import-time'] );
1313 1069 }
1314 - } elseif ( isset( $_FILES['local_data'] ) && $_FILES['local_data']['error'] === 0 ) {
1315 - $local_ext = strtolower( pathinfo( isset( $_FILES['local_data']['name'] ) ? $_FILES['local_data']['name'] : '', PATHINFO_EXTENSION ) );
1316 - if ( 'xlsx' === $local_ext ) {
1317 - $source = new Visualizer_Source_Xlsx( $_FILES['local_data']['tmp_name'] );
1318 - } else {
1319 - $source = new Visualizer_Source_Csv( $_FILES['local_data']['tmp_name'] );
1320 - }
1070 + // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
1071 + } elseif ( isset( $_FILES['local_data'] ) && $_FILES['local_data']['error'] == 0 ) {
1072 + $source = new Visualizer_Source_Csv( $_FILES['local_data']['tmp_name'] );
1321 1073 } elseif ( isset( $_POST['chart_data'] ) && strlen( $_POST['chart_data'] ) > 0 ) {
1322 1074 $source = $this->handleCSVasString( $_POST['chart_data'], $_POST['editor-type'] );
1323 1075 update_post_meta( $chart_id, Visualizer_Plugin::CF_EDITOR, $_POST['editor-type'] );
1324 1076 } elseif ( isset( $_POST['table_data'] ) && 'yes' === $_POST['table_data'] ) {
@@ -1325,10 +1077,10 @@
1325 1077 $source = $this->handleTabularData();
1326 1078 update_post_meta( $chart_id, Visualizer_Plugin::CF_EDITOR, $_POST['editor-type'] );
1327 1079 } else {
1328 1080 do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( 'CSV file with chart data was not uploaded for chart %d.', $chart_id ), 'error', __FILE__, __LINE__ );
1329 - $render->message = esc_html__( 'No CSV file was received. Select a file and try uploading again.', 'visualizer' );
1330 - update_post_meta( $chart_id, Visualizer_Plugin::CF_ERROR, esc_html__( 'No CSV file was received. Select a file and try uploading again.', 'visualizer' ) );
1081 + $render->message = esc_html__( 'CSV file with chart data was not uploaded. Please try again.', 'visualizer' );
1082 + update_post_meta( $chart_id, Visualizer_Plugin::CF_ERROR, esc_html__( 'CSV file with chart data was not uploaded. Please try again.', 'visualizer' ) );
1331 1083 }
1332 1084
1333 1085 do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( 'Uploaded data for chart %d with source %s', $chart_id, print_r( $source, true ) ), 'debug', __FILE__, __LINE__ );
1334 1086
@@ -1333,9 +1085,9 @@
1333 1085 do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( 'Uploaded data for chart %d with source %s', $chart_id, print_r( $source, true ) ), 'debug', __FILE__, __LINE__ );
1334 1086
1335 1087 if ( $source ) {
1336 1088 if ( $source->fetch() ) {
1337 - $content = $source->getData( get_post_meta( $chart_id, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) );
1089 + $content = $source->getData();
1338 1090 $populate = true;
1339 1091 if ( is_string( $content ) && is_array( unserialize( $content ) ) ) {
1340 1092 $json = unserialize( $content );
1341 1093 // if source exists, so should data. if source exists but data is blank, do not populate the chart.
@@ -1349,9 +1101,8 @@
1349 1101 if ( $populate ) {
1350 1102 $chart->post_content = $content;
1351 1103 }
1352 1104 wp_update_post( $chart->to_array() );
1353 -
1354 1105 update_post_meta( $chart->ID, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
1355 1106 update_post_meta( $chart->ID, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() );
1356 1107 update_post_meta( $chart->ID, Visualizer_Plugin::CF_DEFAULT_DATA, 0 );
1357 1108
@@ -1359,26 +1110,17 @@
1359 1110
1360 1111 Visualizer_Module_Utility::set_defaults( $chart, null );
1361 1112
1362 1113 $settings = get_post_meta( $chart->ID, Visualizer_Plugin::CF_SETTINGS, true );
1363 - if ( isset( $settings['series'] ) && ! ( count( $settings['series'] ) - count( $source->getSeries() ) > 1 ) ) {
1364 - $diff_total_series = abs( count( $settings['series'] ) - count( $source->getSeries() ) );
1365 - if ( $diff_total_series ) {
1366 - foreach ( range( 1, $diff_total_series ) as $k => $diff_series ) {
1367 - $settings['series'][] = end( $settings['series'] );
1368 - }
1369 - update_post_meta( $chart->ID, Visualizer_Plugin::CF_SETTINGS, $settings );
1370 - }
1371 - }
1372 1114
1373 1115 $render->id = $chart->ID;
1374 - $render->data = json_encode( $source->getRawData( get_post_meta( $chart->ID, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) ) );
1116 + $render->data = json_encode( $source->getRawData() );
1375 1117 $render->series = json_encode( $source->getSeries() );
1376 1118 $render->settings = json_encode( $settings );
1377 1119 } else {
1378 1120 $error = $source->get_error();
1379 1121 if ( empty( $error ) ) {
1380 - $error = esc_html__( 'The CSV file couldn\'t be read. Check that it\'s properly formatted and try again.', 'visualizer' );
1122 + $error = esc_html__( 'CSV file is broken or invalid. Please try again.', 'visualizer' );
1381 1123 }
1382 1124 $render->message = $error;
1383 1125 do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( '%s for chart %d.', $error, $chart_id ), 'error', __FILE__, __LINE__ );
1384 1126 update_post_meta( $chart_id, Visualizer_Plugin::CF_ERROR, $error );
@@ -1389,9 +1131,9 @@
1389 1131 $render->render();
1390 1132 if ( ! $can_die ) {
1391 1133 return;
1392 1134 }
1393 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1135 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1394 1136 }
1395 1137
1396 1138 /**
1397 1139 * Clones the chart.
@@ -1430,26 +1172,23 @@
1430 1172 if ( strpos( $key, 'visualizer-' ) !== false ) {
1431 1173 add_post_meta( $new_chart_id, $key, maybe_unserialize( $value[0] ) );
1432 1174 }
1433 1175 }
1434 - $redirect = esc_url(
1435 - add_query_arg(
1436 - array(
1437 - 'page' => 'visualizer',
1438 - 'type' => filter_input( INPUT_GET, 'type' ),
1439 - 'vaction' => false,
1440 - ),
1441 - admin_url( 'admin.php' )
1176 + $redirect = add_query_arg(
1177 + array(
1178 + 'page' => 'visualizer',
1179 + 'type' => filter_input( INPUT_GET, 'type' ),
1180 + 'vaction' => false,
1442 1181 ),
1443 - null,
1444 - 'db'
1182 + admin_url( 'admin.php' )
1445 1183 );
1446 1184 }
1447 1185 }
1448 1186
1449 - if ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) {
1187 + if ( defined( 'WP_TESTS_DOMAIN' ) ) {
1450 1188 wp_die();
1451 1189 }
1190 +
1452 1191 wp_redirect( $redirect );
1453 1192 exit;
1454 1193 }
1455 1194
@@ -1480,9 +1219,9 @@
1480 1219 }
1481 1220 }
1482 1221 }
1483 1222
1484 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1223 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1485 1224 }
1486 1225
1487 1226 /**
1488 1227 * Handles chart data page.
@@ -1506,11 +1245,10 @@
1506 1245 'visualizer-render',
1507 1246 'visualizer',
1508 1247 array(
1509 1248 'l10n' => array(
1510 - 'invalid_source' => esc_html__( 'The URL you entered is invalid. Please enter a valid URL.', 'visualizer' ),
1511 - 'loading' => esc_html__( 'Loading...', 'visualizer' ),
1512 - 'invalid_format' => esc_html__( 'This format pattern is not supported in the series settings field. To display percentages, use the Manual Configuration option instead.', 'visualizer' ),
1249 + 'invalid_source' => esc_html__( 'You have entered an invalid URL. Please provide a valid URL.', 'visualizer' ),
1250 + 'loading' => esc_html__( 'Loading...', 'visualizer' ),
1513 1251 ),
1514 1252 'charts' => array(
1515 1253 'canvas' => $data,
1516 1254 ),
@@ -1536,24 +1274,12 @@
1536 1274 */
1537 1275 public function getQueryData() {
1538 1276 check_ajax_referer( Visualizer_Plugin::ACTION_FETCH_DB_DATA . Visualizer_Plugin::VERSION, 'security' );
1539 1277
1540 - if ( ! current_user_can( 'administrator' ) ) {
1541 - wp_send_json_error( array( 'msg' => __( 'Action not allowed for this user.', 'visualizer' ) ) );
1542 - }
1543 - if ( ! is_super_admin() ) {
1544 - wp_send_json_error( array( 'msg' => __( 'Action not allowed for this user.', 'visualizer' ) ) );
1545 - }
1546 -
1547 - if ( ! Visualizer_Module::is_pro() ) {
1548 - wp_send_json_error( array( 'msg' => __( 'Feature is not available.', 'visualizer' ) ) );
1549 - }
1550 -
1551 1278 $params = wp_parse_args( $_POST['params'] );
1552 1279 $chart_id = filter_var( $params['chart_id'], FILTER_VALIDATE_INT );
1553 - $query = trim( $params['query'], ';' );
1554 1280
1555 - $source = new Visualizer_Source_Query( stripslashes( $query ), $chart_id, $params );
1281 + $source = new Visualizer_Source_Query( stripslashes( $params['query'] ), $chart_id, $params );
1556 1282 $html = $source->fetch( true );
1557 1283 $error = $source->get_error();
1558 1284 if ( ! empty( $error ) ) {
1559 1285 wp_send_json_error( array( 'msg' => $error ) );
@@ -1568,19 +1294,8 @@
1568 1294 */
1569 1295 public function saveQuery() {
1570 1296 check_ajax_referer( Visualizer_Plugin::ACTION_SAVE_DB_QUERY . Visualizer_Plugin::VERSION, 'security' );
1571 1297
1572 - if ( ! current_user_can( 'administrator' ) ) {
1573 - wp_send_json_error( array( 'msg' => __( 'Action not allowed for this user.', 'visualizer' ) ) );
1574 - }
1575 - if ( ! is_super_admin() ) {
1576 - wp_send_json_error( array( 'msg' => __( 'Action not allowed for this user.', 'visualizer' ) ) );
1577 - }
1578 -
1579 - if ( ! Visualizer_Module::is_pro() ) {
1580 - wp_send_json_error( array( 'msg' => __( 'Feature is not available.', 'visualizer' ) ) );
1581 - }
1582 -
1583 1298 $chart_id = filter_input(
1584 1299 INPUT_GET,
1585 1300 'chart',
1586 1301 FILTER_VALIDATE_INT,
@@ -1593,9 +1308,9 @@
1593 1308
1594 1309 $hours = filter_input(
1595 1310 INPUT_POST,
1596 1311 'refresh',
1597 - FILTER_VALIDATE_FLOAT,
1312 + FILTER_VALIDATE_INT,
1598 1313 array(
1599 1314 'options' => array(
1600 1315 'min_range' => -1,
1601 1316 'max_range' => apply_filters( 'visualizer_is_business', false ) ? PHP_INT_MAX : -1,
@@ -1602,9 +1317,9 @@
1602 1317 ),
1603 1318 )
1604 1319 );
1605 1320
1606 - if ( ! is_numeric( $hours ) ) {
1321 + if ( ! is_int( $hours ) ) {
1607 1322 $hours = -1;
1608 1323 }
1609 1324
1610 1325 $render = new Visualizer_Render_Page_Update();
@@ -1609,14 +1324,13 @@
1609 1324
1610 1325 $render = new Visualizer_Render_Page_Update();
1611 1326 if ( $chart_id ) {
1612 1327 $params = wp_parse_args( $_POST['params'] );
1613 - $query = trim( $params['query'], ';' );
1614 - $source = new Visualizer_Source_Query( stripslashes( $query ), $chart_id, $params );
1328 + $source = new Visualizer_Source_Query( stripslashes( $params['query'] ), $chart_id, $params );
1615 1329 $source->fetch( false );
1616 1330 $error = $source->get_error();
1617 1331 if ( empty( $error ) ) {
1618 - update_post_meta( $chart_id, Visualizer_Plugin::CF_DB_QUERY, stripslashes( $query ) );
1332 + update_post_meta( $chart_id, Visualizer_Plugin::CF_DB_QUERY, stripslashes( $params['query'] ) );
1619 1333 update_post_meta( $chart_id, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() );
1620 1334 update_post_meta( $chart_id, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
1621 1335 update_post_meta( $chart_id, Visualizer_Plugin::CF_DB_SCHEDULE, $hours );
1622 1336 update_post_meta( $chart_id, Visualizer_Plugin::CF_DEFAULT_DATA, 0 );
@@ -1633,12 +1347,12 @@
1633 1347
1634 1348 wp_update_post(
1635 1349 array(
1636 1350 'ID' => $chart_id,
1637 - 'post_content' => $source->getData( get_post_meta( $chart_id, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) ),
1351 + 'post_content' => $source->getData(),
1638 1352 )
1639 1353 );
1640 - $render->data = json_encode( $source->getRawData( get_post_meta( $chart_id, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) ) );
1354 + $render->data = json_encode( $source->getRawData() );
1641 1355 $render->series = json_encode( $source->getSeries() );
1642 1356 $render->id = $chart_id;
1643 1357 } else {
1644 1358 $render->message = $error;
@@ -1645,9 +1359,9 @@
1645 1359 }
1646 1360 }
1647 1361 $render->render();
1648 1362 if ( ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE ) ) {
1649 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1363 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1650 1364 }
1651 1365 }
1652 1366
1653 1367
@@ -1672,9 +1386,9 @@
1672 1386
1673 1387 $hours = filter_input(
1674 1388 INPUT_POST,
1675 1389 'refresh',
1676 - FILTER_VALIDATE_FLOAT,
1390 + FILTER_VALIDATE_INT,
1677 1391 array(
1678 1392 'options' => array(
1679 1393 'min_range' => -1,
1680 1394 'max_range' => apply_filters( 'visualizer_is_business', false ) ? PHP_INT_MAX : -1,
@@ -1681,9 +1395,9 @@
1681 1395 ),
1682 1396 )
1683 1397 );
1684 1398
1685 - if ( ! is_numeric( $hours ) ) {
1399 + if ( ! $hours ) {
1686 1400 $hours = -1;
1687 1401 }
1688 1402
1689 1403 do_action( 'visualizer_save_filter', $chart_id, $hours );
@@ -1688,61 +1402,8 @@
1688 1402
1689 1403 do_action( 'visualizer_save_filter', $chart_id, $hours );
1690 1404
1691 1405 if ( ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE ) ) {
1692 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1406 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1693 1407 }
1694 - }
1695 -
1696 - /**
1697 - * Save chart image.
1698 - *
1699 - * @param string $base64_img Chart image.
1700 - * @param int $chart_id Chart ID.
1701 - * @param bool $save_attachment Save attachment.
1702 - * @return attachment ID
1703 - */
1704 - public function save_chart_image( $base64_img, $chart_id, $save_attachment = true ) {
1705 - // Delete old chart image.
1706 - $old_attachment_id = get_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_IMAGE, true );
1707 - if ( $old_attachment_id ) {
1708 - wp_delete_attachment( $old_attachment_id, true );
1709 - }
1710 -
1711 - if ( ! $save_attachment ) {
1712 - return 0;
1713 - }
1714 -
1715 - // Upload dir.
1716 - $upload_dir = wp_upload_dir();
1717 - $upload_path = str_replace( '/', DIRECTORY_SEPARATOR, $upload_dir['path'] ) . DIRECTORY_SEPARATOR;
1718 -
1719 - $img = str_replace( 'data:image/png;base64,', '', $base64_img );
1720 - $img = str_replace( ' ', '+', $img );
1721 - $decoded = base64_decode( $img );
1722 - $filename = 'visualization-' . $chart_id . '.png';
1723 - $file_type = 'image/png';
1724 - $hashed_filename = $filename;
1725 -
1726 - // Save the image in the uploads directory.
1727 - require_once ABSPATH . '/wp-admin/includes/file.php';
1728 - \WP_Filesystem();
1729 - global $wp_filesystem;
1730 - if ( ! is_a( $wp_filesystem, 'WP_Filesystem_Base' ) ) {
1731 - $creds = request_filesystem_credentials( site_url() );
1732 - wp_filesystem( $creds );
1733 - }
1734 - $upload_file = $wp_filesystem->put_contents( $upload_path . $hashed_filename, $decoded );
1735 -
1736 - // Insert new chart image.
1737 - $attachment = array(
1738 - 'post_mime_type' => $file_type,
1739 - 'post_title' => preg_replace( '/\.[^.]+$/', '', basename( $hashed_filename ) ),
1740 - 'post_content' => '',
1741 - 'post_status' => 'inherit',
1742 - 'guid' => $upload_dir['url'] . '/' . basename( $hashed_filename ),
1743 - );
1744 -
1745 - $attach_id = wp_insert_attachment( $attachment, $upload_dir['path'] . '/' . $hashed_filename );
1746 - return $attach_id;
1747 1408 }
1748 1409 }