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 -426 4.0.33.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
@@ -231,12 +214,11 @@
231 214
232 215 $chart = get_post( $chart_id );
233 216
234 217 $source = new Visualizer_Source_Json( $params );
235 - update_post_meta( $chart->ID, Visualizer_Plugin::CF_EDITABLE_TABLE, true );
236 218 $source->fetchFromEditableTable();
237 219
238 - $content = $source->getData( get_post_meta( $chart->ID, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) );
220 + $content = $source->getData();
239 221 $chart->post_content = $content;
240 222 wp_update_post( $chart->to_array() );
241 223 update_post_meta( $chart->ID, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
242 224 update_post_meta( $chart->ID, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() );
@@ -258,16 +240,8 @@
258 240 if ( ! empty( $params['paging'] ) ) {
259 241 add_post_meta( $chart->ID, Visualizer_Plugin::CF_JSON_PAGING, $params['paging'] );
260 242 }
261 243
262 - if ( Visualizer_Module::is_pro() ) {
263 - if ( ! empty( $params['vz_woo_source'] ) ) {
264 - update_post_meta( $chart->ID, Visualizer_Plugin::CF_JSON_WOOCOMMERCE_SOURCE, $params['vz_woo_source'] );
265 - } else {
266 - delete_post_meta( $chart->ID, Visualizer_Plugin::CF_JSON_WOOCOMMERCE_SOURCE );
267 - }
268 - }
269 -
270 244 $time = filter_input(
271 245 INPUT_POST,
272 246 'time',
273 247 FILTER_VALIDATE_INT,
@@ -291,13 +265,13 @@
291 265 delete_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_SCHEDULE );
292 266
293 267 $render = new Visualizer_Render_Page_Update();
294 268 $render->id = $chart->ID;
295 - $render->data = json_encode( $source->getRawData( get_post_meta( $chart_id, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) ) );
269 + $render->data = json_encode( $source->getRawData() );
296 270 $render->series = json_encode( $source->getSeries() );
297 271 $render->render();
298 272
299 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
273 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
300 274 }
301 275
302 276
303 277 /**
@@ -373,13 +347,13 @@
373 347 * @since 1.0.0
374 348 *
375 349 * @access private
376 350 *
377 - * @param WP_Post|null $chart The chart object.
351 + * @param WP_Post $chart The chart object.
378 352 *
379 353 * @return array The array of chart data.
380 354 */
381 - private function _getChartArray( $chart = null ) {
355 + private function _getChartArray( WP_Post $chart = null ) {
382 356 if ( is_null( $chart ) ) {
383 357 $chart = $this->_chart;
384 358 }
385 359 $type = get_post_meta( $chart->ID, Visualizer_Plugin::CF_CHART_TYPE, true );
@@ -401,13 +375,8 @@
401 375 }
402 376
403 377 $date_formats = Visualizer_Source::get_date_formats_if_exists( $series, $data );
404 378
405 - $code = '';
406 - if ( 'd3' === $library ) {
407 - $code = get_post_meta( $chart->ID, Visualizer_Module_AIBuilder::CF_D3_CODE, true );
408 - }
409 -
410 379 return array(
411 380 'type' => $type,
412 381 'series' => $series,
413 382 'settings' => $settings,
@@ -412,9 +381,8 @@
412 381 'series' => $series,
413 382 'settings' => $settings,
414 383 'data' => $data,
415 384 'library' => $library,
416 - 'code' => $code,
417 385 'css' => $css,
418 386 'date_formats' => $date_formats,
419 387 );
420 388 }
@@ -431,9 +399,9 @@
431 399 public static function _sendResponse( $results ) {
432 400 header( 'Content-type: application/json' );
433 401 nocache_headers();
434 402 echo json_encode( $results );
435 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
403 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
436 404 }
437 405
438 406 /**
439 407 * Deletes a chart from database.
@@ -465,22 +433,9 @@
465 433 $success = $chart && $chart->post_type === Visualizer_Plugin::CPT_VISUALIZER;
466 434 }
467 435 }
468 436 if ( $success ) {
469 - global $sitepress;
470 - if ( Visualizer_Module::is_pro() && ( function_exists( 'icl_get_languages' ) && $sitepress instanceof \SitePress ) ) {
471 - $trid = $sitepress->get_element_trid( $chart_id, 'post_' . Visualizer_Plugin::CPT_VISUALIZER );
472 - $translations = $sitepress->get_element_translations( $trid );
473 - if ( ! empty( $translations ) ) {
474 - foreach ( $translations as $translated_post ) {
475 - wp_delete_post( $translated_post->element_id, true );
476 - }
477 - } else {
478 - wp_delete_post( $chart_id, true );
479 - }
480 - } else {
481 - wp_delete_post( $chart_id, true );
482 - }
437 + wp_delete_post( $chart_id, true );
483 438 }
484 439 if ( $is_post ) {
485 440 self::_sendResponse(
486 441 array(
@@ -528,108 +483,44 @@
528 483 *
529 484 * @access public
530 485 */
531 486 public function renderChartPages() {
532 - if ( ! current_user_can( 'edit_posts' ) ) {
533 - wp_die( __( 'You do not have permission to access this page.', 'visualizer' ) );
534 - }
535 -
536 487 defined( 'IFRAME_REQUEST' ) || define( 'IFRAME_REQUEST', 1 );
537 - if ( ! defined( 'ET_BUILDER_PRODUCT_VERSION' ) && function_exists( 'et_get_theme_version' ) ) {
538 - define( 'ET_BUILDER_PRODUCT_VERSION', et_get_theme_version() );
539 - }
540 - // Set current screen for the render chart.
541 - set_current_screen( 'visualizer_render_chart' );
542 488 // check chart, if chart not exists, will create new one and redirects to the same page with proper chart id
543 489 $chart_id = isset( $_GET['chart'] ) ? filter_var( $_GET['chart'], FILTER_VALIDATE_INT ) : '';
544 - if ( ! empty( $_POST ) ) {
545 - $_POST = map_deep( $_POST, 'wp_strip_all_tags' );
546 - }
547 - $chart = $chart_id ? get_post( $chart_id ) : null;
548 - if ( ! $chart_id || ! $chart || $chart->post_type !== Visualizer_Plugin::CPT_VISUALIZER ) {
549 - if ( empty( $_GET['lang'] ) || empty( $_GET['parent_chart_id'] ) ) {
550 - $this->deleteOldCharts();
551 - $default_type = isset( $_GET['type'] ) && ! empty( $_GET['type'] ) ? $_GET['type'] : 'line';
552 - $chart_status = Visualizer_Module_Admin::checkChartStatus( $default_type );
553 - if ( ! $chart_status ) {
554 - $default_type = 'line';
555 - }
556 - $source = new Visualizer_Source_Csv( VISUALIZER_ABSPATH . DIRECTORY_SEPARATOR . 'samples' . DIRECTORY_SEPARATOR . $default_type . '.csv' );
557 - $source->fetch();
558 - $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,
559 513 array(
560 - 'post_type' => Visualizer_Plugin::CPT_VISUALIZER,
561 - 'post_title' => 'Visualization',
562 - 'post_author' => get_current_user_id(),
563 - 'post_status' => 'auto-draft',
564 - 'post_content' => $source->getData( get_post_meta( $chart_id, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) ),
514 + 'focusTarget' => 'datum',
565 515 )
566 516 );
567 - if ( $chart_id && ! is_wp_error( $chart_id ) ) {
568 - add_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_TYPE, $default_type );
569 - add_post_meta( $chart_id, Visualizer_Plugin::CF_DEFAULT_DATA, 1 );
570 - add_post_meta( $chart_id, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() );
571 - add_post_meta( $chart_id, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
572 - add_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_LIBRARY, '' );
573 - add_post_meta(
574 - $chart_id,
575 - Visualizer_Plugin::CF_SETTINGS,
576 - array(
577 - 'focusTarget' => 'datum',
578 - )
579 - );
580 -
581 - do_action( 'visualizer_pro_new_chart_defaults', $chart_id );
582 - }
583 - } else {
584 - $parent_chart_id = filter_var( $_GET['parent_chart_id'], FILTER_VALIDATE_INT );
585 - $success = false;
586 - if ( $parent_chart_id ) {
587 - $parent_chart = get_post( $parent_chart_id );
588 - $success = $parent_chart && $parent_chart->post_type === Visualizer_Plugin::CPT_VISUALIZER;
589 - }
590 - if ( $success ) {
591 - $new_chart_id = wp_insert_post(
592 - array(
593 - 'post_type' => Visualizer_Plugin::CPT_VISUALIZER,
594 - 'post_title' => 'Visualization',
595 - 'post_author' => get_current_user_id(),
596 - 'post_status' => $parent_chart->post_status,
597 - 'post_content' => $parent_chart->post_content,
598 - )
599 - );
600 -
601 - if ( is_wp_error( $new_chart_id ) ) {
602 - 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__ );
603 - } else {
604 - $post_meta = get_post_meta( $parent_chart_id );
605 - $chart_id = $new_chart_id;
606 - foreach ( $post_meta as $key => $value ) {
607 - if ( strpos( $key, 'visualizer-' ) !== false ) {
608 - add_post_meta( $new_chart_id, $key, maybe_unserialize( $value[0] ) );
609 - }
610 - }
611 - }
612 - }
613 517 do_action( 'visualizer_pro_new_chart_defaults', $chart_id );
614 518 }
615 - wp_redirect( esc_url_raw( add_query_arg( 'chart', (int) $chart_id ) ) );
616 -
617 - if ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) {
618 - wp_die();
619 - }
620 - exit();
519 + wp_redirect( add_query_arg( 'chart', (int) $chart_id ) );
520 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
621 521 }
622 522
623 - $_POST['save_chart_image'] = isset( $_POST['save_chart_image'] ) && 'yes' === $_POST['save_chart_image'] ? true : false;
624 - $_POST['lazy_load_chart'] = isset( $_POST['lazy_load_chart'] ) && 'yes' === $_POST['lazy_load_chart'] ? true : false;
625 -
626 - if ( isset( $_POST['chart-img'] ) && ! empty( $_POST['chart-img'] ) ) {
627 - $attachment_id = $this->save_chart_image( $_POST['chart-img'], $chart_id, $_POST['save_chart_image'] );
628 - if ( $attachment_id ) {
629 - update_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_IMAGE, $attachment_id );
630 - }
631 - }
632 523 $lib = $this->load_chart_type( $chart_id );
633 524
634 525 // the alpha color picker (RGBA) is not supported by google.
635 526 $color_picker_dep = 'wp-color-picker';
@@ -691,16 +582,8 @@
691 582 // if the edit button is clicked.
692 583 $this->_chart = $this->handleExistingRevisions( $chart_id, $this->_chart );
693 584 }
694 585
695 - // Clear existing chart cache.
696 - if ( isset( $_POST['save'] ) && 1 === intval( $_POST['save'] ) ) {
697 - $cache_key = Visualizer_Plugin::CF_CHART_CACHE . '_' . $chart_id;
698 - if ( get_transient( $cache_key ) ) {
699 - delete_transient( $cache_key );
700 - }
701 - }
702 -
703 586 switch ( $tab ) {
704 587 case 'settings':
705 588 $this->_handleDataAndSettingsPage();
706 589 break;
@@ -711,9 +594,9 @@
711 594 default:
712 595 // this should never happen.
713 596 break;
714 597 }
715 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
598 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
716 599 }
717 600
718 601 /**
719 602 * Load code editor assets.
@@ -725,9 +608,9 @@
725 608
726 609 // data tables assets.
727 610 wp_register_script( 'visualizer-datatables', VISUALIZER_ABSURL . 'js/lib/datatables.min.js', array( 'jquery-ui-core' ), Visualizer_Plugin::VERSION );
728 611 wp_register_style( 'visualizer-datatables', VISUALIZER_ABSURL . 'css/lib/datatables.min.css', array(), Visualizer_Plugin::VERSION );
729 - 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 );
730 613 wp_enqueue_script( 'visualizer-datatables' );
731 614 wp_enqueue_style( 'visualizer-jquery-ui' );
732 615
733 616 if ( ! Visualizer_Module::is_pro() ) {
@@ -743,9 +626,9 @@
743 626 wp_register_script( 'visualizer-codemirror-matchbrackets', '//codemirror.net/addon/edit/matchbrackets.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
744 627 wp_register_script( 'visualizer-codemirror-closebrackets', '//codemirror.net/addon/edit/closebrackets.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
745 628 wp_register_script( 'visualizer-codemirror-sql', '//codemirror.net/mode/sql/sql.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
746 629 wp_register_script( 'visualizer-codemirror-sql-hint', '//codemirror.net/addon/hint/sql-hint.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
747 - 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 );
748 631 wp_register_style( 'visualizer-codemirror-core', '//codemirror.net/lib/codemirror.css', array(), Visualizer_Plugin::VERSION );
749 632 wp_register_style( 'visualizer-codemirror-hint', '//codemirror.net/addon/hint/show-hint.css', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
750 633
751 634 wp_enqueue_script( 'visualizer-codemirror-hint' );
@@ -759,9 +642,9 @@
759 642 'lineWrapping' => true,
760 643 'dragDrop' => false,
761 644 'matchBrackets' => true,
762 645 'autoCloseBrackets' => true,
763 - 'extraKeys' => array( 'Shift-Space' => 'autocomplete' ),
646 + 'extraKeys' => array( 'Ctrl-Space' => 'autocomplete' ),
764 647 'hintOptions' => array( 'tables' => $table_col_mapping ),
765 648 ),
766 649 )
767 650 );
@@ -795,28 +678,19 @@
795 678 update_option( 'visualizer-map-api-key', $_POST['map_api_key'] );
796 679 }
797 680
798 681 if ( $_SERVER['REQUEST_METHOD'] === 'POST' && isset( $_GET['nonce'] ) && wp_verify_nonce( $_GET['nonce'] ) ) {
799 - $is_canceled = isset( $_POST['cancel'] ) && 1 === intval( $_POST['cancel'] );
800 - $is_newly_created = $this->_chart->post_status === 'auto-draft';
801 -
802 - if ( $is_newly_created && ! $is_canceled ) {
682 + if ( $this->_chart->post_status === 'auto-draft' ) {
803 683 $this->_chart->post_status = 'publish';
804 684
805 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.
806 686 // we do not want any difference in data so disable revisions temporarily.
807 - $this->disableRevisionsTemporarily();
808 -
687 + add_filter( 'wp_revisions_to_keep', '__return_false' );
809 688 wp_update_post( $this->_chart->to_array() );
810 689 }
811 690 // save meta data only when it is NOT being canceled.
812 - if ( ! $is_canceled ) {
813 - $post_settings = $_POST;
814 - $existing = get_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SETTINGS, true );
815 - if ( isset( $existing['colors'] ) && is_array( $existing['colors'] ) && ! isset( $post_settings['colors'] ) ) {
816 - $post_settings['colors'] = $existing['colors'];
817 - }
818 - 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 );
819 693
820 694 // we will keep a parameter called 'internal_title' that will be set to the given title or, if empty, the chart ID
821 695 // this will help in searching with the chart id.
822 696 $settings = get_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SETTINGS, true );
@@ -830,14 +704,8 @@
830 704 if ( empty( $title ) ) {
831 705 $title = $this->_chart->ID;
832 706 }
833 707 $settings['internal_title'] = $title;
834 - $settings_label = isset( $settings['pieResidueSliceLabel'] ) ? $settings['pieResidueSliceLabel'] : '';
835 - if ( empty( $settings_label ) ) {
836 - $settings['pieResidueSliceLabel'] = esc_html__( 'Other', 'visualizer' );
837 - } else {
838 - $settings['pieResidueSliceLabel'] = $settings_label;
839 - }
840 708 update_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SETTINGS, $settings );
841 709 }
842 710 $render = new Visualizer_Render_Page_Send();
843 711 $render->text = sprintf( '[visualizer id="%d"]', $this->_chart->ID );
@@ -863,9 +731,8 @@
863 731 wp_enqueue_style( 'visualizer-frame' );
864 732 wp_enqueue_script( 'visualizer-preview' );
865 733 wp_enqueue_script( 'visualizer-chosen' );
866 734 wp_enqueue_script( 'visualizer-render' );
867 - wp_enqueue_code_editor( array( 'type' => 'application/json' ) );
868 735
869 736 if ( Visualizer_Module::can_show_feature( 'simple-editor' ) ) {
870 737 wp_enqueue_script( 'visualizer-editor-simple' );
871 738 wp_localize_script(
@@ -873,10 +740,12 @@
873 740 'visualizer1',
874 741 array(
875 742 'ajax' => array(
876 743 'url' => admin_url( 'admin-ajax.php' ),
877 - 'nonces' => array(),
878 - 'actions' => array(),
744 + 'nonces' => array(
745 + ),
746 + 'actions' => array(
747 + ),
879 748 ),
880 749 )
881 750 );
882 751 }
@@ -887,15 +756,13 @@
887 756 'visualizer-render',
888 757 'visualizer',
889 758 array(
890 759 'l10n' => array(
891 - 'invalid_source' => esc_html__( 'The URL you entered is invalid. Please enter a valid URL.', 'visualizer' ),
892 - 'loading' => esc_html__( 'Loading...', 'visualizer' ),
893 - 'json_error' => esc_html__( 'An error occured in fetching data.', 'visualizer' ),
894 - 'select_columns' => esc_html__( 'Please select a few columns to include in the chart.', 'visualizer' ),
895 - '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' ),
896 - 'copied' => __( 'The data has been copied to your clipboard. Hit Ctrl-V/Cmd-V in your spreadsheet editor to paste the data.', 'visualizer' ),
897 - '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' ),
898 765 ),
899 766 'charts' => array(
900 767 'canvas' => $data,
901 768 'id' => $this->_chart->ID,
@@ -926,9 +793,8 @@
926 793 'page_type' => 'chart',
927 794 'json_tag_separator' => Visualizer_Source_Json::TAG_SEPARATOR,
928 795 'json_tag_separator_view' => Visualizer_Source_Json::TAG_SEPARATOR_VIEW,
929 796 'is_front' => false,
930 - 'rest_base' => get_rest_url( null, 'wc/v3/reports/' ),
931 797 )
932 798 );
933 799
934 800 $render = new Visualizer_Render_Page_Data();
@@ -939,10 +805,11 @@
939 805 if ( filter_input( INPUT_GET, 'library', FILTER_VALIDATE_BOOLEAN ) ) {
940 806 $render->button = filter_input( INPUT_GET, 'action' ) === Visualizer_Plugin::ACTION_EDIT_CHART
941 807 ? esc_html__( 'Save Chart', 'visualizer' )
942 808 : esc_html__( 'Create Chart', 'visualizer' );
943 -
944 - $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 + }
945 812 } else {
946 813 $render->button = esc_attr__( 'Insert Chart', 'visualizer' );
947 814 }
948 815
@@ -965,12 +832,12 @@
965 832 * @access private
966 833 */
967 834 private function _handleTypesPage() {
968 835 // process post request
969 - 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' ) ) ) {
970 837 $type = filter_input( INPUT_POST, 'type' );
971 838 $library = filter_input( INPUT_POST, 'chart-library' );
972 - if ( Visualizer_Module_Admin::checkChartStatus( $type ) ) {
839 + if ( in_array( $type, Visualizer_Plugin::getChartTypes(), true ) ) {
973 840 if ( empty( $library ) ) {
974 841 // library cannot be empty.
975 842 do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, 'Chart library empty while creating the chart! Aborting...', 'error', __FILE__, __LINE__ );
976 843 return;
@@ -982,9 +849,9 @@
982 849 // if the chart has default data, update it with appropriate default data for new type
983 850 if ( filter_var( get_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_DEFAULT_DATA, true ), FILTER_VALIDATE_BOOLEAN ) ) {
984 851 $source = new Visualizer_Source_Csv( VISUALIZER_ABSPATH . DIRECTORY_SEPARATOR . 'samples' . DIRECTORY_SEPARATOR . $type . '.csv' );
985 852 $source->fetch();
986 - $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();
987 854 wp_update_post( $this->_chart->to_array() );
988 855 update_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
989 856 }
990 857
@@ -991,9 +858,9 @@
991 858 Visualizer_Module_Utility::set_defaults( $this->_chart );
992 859
993 860 // redirect to next tab
994 861 // changed by Ash/Upwork
995 - wp_redirect( esc_url_raw( add_query_arg( 'tab', 'settings' ) ) );
862 + wp_redirect( add_query_arg( 'tab', 'settings' ) );
996 863
997 864 return;
998 865 }
999 866 }
@@ -1022,80 +889,8 @@
1022 889 * Processes the CSV that is sent in the request as a string.
1023 890 *
1024 891 * @since 3.2.0
1025 892 */
1026 - /**
1027 - * Determines whether a remote URL serves an XLSX file.
1028 - *
1029 - * Used as a fallback when the URL path has no recognisable file extension
1030 - * (e.g. SharePoint, signed S3 URLs, or "download?id=…" endpoints).
1031 - *
1032 - * Uses wp_safe_remote_get() to block requests to private/loopback addresses,
1033 - * and streams the response to a temp file so no body data is held in memory
1034 - * regardless of whether the server honours the Range header.
1035 - *
1036 - * The check relies on the ZIP magic number (PK\x03\x04) that every XLSX
1037 - * file begins with, making it immune to misleading Content-Type headers
1038 - * such as application/octet-stream. Content-Type is used as a last-resort
1039 - * fallback only when the temp file is empty (e.g. a HEAD-only server).
1040 - *
1041 - * @access private
1042 - * @param string $url The remote URL to probe.
1043 - * @return bool TRUE if the file appears to be XLSX, FALSE otherwise.
1044 - */
1045 - private static function _url_is_xlsx( $url ) {
1046 - $tmpfile = wp_tempnam( 'visualizer_xlsx_probe' );
1047 - if ( ! $tmpfile ) {
1048 - return false;
1049 - }
1050 -
1051 - $response = wp_safe_remote_get(
1052 - $url,
1053 - array(
1054 - 'timeout' => 10,
1055 - 'user-agent' => 'WordPress/' . get_bloginfo( 'version' ),
1056 - 'headers' => array( 'Range' => 'bytes=0-3' ),
1057 - 'stream' => true,
1058 - 'filename' => $tmpfile,
1059 - )
1060 - );
1061 -
1062 - if ( is_wp_error( $response ) ) {
1063 - @unlink( $tmpfile ); // phpcs:ignore WordPress.PHP.NoSilencedErrors
1064 - return false;
1065 - }
1066 -
1067 - $magic = '';
1068 - // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fopen
1069 - $fh = @fopen( $tmpfile, 'rb' ); // phpcs:ignore WordPress.PHP.NoSilencedErrors
1070 - if ( $fh ) {
1071 - $magic = fread( $fh, 4 ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fread
1072 - fclose( $fh ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose
1073 - }
1074 - @unlink( $tmpfile ); // phpcs:ignore WordPress.PHP.NoSilencedErrors
1075 -
1076 - if ( strlen( $magic ) >= 4 ) {
1077 - // XLSX (and all ZIP-based Office formats) start with PK\x03\x04.
1078 - return $magic === "PK\x03\x04";
1079 - }
1080 -
1081 - // Last resort: server returned an empty body (e.g. ignored Range and
1082 - // returned only headers). Check Content-Type from the same response.
1083 - // application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
1084 - return false !== strpos(
1085 - wp_remote_retrieve_header( $response, 'content-type' ),
1086 - 'spreadsheetml'
1087 - );
1088 - }
1089 -
1090 - /**
1091 - * Parses a raw CSV string or editor payload and returns a source object.
1092 - *
1093 - * @access private
1094 - * @param string $data The raw CSV data string.
1095 - * @param string $editor_type The editor type ('text' or 'tabular').
1096 - * @return Visualizer_Source|null The populated source object, or null on failure.
1097 - */
1098 893 private function handleCSVasString( $data, $editor_type ) {
1099 894 $source = null;
1100 895
1101 896 switch ( $editor_type ) {
@@ -1108,16 +903,8 @@
1108 903 foreach ( $values as $row ) {
1109 904 if ( empty( $row ) ) {
1110 905 continue;
1111 906 }
1112 - $row = explode( ',', $row );
1113 - $row = array_map(
1114 - function ( $r ) {
1115 - return '' === $r ? ' ' : $r;
1116 - },
1117 - $row
1118 - );
1119 - $row = implode( ',', $row );
1120 907 // don't use fpucsv here because we need to just dump the data
1121 908 // minus the empty rows
1122 909 // because fputcsv needs to tokenize
1123 910 // we can standardize the CSV enclosure here and replace all ' with "
@@ -1161,9 +948,9 @@
1161 948 foreach ( $types as $type ) {
1162 949 if ( empty( $type ) ) {
1163 950 $exclude[] = $index;
1164 951 }
1165 - ++$index;
952 + $index++;
1166 953 }
1167 954
1168 955 // when N headers are being renamed, the number of headers increases by N
1169 956 // because of the way datatable duplicates header information
@@ -1223,13 +1010,9 @@
1223 1010 // otherwise, assume this is a normal web request.
1224 1011 $can_die = ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE );
1225 1012
1226 1013 // validate nonce
1227 - if (
1228 - ! isset( $_GET['nonce'] ) ||
1229 - ! wp_verify_nonce( $_GET['nonce'], 'visualizer-upload-data' ) ||
1230 - ! current_user_can( 'edit_posts' )
1231 - ) {
1014 + if ( ! isset( $_GET['nonce'] ) || ! wp_verify_nonce( $_GET['nonce'] ) ) {
1232 1015 if ( ! $can_die ) {
1233 1016 return;
1234 1017 }
1235 1018 status_header( 403 );
@@ -1238,15 +1021,9 @@
1238 1021
1239 1022 // check chart, if chart exists
1240 1023 // do not use filter_input as it does not work for phpunit test cases, use filter_var instead
1241 1024 $chart_id = isset( $_GET['chart'] ) ? filter_var( $_GET['chart'], FILTER_VALIDATE_INT ) : '';
1242 - $chart = $chart_id ? get_post( $chart_id ) : null;
1243 - if (
1244 - ! $chart_id ||
1245 - ! $chart ||
1246 - $chart->post_type !== Visualizer_Plugin::CPT_VISUALIZER ||
1247 - ! current_user_can( 'edit_post', $chart_id )
1248 - ) {
1025 + if ( ! $chart_id || ! ( $chart = get_post( $chart_id ) ) || $chart->post_type !== Visualizer_Plugin::CPT_VISUALIZER ) {
1249 1026 if ( ! $can_die ) {
1250 1027 return;
1251 1028 }
1252 1029 status_header( 400 );
@@ -1282,35 +1059,18 @@
1282 1059
1283 1060 // delete editor related data.
1284 1061 delete_post_meta( $chart_id, Visualizer_Plugin::CF_EDITOR );
1285 1062
1286 - // delete this so that a JSON import can be later edited manually without a problem.
1287 - delete_post_meta( $chart_id, Visualizer_Plugin::CF_EDITABLE_TABLE );
1288 -
1289 1063 $source = null;
1290 1064 $render = new Visualizer_Render_Page_Update();
1291 -
1292 - $remote_data = false;
1293 - if ( isset( $_POST['remote_data'] ) && function_exists( 'wp_http_validate_url' ) ) {
1294 - $remote_data = wp_http_validate_url( $_POST['remote_data'] );
1295 - }
1296 - if ( false !== $remote_data ) {
1297 - $remote_ext = strtolower( pathinfo( parse_url( $remote_data, PHP_URL_PATH ), PATHINFO_EXTENSION ) );
1298 - if ( 'xlsx' === $remote_ext || ( 'csv' !== $remote_ext && self::_url_is_xlsx( $remote_data ) ) ) {
1299 - $source = new Visualizer_Source_Xlsx_Remote( $remote_data );
1300 - } else {
1301 - $source = new Visualizer_Source_Csv_Remote( $remote_data );
1302 - }
1065 + if ( isset( $_POST['remote_data'] ) && filter_var( $_POST['remote_data'], FILTER_VALIDATE_URL ) ) {
1066 + $source = new Visualizer_Source_Csv_Remote( $_POST['remote_data'] );
1303 1067 if ( isset( $_POST['vz-import-time'] ) ) {
1304 - 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'] );
1305 1069 }
1306 - } elseif ( isset( $_FILES['local_data'] ) && $_FILES['local_data']['error'] === 0 ) {
1307 - $local_ext = strtolower( pathinfo( isset( $_FILES['local_data']['name'] ) ? $_FILES['local_data']['name'] : '', PATHINFO_EXTENSION ) );
1308 - if ( 'xlsx' === $local_ext ) {
1309 - $source = new Visualizer_Source_Xlsx( $_FILES['local_data']['tmp_name'] );
1310 - } else {
1311 - $source = new Visualizer_Source_Csv( $_FILES['local_data']['tmp_name'] );
1312 - }
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'] );
1313 1073 } elseif ( isset( $_POST['chart_data'] ) && strlen( $_POST['chart_data'] ) > 0 ) {
1314 1074 $source = $this->handleCSVasString( $_POST['chart_data'], $_POST['editor-type'] );
1315 1075 update_post_meta( $chart_id, Visualizer_Plugin::CF_EDITOR, $_POST['editor-type'] );
1316 1076 } elseif ( isset( $_POST['table_data'] ) && 'yes' === $_POST['table_data'] ) {
@@ -1317,10 +1077,10 @@
1317 1077 $source = $this->handleTabularData();
1318 1078 update_post_meta( $chart_id, Visualizer_Plugin::CF_EDITOR, $_POST['editor-type'] );
1319 1079 } else {
1320 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__ );
1321 - $render->message = esc_html__( 'No CSV file was received. Select a file and try uploading again.', 'visualizer' );
1322 - 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' ) );
1323 1083 }
1324 1084
1325 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__ );
1326 1086
@@ -1325,9 +1085,9 @@
1325 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__ );
1326 1086
1327 1087 if ( $source ) {
1328 1088 if ( $source->fetch() ) {
1329 - $content = $source->getData( get_post_meta( $chart_id, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) );
1089 + $content = $source->getData();
1330 1090 $populate = true;
1331 1091 if ( is_string( $content ) && is_array( unserialize( $content ) ) ) {
1332 1092 $json = unserialize( $content );
1333 1093 // if source exists, so should data. if source exists but data is blank, do not populate the chart.
@@ -1341,9 +1101,8 @@
1341 1101 if ( $populate ) {
1342 1102 $chart->post_content = $content;
1343 1103 }
1344 1104 wp_update_post( $chart->to_array() );
1345 -
1346 1105 update_post_meta( $chart->ID, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
1347 1106 update_post_meta( $chart->ID, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() );
1348 1107 update_post_meta( $chart->ID, Visualizer_Plugin::CF_DEFAULT_DATA, 0 );
1349 1108
@@ -1351,26 +1110,17 @@
1351 1110
1352 1111 Visualizer_Module_Utility::set_defaults( $chart, null );
1353 1112
1354 1113 $settings = get_post_meta( $chart->ID, Visualizer_Plugin::CF_SETTINGS, true );
1355 - if ( isset( $settings['series'] ) && ! ( count( $settings['series'] ) - count( $source->getSeries() ) > 1 ) ) {
1356 - $diff_total_series = abs( count( $settings['series'] ) - count( $source->getSeries() ) );
1357 - if ( $diff_total_series ) {
1358 - foreach ( range( 1, $diff_total_series ) as $k => $diff_series ) {
1359 - $settings['series'][] = end( $settings['series'] );
1360 - }
1361 - update_post_meta( $chart->ID, Visualizer_Plugin::CF_SETTINGS, $settings );
1362 - }
1363 - }
1364 1114
1365 1115 $render->id = $chart->ID;
1366 - $render->data = json_encode( $source->getRawData( get_post_meta( $chart->ID, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) ) );
1116 + $render->data = json_encode( $source->getRawData() );
1367 1117 $render->series = json_encode( $source->getSeries() );
1368 1118 $render->settings = json_encode( $settings );
1369 1119 } else {
1370 1120 $error = $source->get_error();
1371 1121 if ( empty( $error ) ) {
1372 - $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' );
1373 1123 }
1374 1124 $render->message = $error;
1375 1125 do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( '%s for chart %d.', $error, $chart_id ), 'error', __FILE__, __LINE__ );
1376 1126 update_post_meta( $chart_id, Visualizer_Plugin::CF_ERROR, $error );
@@ -1381,9 +1131,9 @@
1381 1131 $render->render();
1382 1132 if ( ! $can_die ) {
1383 1133 return;
1384 1134 }
1385 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1135 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1386 1136 }
1387 1137
1388 1138 /**
1389 1139 * Clones the chart.
@@ -1422,26 +1172,23 @@
1422 1172 if ( strpos( $key, 'visualizer-' ) !== false ) {
1423 1173 add_post_meta( $new_chart_id, $key, maybe_unserialize( $value[0] ) );
1424 1174 }
1425 1175 }
1426 - $redirect = esc_url(
1427 - add_query_arg(
1428 - array(
1429 - 'page' => 'visualizer',
1430 - 'type' => filter_input( INPUT_GET, 'type' ),
1431 - 'vaction' => false,
1432 - ),
1433 - admin_url( 'admin.php' )
1176 + $redirect = add_query_arg(
1177 + array(
1178 + 'page' => 'visualizer',
1179 + 'type' => filter_input( INPUT_GET, 'type' ),
1180 + 'vaction' => false,
1434 1181 ),
1435 - null,
1436 - 'db'
1182 + admin_url( 'admin.php' )
1437 1183 );
1438 1184 }
1439 1185 }
1440 1186
1441 - if ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) {
1187 + if ( defined( 'WP_TESTS_DOMAIN' ) ) {
1442 1188 wp_die();
1443 1189 }
1190 +
1444 1191 wp_redirect( $redirect );
1445 1192 exit;
1446 1193 }
1447 1194
@@ -1472,9 +1219,9 @@
1472 1219 }
1473 1220 }
1474 1221 }
1475 1222
1476 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1223 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1477 1224 }
1478 1225
1479 1226 /**
1480 1227 * Handles chart data page.
@@ -1498,11 +1245,10 @@
1498 1245 'visualizer-render',
1499 1246 'visualizer',
1500 1247 array(
1501 1248 'l10n' => array(
1502 - 'invalid_source' => esc_html__( 'The URL you entered is invalid. Please enter a valid URL.', 'visualizer' ),
1503 - 'loading' => esc_html__( 'Loading...', 'visualizer' ),
1504 - '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' ),
1505 1251 ),
1506 1252 'charts' => array(
1507 1253 'canvas' => $data,
1508 1254 ),
@@ -1528,24 +1274,12 @@
1528 1274 */
1529 1275 public function getQueryData() {
1530 1276 check_ajax_referer( Visualizer_Plugin::ACTION_FETCH_DB_DATA . Visualizer_Plugin::VERSION, 'security' );
1531 1277
1532 - if ( ! current_user_can( 'administrator' ) ) {
1533 - wp_send_json_error( array( 'msg' => __( 'Action not allowed for this user.', 'visualizer' ) ) );
1534 - }
1535 - if ( ! is_super_admin() ) {
1536 - wp_send_json_error( array( 'msg' => __( 'Action not allowed for this user.', 'visualizer' ) ) );
1537 - }
1538 -
1539 - if ( ! Visualizer_Module::is_pro() ) {
1540 - wp_send_json_error( array( 'msg' => __( 'Feature is not available.', 'visualizer' ) ) );
1541 - }
1542 -
1543 1278 $params = wp_parse_args( $_POST['params'] );
1544 1279 $chart_id = filter_var( $params['chart_id'], FILTER_VALIDATE_INT );
1545 - $query = trim( $params['query'], ';' );
1546 1280
1547 - $source = new Visualizer_Source_Query( stripslashes( $query ), $chart_id, $params );
1281 + $source = new Visualizer_Source_Query( stripslashes( $params['query'] ), $chart_id, $params );
1548 1282 $html = $source->fetch( true );
1549 1283 $error = $source->get_error();
1550 1284 if ( ! empty( $error ) ) {
1551 1285 wp_send_json_error( array( 'msg' => $error ) );
@@ -1560,19 +1294,8 @@
1560 1294 */
1561 1295 public function saveQuery() {
1562 1296 check_ajax_referer( Visualizer_Plugin::ACTION_SAVE_DB_QUERY . Visualizer_Plugin::VERSION, 'security' );
1563 1297
1564 - if ( ! current_user_can( 'administrator' ) ) {
1565 - wp_send_json_error( array( 'msg' => __( 'Action not allowed for this user.', 'visualizer' ) ) );
1566 - }
1567 - if ( ! is_super_admin() ) {
1568 - wp_send_json_error( array( 'msg' => __( 'Action not allowed for this user.', 'visualizer' ) ) );
1569 - }
1570 -
1571 - if ( ! Visualizer_Module::is_pro() ) {
1572 - wp_send_json_error( array( 'msg' => __( 'Feature is not available.', 'visualizer' ) ) );
1573 - }
1574 -
1575 1298 $chart_id = filter_input(
1576 1299 INPUT_GET,
1577 1300 'chart',
1578 1301 FILTER_VALIDATE_INT,
@@ -1585,9 +1308,9 @@
1585 1308
1586 1309 $hours = filter_input(
1587 1310 INPUT_POST,
1588 1311 'refresh',
1589 - FILTER_VALIDATE_FLOAT,
1312 + FILTER_VALIDATE_INT,
1590 1313 array(
1591 1314 'options' => array(
1592 1315 'min_range' => -1,
1593 1316 'max_range' => apply_filters( 'visualizer_is_business', false ) ? PHP_INT_MAX : -1,
@@ -1594,9 +1317,9 @@
1594 1317 ),
1595 1318 )
1596 1319 );
1597 1320
1598 - if ( ! is_numeric( $hours ) ) {
1321 + if ( ! is_int( $hours ) ) {
1599 1322 $hours = -1;
1600 1323 }
1601 1324
1602 1325 $render = new Visualizer_Render_Page_Update();
@@ -1601,14 +1324,13 @@
1601 1324
1602 1325 $render = new Visualizer_Render_Page_Update();
1603 1326 if ( $chart_id ) {
1604 1327 $params = wp_parse_args( $_POST['params'] );
1605 - $query = trim( $params['query'], ';' );
1606 - $source = new Visualizer_Source_Query( stripslashes( $query ), $chart_id, $params );
1328 + $source = new Visualizer_Source_Query( stripslashes( $params['query'] ), $chart_id, $params );
1607 1329 $source->fetch( false );
1608 1330 $error = $source->get_error();
1609 1331 if ( empty( $error ) ) {
1610 - 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'] ) );
1611 1333 update_post_meta( $chart_id, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() );
1612 1334 update_post_meta( $chart_id, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
1613 1335 update_post_meta( $chart_id, Visualizer_Plugin::CF_DB_SCHEDULE, $hours );
1614 1336 update_post_meta( $chart_id, Visualizer_Plugin::CF_DEFAULT_DATA, 0 );
@@ -1625,12 +1347,12 @@
1625 1347
1626 1348 wp_update_post(
1627 1349 array(
1628 1350 'ID' => $chart_id,
1629 - 'post_content' => $source->getData( get_post_meta( $chart_id, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) ),
1351 + 'post_content' => $source->getData(),
1630 1352 )
1631 1353 );
1632 - $render->data = json_encode( $source->getRawData( get_post_meta( $chart_id, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) ) );
1354 + $render->data = json_encode( $source->getRawData() );
1633 1355 $render->series = json_encode( $source->getSeries() );
1634 1356 $render->id = $chart_id;
1635 1357 } else {
1636 1358 $render->message = $error;
@@ -1637,9 +1359,9 @@
1637 1359 }
1638 1360 }
1639 1361 $render->render();
1640 1362 if ( ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE ) ) {
1641 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1363 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1642 1364 }
1643 1365 }
1644 1366
1645 1367
@@ -1664,9 +1386,9 @@
1664 1386
1665 1387 $hours = filter_input(
1666 1388 INPUT_POST,
1667 1389 'refresh',
1668 - FILTER_VALIDATE_FLOAT,
1390 + FILTER_VALIDATE_INT,
1669 1391 array(
1670 1392 'options' => array(
1671 1393 'min_range' => -1,
1672 1394 'max_range' => apply_filters( 'visualizer_is_business', false ) ? PHP_INT_MAX : -1,
@@ -1673,9 +1395,9 @@
1673 1395 ),
1674 1396 )
1675 1397 );
1676 1398
1677 - if ( ! is_numeric( $hours ) ) {
1399 + if ( ! $hours ) {
1678 1400 $hours = -1;
1679 1401 }
1680 1402
1681 1403 do_action( 'visualizer_save_filter', $chart_id, $hours );
@@ -1680,61 +1402,8 @@
1680 1402
1681 1403 do_action( 'visualizer_save_filter', $chart_id, $hours );
1682 1404
1683 1405 if ( ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE ) ) {
1684 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1406 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1685 1407 }
1686 - }
1687 -
1688 - /**
1689 - * Save chart image.
1690 - *
1691 - * @param string $base64_img Chart image.
1692 - * @param int $chart_id Chart ID.
1693 - * @param bool $save_attachment Save attachment.
1694 - * @return attachment ID
1695 - */
1696 - public function save_chart_image( $base64_img, $chart_id, $save_attachment = true ) {
1697 - // Delete old chart image.
1698 - $old_attachment_id = get_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_IMAGE, true );
1699 - if ( $old_attachment_id ) {
1700 - wp_delete_attachment( $old_attachment_id, true );
1701 - }
1702 -
1703 - if ( ! $save_attachment ) {
1704 - return 0;
1705 - }
1706 -
1707 - // Upload dir.
1708 - $upload_dir = wp_upload_dir();
1709 - $upload_path = str_replace( '/', DIRECTORY_SEPARATOR, $upload_dir['path'] ) . DIRECTORY_SEPARATOR;
1710 -
1711 - $img = str_replace( 'data:image/png;base64,', '', $base64_img );
1712 - $img = str_replace( ' ', '+', $img );
1713 - $decoded = base64_decode( $img );
1714 - $filename = 'visualization-' . $chart_id . '.png';
1715 - $file_type = 'image/png';
1716 - $hashed_filename = $filename;
1717 -
1718 - // Save the image in the uploads directory.
1719 - require_once ABSPATH . '/wp-admin/includes/file.php';
1720 - \WP_Filesystem();
1721 - global $wp_filesystem;
1722 - if ( ! is_a( $wp_filesystem, 'WP_Filesystem_Base' ) ) {
1723 - $creds = request_filesystem_credentials( site_url() );
1724 - wp_filesystem( $creds );
1725 - }
1726 - $upload_file = $wp_filesystem->put_contents( $upload_path . $hashed_filename, $decoded );
1727 -
1728 - // Insert new chart image.
1729 - $attachment = array(
1730 - 'post_mime_type' => $file_type,
1731 - 'post_title' => preg_replace( '/\.[^.]+$/', '', basename( $hashed_filename ) ),
1732 - 'post_content' => '',
1733 - 'post_status' => 'inherit',
1734 - 'guid' => $upload_dir['url'] . '/' . basename( $hashed_filename ),
1735 - );
1736 -
1737 - $attach_id = wp_insert_attachment( $attachment, $upload_dir['path'] . '/' . $hashed_filename );
1738 - return $attach_id;
1739 1408 }
1740 1409 }