PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.5.0
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.5.0
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 +87 -419 4.0.53.5.0 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
@@ -266,16 +241,8 @@
266 241 if ( ! empty( $params['paging'] ) ) {
267 242 add_post_meta( $chart->ID, Visualizer_Plugin::CF_JSON_PAGING, $params['paging'] );
268 243 }
269 244
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 245 $time = filter_input(
279 246 INPUT_POST,
280 247 'time',
281 248 FILTER_VALIDATE_INT,
@@ -303,9 +270,9 @@
303 270 $render->data = json_encode( $source->getRawData( get_post_meta( $chart_id, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) ) );
304 271 $render->series = json_encode( $source->getSeries() );
305 272 $render->render();
306 273
307 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
274 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
308 275 }
309 276
310 277
311 278 /**
@@ -381,13 +348,13 @@
381 348 * @since 1.0.0
382 349 *
383 350 * @access private
384 351 *
385 - * @param WP_Post|null $chart The chart object.
352 + * @param WP_Post $chart The chart object.
386 353 *
387 354 * @return array The array of chart data.
388 355 */
389 - private function _getChartArray( $chart = null ) {
356 + private function _getChartArray( WP_Post $chart = null ) {
390 357 if ( is_null( $chart ) ) {
391 358 $chart = $this->_chart;
392 359 }
393 360 $type = get_post_meta( $chart->ID, Visualizer_Plugin::CF_CHART_TYPE, true );
@@ -409,13 +376,8 @@
409 376 }
410 377
411 378 $date_formats = Visualizer_Source::get_date_formats_if_exists( $series, $data );
412 379
413 - $code = '';
414 - if ( 'd3' === $library ) {
415 - $code = get_post_meta( $chart->ID, Visualizer_Module_AIBuilder::CF_D3_CODE, true );
416 - }
417 -
418 380 return array(
419 381 'type' => $type,
420 382 'series' => $series,
421 383 'settings' => $settings,
@@ -420,9 +382,8 @@
420 382 'series' => $series,
421 383 'settings' => $settings,
422 384 'data' => $data,
423 385 'library' => $library,
424 - 'code' => $code,
425 386 'css' => $css,
426 387 'date_formats' => $date_formats,
427 388 );
428 389 }
@@ -439,9 +400,9 @@
439 400 public static function _sendResponse( $results ) {
440 401 header( 'Content-type: application/json' );
441 402 nocache_headers();
442 403 echo json_encode( $results );
443 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
404 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
444 405 }
445 406
446 407 /**
447 408 * Deletes a chart from database.
@@ -473,22 +434,9 @@
473 434 $success = $chart && $chart->post_type === Visualizer_Plugin::CPT_VISUALIZER;
474 435 }
475 436 }
476 437 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 - }
438 + wp_delete_post( $chart_id, true );
491 439 }
492 440 if ( $is_post ) {
493 441 self::_sendResponse(
494 442 array(
@@ -536,108 +484,46 @@
536 484 *
537 485 * @access public
538 486 */
539 487 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 488 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 489 // Set current screen for the render chart.
549 490 set_current_screen( 'visualizer_render_chart' );
550 491 // check chart, if chart not exists, will create new one and redirects to the same page with proper chart id
551 492 $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(
493 + if ( ! $chart_id || ! ( $chart = get_post( $chart_id ) ) || $chart->post_type !== Visualizer_Plugin::CPT_VISUALIZER ) {
494 + $this->deleteOldCharts();
495 + $default_type = isset( $_GET['type'] ) && ! empty( $_GET['type'] ) ? $_GET['type'] : 'line';
496 + $source = new Visualizer_Source_Csv( VISUALIZER_ABSPATH . DIRECTORY_SEPARATOR . 'samples' . DIRECTORY_SEPARATOR . $default_type . '.csv' );
497 + $source->fetch();
498 + $chart_id = wp_insert_post(
499 + array(
500 + 'post_type' => Visualizer_Plugin::CPT_VISUALIZER,
501 + 'post_title' => 'Visualization',
502 + 'post_author' => get_current_user_id(),
503 + 'post_status' => 'auto-draft',
504 + 'post_content' => $source->getData( get_post_meta( $chart_id, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) ),
505 + )
506 + );
507 + if ( $chart_id && ! is_wp_error( $chart_id ) ) {
508 + add_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_TYPE, $default_type );
509 + add_post_meta( $chart_id, Visualizer_Plugin::CF_DEFAULT_DATA, 1 );
510 + add_post_meta( $chart_id, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() );
511 + add_post_meta( $chart_id, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
512 + add_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_LIBRARY, '' );
513 + add_post_meta(
514 + $chart_id,
515 + Visualizer_Plugin::CF_SETTINGS,
567 516 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 ) ),
517 + 'focusTarget' => 'datum',
573 518 )
574 519 );
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 520 do_action( 'visualizer_pro_new_chart_defaults', $chart_id );
622 521 }
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();
522 + wp_redirect( add_query_arg( 'chart', (int) $chart_id ) );
523 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
629 524 }
630 525
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 526 $lib = $this->load_chart_type( $chart_id );
641 527
642 528 // the alpha color picker (RGBA) is not supported by google.
643 529 $color_picker_dep = 'wp-color-picker';
@@ -699,16 +585,8 @@
699 585 // if the edit button is clicked.
700 586 $this->_chart = $this->handleExistingRevisions( $chart_id, $this->_chart );
701 587 }
702 588
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 589 switch ( $tab ) {
712 590 case 'settings':
713 591 $this->_handleDataAndSettingsPage();
714 592 break;
@@ -719,9 +597,9 @@
719 597 default:
720 598 // this should never happen.
721 599 break;
722 600 }
723 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
601 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
724 602 }
725 603
726 604 /**
727 605 * Load code editor assets.
@@ -733,9 +611,9 @@
733 611
734 612 // data tables assets.
735 613 wp_register_script( 'visualizer-datatables', VISUALIZER_ABSURL . 'js/lib/datatables.min.js', array( 'jquery-ui-core' ), Visualizer_Plugin::VERSION );
736 614 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 );
615 + 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 616 wp_enqueue_script( 'visualizer-datatables' );
739 617 wp_enqueue_style( 'visualizer-jquery-ui' );
740 618
741 619 if ( ! Visualizer_Module::is_pro() ) {
@@ -751,9 +629,9 @@
751 629 wp_register_script( 'visualizer-codemirror-matchbrackets', '//codemirror.net/addon/edit/matchbrackets.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
752 630 wp_register_script( 'visualizer-codemirror-closebrackets', '//codemirror.net/addon/edit/closebrackets.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
753 631 wp_register_script( 'visualizer-codemirror-sql', '//codemirror.net/mode/sql/sql.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
754 632 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 );
633 + 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 634 wp_register_style( 'visualizer-codemirror-core', '//codemirror.net/lib/codemirror.css', array(), Visualizer_Plugin::VERSION );
757 635 wp_register_style( 'visualizer-codemirror-hint', '//codemirror.net/addon/hint/show-hint.css', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
758 636
759 637 wp_enqueue_script( 'visualizer-codemirror-hint' );
@@ -767,9 +645,9 @@
767 645 'lineWrapping' => true,
768 646 'dragDrop' => false,
769 647 'matchBrackets' => true,
770 648 'autoCloseBrackets' => true,
771 - 'extraKeys' => array( 'Shift-Space' => 'autocomplete' ),
649 + 'extraKeys' => array( 'Ctrl-Space' => 'autocomplete' ),
772 650 'hintOptions' => array( 'tables' => $table_col_mapping ),
773 651 ),
774 652 )
775 653 );
@@ -803,12 +681,9 @@
803 681 update_option( 'visualizer-map-api-key', $_POST['map_api_key'] );
804 682 }
805 683
806 684 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 ) {
685 + if ( $this->_chart->post_status === 'auto-draft' ) {
811 686 $this->_chart->post_status = 'publish';
812 687
813 688 // 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 689 // we do not want any difference in data so disable revisions temporarily.
@@ -816,15 +691,10 @@
816 691
817 692 wp_update_post( $this->_chart->to_array() );
818 693 }
819 694 // 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 );
695 + if ( ! ( isset( $_POST['cancel'] ) && 1 === intval( $_POST['cancel'] ) ) ) {
696 + update_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SETTINGS, $_POST );
827 697
828 698 // we will keep a parameter called 'internal_title' that will be set to the given title or, if empty, the chart ID
829 699 // this will help in searching with the chart id.
830 700 $settings = get_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SETTINGS, true );
@@ -838,14 +708,8 @@
838 708 if ( empty( $title ) ) {
839 709 $title = $this->_chart->ID;
840 710 }
841 711 $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 712 update_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SETTINGS, $settings );
849 713 }
850 714 $render = new Visualizer_Render_Page_Send();
851 715 $render->text = sprintf( '[visualizer id="%d"]', $this->_chart->ID );
@@ -871,9 +735,8 @@
871 735 wp_enqueue_style( 'visualizer-frame' );
872 736 wp_enqueue_script( 'visualizer-preview' );
873 737 wp_enqueue_script( 'visualizer-chosen' );
874 738 wp_enqueue_script( 'visualizer-render' );
875 - wp_enqueue_code_editor( array( 'type' => 'application/json' ) );
876 739
877 740 if ( Visualizer_Module::can_show_feature( 'simple-editor' ) ) {
878 741 wp_enqueue_script( 'visualizer-editor-simple' );
879 742 wp_localize_script(
@@ -881,10 +744,12 @@
881 744 'visualizer1',
882 745 array(
883 746 'ajax' => array(
884 747 'url' => admin_url( 'admin-ajax.php' ),
885 - 'nonces' => array(),
886 - 'actions' => array(),
748 + 'nonces' => array(
749 + ),
750 + 'actions' => array(
751 + ),
887 752 ),
888 753 )
889 754 );
890 755 }
@@ -895,15 +760,13 @@
895 760 'visualizer-render',
896 761 'visualizer',
897 762 array(
898 763 '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' ),
764 + 'invalid_source' => esc_html__( 'You have entered an invalid URL. Please provide a valid URL.', 'visualizer' ),
765 + 'loading' => esc_html__( 'Loading...', 'visualizer' ),
766 + 'json_error' => esc_html__( 'An error occured in fetching data.', 'visualizer' ),
767 + 'select_columns' => esc_html__( 'Please select a few columns to include in the chart.', 'visualizer' ),
768 + '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 769 ),
907 770 'charts' => array(
908 771 'canvas' => $data,
909 772 'id' => $this->_chart->ID,
@@ -934,9 +797,8 @@
934 797 'page_type' => 'chart',
935 798 'json_tag_separator' => Visualizer_Source_Json::TAG_SEPARATOR,
936 799 'json_tag_separator_view' => Visualizer_Source_Json::TAG_SEPARATOR_VIEW,
937 800 'is_front' => false,
938 - 'rest_base' => get_rest_url( null, 'wc/v3/reports/' ),
939 801 )
940 802 );
941 803
942 804 $render = new Visualizer_Render_Page_Data();
@@ -947,10 +809,11 @@
947 809 if ( filter_input( INPUT_GET, 'library', FILTER_VALIDATE_BOOLEAN ) ) {
948 810 $render->button = filter_input( INPUT_GET, 'action' ) === Visualizer_Plugin::ACTION_EDIT_CHART
949 811 ? esc_html__( 'Save Chart', 'visualizer' )
950 812 : esc_html__( 'Create Chart', 'visualizer' );
951 -
952 - $render->cancel_button = esc_html__( 'Cancel', 'visualizer' );
813 + if ( filter_input( INPUT_GET, 'action' ) === Visualizer_Plugin::ACTION_EDIT_CHART ) {
814 + $render->cancel_button = esc_html__( 'Cancel', 'visualizer' );
815 + }
953 816 } else {
954 817 $render->button = esc_attr__( 'Insert Chart', 'visualizer' );
955 818 }
956 819
@@ -973,12 +836,12 @@
973 836 * @access private
974 837 */
975 838 private function _handleTypesPage() {
976 839 // process post request
977 - if ( $_SERVER['REQUEST_METHOD'] === 'POST' && wp_verify_nonce( filter_input( INPUT_POST, 'nonce' ), 'visualizer-upload-data' ) ) {
840 + if ( $_SERVER['REQUEST_METHOD'] === 'POST' && wp_verify_nonce( filter_input( INPUT_POST, 'nonce' ) ) ) {
978 841 $type = filter_input( INPUT_POST, 'type' );
979 842 $library = filter_input( INPUT_POST, 'chart-library' );
980 - if ( Visualizer_Module_Admin::checkChartStatus( $type ) ) {
843 + if ( in_array( $type, Visualizer_Plugin::getChartTypes(), true ) ) {
981 844 if ( empty( $library ) ) {
982 845 // library cannot be empty.
983 846 do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, 'Chart library empty while creating the chart! Aborting...', 'error', __FILE__, __LINE__ );
984 847 return;
@@ -999,9 +862,9 @@
999 862 Visualizer_Module_Utility::set_defaults( $this->_chart );
1000 863
1001 864 // redirect to next tab
1002 865 // changed by Ash/Upwork
1003 - wp_redirect( esc_url_raw( add_query_arg( 'tab', 'settings' ) ) );
866 + wp_redirect( add_query_arg( 'tab', 'settings' ) );
1004 867
1005 868 return;
1006 869 }
1007 870 }
@@ -1030,80 +893,8 @@
1030 893 * Processes the CSV that is sent in the request as a string.
1031 894 *
1032 895 * @since 3.2.0
1033 896 */
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 897 private function handleCSVasString( $data, $editor_type ) {
1107 898 $source = null;
1108 899
1109 900 switch ( $editor_type ) {
@@ -1116,16 +907,8 @@
1116 907 foreach ( $values as $row ) {
1117 908 if ( empty( $row ) ) {
1118 909 continue;
1119 910 }
1120 - $row = explode( ',', $row );
1121 - $row = array_map(
1122 - function ( $r ) {
1123 - return '' === $r ? ' ' : $r;
1124 - },
1125 - $row
1126 - );
1127 - $row = implode( ',', $row );
1128 911 // don't use fpucsv here because we need to just dump the data
1129 912 // minus the empty rows
1130 913 // because fputcsv needs to tokenize
1131 914 // we can standardize the CSV enclosure here and replace all ' with "
@@ -1169,9 +952,9 @@
1169 952 foreach ( $types as $type ) {
1170 953 if ( empty( $type ) ) {
1171 954 $exclude[] = $index;
1172 955 }
1173 - ++$index;
956 + $index++;
1174 957 }
1175 958
1176 959 // when N headers are being renamed, the number of headers increases by N
1177 960 // because of the way datatable duplicates header information
@@ -1231,13 +1014,9 @@
1231 1014 // otherwise, assume this is a normal web request.
1232 1015 $can_die = ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE );
1233 1016
1234 1017 // validate nonce
1235 - if (
1236 - ! isset( $_GET['nonce'] ) ||
1237 - ! wp_verify_nonce( $_GET['nonce'], 'visualizer-upload-data' ) ||
1238 - ! current_user_can( 'edit_posts' )
1239 - ) {
1018 + if ( ! isset( $_GET['nonce'] ) || ! wp_verify_nonce( $_GET['nonce'] ) ) {
1240 1019 if ( ! $can_die ) {
1241 1020 return;
1242 1021 }
1243 1022 status_header( 403 );
@@ -1246,15 +1025,9 @@
1246 1025
1247 1026 // check chart, if chart exists
1248 1027 // do not use filter_input as it does not work for phpunit test cases, use filter_var instead
1249 1028 $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 - ) {
1029 + if ( ! $chart_id || ! ( $chart = get_post( $chart_id ) ) || $chart->post_type !== Visualizer_Plugin::CPT_VISUALIZER ) {
1257 1030 if ( ! $can_die ) {
1258 1031 return;
1259 1032 }
1260 1033 status_header( 400 );
@@ -1295,30 +1068,16 @@
1295 1068 delete_post_meta( $chart_id, Visualizer_Plugin::CF_EDITABLE_TABLE );
1296 1069
1297 1070 $source = null;
1298 1071 $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 - }
1072 + if ( isset( $_POST['remote_data'] ) && filter_var( $_POST['remote_data'], FILTER_VALIDATE_URL ) ) {
1073 + $source = new Visualizer_Source_Csv_Remote( $_POST['remote_data'] );
1311 1074 if ( isset( $_POST['vz-import-time'] ) ) {
1312 - apply_filters( 'visualizer_pro_chart_schedule', $chart_id, $remote_data, $_POST['vz-import-time'] );
1075 + apply_filters( 'visualizer_pro_chart_schedule', $chart_id, $_POST['remote_data'], $_POST['vz-import-time'] );
1313 1076 }
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 - }
1077 + // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
1078 + } elseif ( isset( $_FILES['local_data'] ) && $_FILES['local_data']['error'] == 0 ) {
1079 + $source = new Visualizer_Source_Csv( $_FILES['local_data']['tmp_name'] );
1321 1080 } elseif ( isset( $_POST['chart_data'] ) && strlen( $_POST['chart_data'] ) > 0 ) {
1322 1081 $source = $this->handleCSVasString( $_POST['chart_data'], $_POST['editor-type'] );
1323 1082 update_post_meta( $chart_id, Visualizer_Plugin::CF_EDITOR, $_POST['editor-type'] );
1324 1083 } elseif ( isset( $_POST['table_data'] ) && 'yes' === $_POST['table_data'] ) {
@@ -1325,10 +1084,10 @@
1325 1084 $source = $this->handleTabularData();
1326 1085 update_post_meta( $chart_id, Visualizer_Plugin::CF_EDITOR, $_POST['editor-type'] );
1327 1086 } else {
1328 1087 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' ) );
1088 + $render->message = esc_html__( 'CSV file with chart data was not uploaded. Please try again.', 'visualizer' );
1089 + update_post_meta( $chart_id, Visualizer_Plugin::CF_ERROR, esc_html__( 'CSV file with chart data was not uploaded. Please try again.', 'visualizer' ) );
1331 1090 }
1332 1091
1333 1092 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 1093
@@ -1349,9 +1108,8 @@
1349 1108 if ( $populate ) {
1350 1109 $chart->post_content = $content;
1351 1110 }
1352 1111 wp_update_post( $chart->to_array() );
1353 -
1354 1112 update_post_meta( $chart->ID, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
1355 1113 update_post_meta( $chart->ID, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() );
1356 1114 update_post_meta( $chart->ID, Visualizer_Plugin::CF_DEFAULT_DATA, 0 );
1357 1115
@@ -1359,17 +1117,8 @@
1359 1117
1360 1118 Visualizer_Module_Utility::set_defaults( $chart, null );
1361 1119
1362 1120 $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 1121
1373 1122 $render->id = $chart->ID;
1374 1123 $render->data = json_encode( $source->getRawData( get_post_meta( $chart->ID, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) ) );
1375 1124 $render->series = json_encode( $source->getSeries() );
@@ -1376,9 +1125,9 @@
1376 1125 $render->settings = json_encode( $settings );
1377 1126 } else {
1378 1127 $error = $source->get_error();
1379 1128 if ( empty( $error ) ) {
1380 - $error = esc_html__( 'The CSV file couldn\'t be read. Check that it\'s properly formatted and try again.', 'visualizer' );
1129 + $error = esc_html__( 'CSV file is broken or invalid. Please try again.', 'visualizer' );
1381 1130 }
1382 1131 $render->message = $error;
1383 1132 do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( '%s for chart %d.', $error, $chart_id ), 'error', __FILE__, __LINE__ );
1384 1133 update_post_meta( $chart_id, Visualizer_Plugin::CF_ERROR, $error );
@@ -1389,9 +1138,9 @@
1389 1138 $render->render();
1390 1139 if ( ! $can_die ) {
1391 1140 return;
1392 1141 }
1393 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1142 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1394 1143 }
1395 1144
1396 1145 /**
1397 1146 * Clones the chart.
@@ -1430,26 +1179,23 @@
1430 1179 if ( strpos( $key, 'visualizer-' ) !== false ) {
1431 1180 add_post_meta( $new_chart_id, $key, maybe_unserialize( $value[0] ) );
1432 1181 }
1433 1182 }
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' )
1183 + $redirect = add_query_arg(
1184 + array(
1185 + 'page' => 'visualizer',
1186 + 'type' => filter_input( INPUT_GET, 'type' ),
1187 + 'vaction' => false,
1442 1188 ),
1443 - null,
1444 - 'db'
1189 + admin_url( 'admin.php' )
1445 1190 );
1446 1191 }
1447 1192 }
1448 1193
1449 - if ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) {
1194 + if ( defined( 'WP_TESTS_DOMAIN' ) ) {
1450 1195 wp_die();
1451 1196 }
1197 +
1452 1198 wp_redirect( $redirect );
1453 1199 exit;
1454 1200 }
1455 1201
@@ -1480,9 +1226,9 @@
1480 1226 }
1481 1227 }
1482 1228 }
1483 1229
1484 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1230 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1485 1231 }
1486 1232
1487 1233 /**
1488 1234 * Handles chart data page.
@@ -1506,11 +1252,10 @@
1506 1252 'visualizer-render',
1507 1253 'visualizer',
1508 1254 array(
1509 1255 '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' ),
1256 + 'invalid_source' => esc_html__( 'You have entered an invalid URL. Please provide a valid URL.', 'visualizer' ),
1257 + 'loading' => esc_html__( 'Loading...', 'visualizer' ),
1513 1258 ),
1514 1259 'charts' => array(
1515 1260 'canvas' => $data,
1516 1261 ),
@@ -1536,24 +1281,12 @@
1536 1281 */
1537 1282 public function getQueryData() {
1538 1283 check_ajax_referer( Visualizer_Plugin::ACTION_FETCH_DB_DATA . Visualizer_Plugin::VERSION, 'security' );
1539 1284
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 1285 $params = wp_parse_args( $_POST['params'] );
1552 1286 $chart_id = filter_var( $params['chart_id'], FILTER_VALIDATE_INT );
1553 - $query = trim( $params['query'], ';' );
1554 1287
1555 - $source = new Visualizer_Source_Query( stripslashes( $query ), $chart_id, $params );
1288 + $source = new Visualizer_Source_Query( stripslashes( $params['query'] ), $chart_id, $params );
1556 1289 $html = $source->fetch( true );
1557 1290 $error = $source->get_error();
1558 1291 if ( ! empty( $error ) ) {
1559 1292 wp_send_json_error( array( 'msg' => $error ) );
@@ -1568,19 +1301,8 @@
1568 1301 */
1569 1302 public function saveQuery() {
1570 1303 check_ajax_referer( Visualizer_Plugin::ACTION_SAVE_DB_QUERY . Visualizer_Plugin::VERSION, 'security' );
1571 1304
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 1305 $chart_id = filter_input(
1584 1306 INPUT_GET,
1585 1307 'chart',
1586 1308 FILTER_VALIDATE_INT,
@@ -1593,9 +1315,9 @@
1593 1315
1594 1316 $hours = filter_input(
1595 1317 INPUT_POST,
1596 1318 'refresh',
1597 - FILTER_VALIDATE_FLOAT,
1319 + FILTER_VALIDATE_INT,
1598 1320 array(
1599 1321 'options' => array(
1600 1322 'min_range' => -1,
1601 1323 'max_range' => apply_filters( 'visualizer_is_business', false ) ? PHP_INT_MAX : -1,
@@ -1602,9 +1324,9 @@
1602 1324 ),
1603 1325 )
1604 1326 );
1605 1327
1606 - if ( ! is_numeric( $hours ) ) {
1328 + if ( ! is_int( $hours ) ) {
1607 1329 $hours = -1;
1608 1330 }
1609 1331
1610 1332 $render = new Visualizer_Render_Page_Update();
@@ -1609,14 +1331,13 @@
1609 1331
1610 1332 $render = new Visualizer_Render_Page_Update();
1611 1333 if ( $chart_id ) {
1612 1334 $params = wp_parse_args( $_POST['params'] );
1613 - $query = trim( $params['query'], ';' );
1614 - $source = new Visualizer_Source_Query( stripslashes( $query ), $chart_id, $params );
1335 + $source = new Visualizer_Source_Query( stripslashes( $params['query'] ), $chart_id, $params );
1615 1336 $source->fetch( false );
1616 1337 $error = $source->get_error();
1617 1338 if ( empty( $error ) ) {
1618 - update_post_meta( $chart_id, Visualizer_Plugin::CF_DB_QUERY, stripslashes( $query ) );
1339 + update_post_meta( $chart_id, Visualizer_Plugin::CF_DB_QUERY, stripslashes( $params['query'] ) );
1619 1340 update_post_meta( $chart_id, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() );
1620 1341 update_post_meta( $chart_id, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
1621 1342 update_post_meta( $chart_id, Visualizer_Plugin::CF_DB_SCHEDULE, $hours );
1622 1343 update_post_meta( $chart_id, Visualizer_Plugin::CF_DEFAULT_DATA, 0 );
@@ -1645,9 +1366,9 @@
1645 1366 }
1646 1367 }
1647 1368 $render->render();
1648 1369 if ( ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE ) ) {
1649 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1370 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1650 1371 }
1651 1372 }
1652 1373
1653 1374
@@ -1672,9 +1393,9 @@
1672 1393
1673 1394 $hours = filter_input(
1674 1395 INPUT_POST,
1675 1396 'refresh',
1676 - FILTER_VALIDATE_FLOAT,
1397 + FILTER_VALIDATE_INT,
1677 1398 array(
1678 1399 'options' => array(
1679 1400 'min_range' => -1,
1680 1401 'max_range' => apply_filters( 'visualizer_is_business', false ) ? PHP_INT_MAX : -1,
@@ -1681,9 +1402,9 @@
1681 1402 ),
1682 1403 )
1683 1404 );
1684 1405
1685 - if ( ! is_numeric( $hours ) ) {
1406 + if ( 0 !== $hours && empty( $hours ) ) {
1686 1407 $hours = -1;
1687 1408 }
1688 1409
1689 1410 do_action( 'visualizer_save_filter', $chart_id, $hours );
@@ -1688,61 +1409,8 @@
1688 1409
1689 1410 do_action( 'visualizer_save_filter', $chart_id, $hours );
1690 1411
1691 1412 if ( ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE ) ) {
1692 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1413 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1693 1414 }
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 1415 }
1748 1416 }