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 -411 4.0.33.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
@@ -258,16 +241,8 @@
258 241 if ( ! empty( $params['paging'] ) ) {
259 242 add_post_meta( $chart->ID, Visualizer_Plugin::CF_JSON_PAGING, $params['paging'] );
260 243 }
261 244
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 245 $time = filter_input(
271 246 INPUT_POST,
272 247 'time',
273 248 FILTER_VALIDATE_INT,
@@ -295,9 +270,9 @@
295 270 $render->data = json_encode( $source->getRawData( get_post_meta( $chart_id, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) ) );
296 271 $render->series = json_encode( $source->getSeries() );
297 272 $render->render();
298 273
299 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
274 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
300 275 }
301 276
302 277
303 278 /**
@@ -373,13 +348,13 @@
373 348 * @since 1.0.0
374 349 *
375 350 * @access private
376 351 *
377 - * @param WP_Post|null $chart The chart object.
352 + * @param WP_Post $chart The chart object.
378 353 *
379 354 * @return array The array of chart data.
380 355 */
381 - private function _getChartArray( $chart = null ) {
356 + private function _getChartArray( WP_Post $chart = null ) {
382 357 if ( is_null( $chart ) ) {
383 358 $chart = $this->_chart;
384 359 }
385 360 $type = get_post_meta( $chart->ID, Visualizer_Plugin::CF_CHART_TYPE, true );
@@ -401,13 +376,8 @@
401 376 }
402 377
403 378 $date_formats = Visualizer_Source::get_date_formats_if_exists( $series, $data );
404 379
405 - $code = '';
406 - if ( 'd3' === $library ) {
407 - $code = get_post_meta( $chart->ID, Visualizer_Module_AIBuilder::CF_D3_CODE, true );
408 - }
409 -
410 380 return array(
411 381 'type' => $type,
412 382 'series' => $series,
413 383 'settings' => $settings,
@@ -412,9 +382,8 @@
412 382 'series' => $series,
413 383 'settings' => $settings,
414 384 'data' => $data,
415 385 'library' => $library,
416 - 'code' => $code,
417 386 'css' => $css,
418 387 'date_formats' => $date_formats,
419 388 );
420 389 }
@@ -431,9 +400,9 @@
431 400 public static function _sendResponse( $results ) {
432 401 header( 'Content-type: application/json' );
433 402 nocache_headers();
434 403 echo json_encode( $results );
435 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
404 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
436 405 }
437 406
438 407 /**
439 408 * Deletes a chart from database.
@@ -465,22 +434,9 @@
465 434 $success = $chart && $chart->post_type === Visualizer_Plugin::CPT_VISUALIZER;
466 435 }
467 436 }
468 437 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 - }
438 + wp_delete_post( $chart_id, true );
483 439 }
484 440 if ( $is_post ) {
485 441 self::_sendResponse(
486 442 array(
@@ -528,108 +484,46 @@
528 484 *
529 485 * @access public
530 486 */
531 487 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 488 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 489 // Set current screen for the render chart.
541 490 set_current_screen( 'visualizer_render_chart' );
542 491 // check chart, if chart not exists, will create new one and redirects to the same page with proper chart id
543 492 $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(
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,
559 516 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 ) ),
517 + 'focusTarget' => 'datum',
565 518 )
566 519 );
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 520 do_action( 'visualizer_pro_new_chart_defaults', $chart_id );
614 521 }
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();
522 + wp_redirect( add_query_arg( 'chart', (int) $chart_id ) );
523 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
621 524 }
622 525
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 526 $lib = $this->load_chart_type( $chart_id );
633 527
634 528 // the alpha color picker (RGBA) is not supported by google.
635 529 $color_picker_dep = 'wp-color-picker';
@@ -691,16 +585,8 @@
691 585 // if the edit button is clicked.
692 586 $this->_chart = $this->handleExistingRevisions( $chart_id, $this->_chart );
693 587 }
694 588
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 589 switch ( $tab ) {
704 590 case 'settings':
705 591 $this->_handleDataAndSettingsPage();
706 592 break;
@@ -711,9 +597,9 @@
711 597 default:
712 598 // this should never happen.
713 599 break;
714 600 }
715 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
601 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
716 602 }
717 603
718 604 /**
719 605 * Load code editor assets.
@@ -725,9 +611,9 @@
725 611
726 612 // data tables assets.
727 613 wp_register_script( 'visualizer-datatables', VISUALIZER_ABSURL . 'js/lib/datatables.min.js', array( 'jquery-ui-core' ), Visualizer_Plugin::VERSION );
728 614 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 );
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 );
730 616 wp_enqueue_script( 'visualizer-datatables' );
731 617 wp_enqueue_style( 'visualizer-jquery-ui' );
732 618
733 619 if ( ! Visualizer_Module::is_pro() ) {
@@ -743,9 +629,9 @@
743 629 wp_register_script( 'visualizer-codemirror-matchbrackets', '//codemirror.net/addon/edit/matchbrackets.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
744 630 wp_register_script( 'visualizer-codemirror-closebrackets', '//codemirror.net/addon/edit/closebrackets.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
745 631 wp_register_script( 'visualizer-codemirror-sql', '//codemirror.net/mode/sql/sql.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
746 632 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 );
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 );
748 634 wp_register_style( 'visualizer-codemirror-core', '//codemirror.net/lib/codemirror.css', array(), Visualizer_Plugin::VERSION );
749 635 wp_register_style( 'visualizer-codemirror-hint', '//codemirror.net/addon/hint/show-hint.css', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
750 636
751 637 wp_enqueue_script( 'visualizer-codemirror-hint' );
@@ -759,9 +645,9 @@
759 645 'lineWrapping' => true,
760 646 'dragDrop' => false,
761 647 'matchBrackets' => true,
762 648 'autoCloseBrackets' => true,
763 - 'extraKeys' => array( 'Shift-Space' => 'autocomplete' ),
649 + 'extraKeys' => array( 'Ctrl-Space' => 'autocomplete' ),
764 650 'hintOptions' => array( 'tables' => $table_col_mapping ),
765 651 ),
766 652 )
767 653 );
@@ -795,12 +681,9 @@
795 681 update_option( 'visualizer-map-api-key', $_POST['map_api_key'] );
796 682 }
797 683
798 684 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 ) {
685 + if ( $this->_chart->post_status === 'auto-draft' ) {
803 686 $this->_chart->post_status = 'publish';
804 687
805 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.
806 689 // we do not want any difference in data so disable revisions temporarily.
@@ -808,15 +691,10 @@
808 691
809 692 wp_update_post( $this->_chart->to_array() );
810 693 }
811 694 // 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 );
695 + if ( ! ( isset( $_POST['cancel'] ) && 1 === intval( $_POST['cancel'] ) ) ) {
696 + update_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SETTINGS, $_POST );
819 697
820 698 // we will keep a parameter called 'internal_title' that will be set to the given title or, if empty, the chart ID
821 699 // this will help in searching with the chart id.
822 700 $settings = get_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SETTINGS, true );
@@ -830,14 +708,8 @@
830 708 if ( empty( $title ) ) {
831 709 $title = $this->_chart->ID;
832 710 }
833 711 $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 712 update_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SETTINGS, $settings );
841 713 }
842 714 $render = new Visualizer_Render_Page_Send();
843 715 $render->text = sprintf( '[visualizer id="%d"]', $this->_chart->ID );
@@ -863,9 +735,8 @@
863 735 wp_enqueue_style( 'visualizer-frame' );
864 736 wp_enqueue_script( 'visualizer-preview' );
865 737 wp_enqueue_script( 'visualizer-chosen' );
866 738 wp_enqueue_script( 'visualizer-render' );
867 - wp_enqueue_code_editor( array( 'type' => 'application/json' ) );
868 739
869 740 if ( Visualizer_Module::can_show_feature( 'simple-editor' ) ) {
870 741 wp_enqueue_script( 'visualizer-editor-simple' );
871 742 wp_localize_script(
@@ -873,10 +744,12 @@
873 744 'visualizer1',
874 745 array(
875 746 'ajax' => array(
876 747 'url' => admin_url( 'admin-ajax.php' ),
877 - 'nonces' => array(),
878 - 'actions' => array(),
748 + 'nonces' => array(
749 + ),
750 + 'actions' => array(
751 + ),
879 752 ),
880 753 )
881 754 );
882 755 }
@@ -887,15 +760,13 @@
887 760 'visualizer-render',
888 761 'visualizer',
889 762 array(
890 763 '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' ),
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' ),
898 769 ),
899 770 'charts' => array(
900 771 'canvas' => $data,
901 772 'id' => $this->_chart->ID,
@@ -926,9 +797,8 @@
926 797 'page_type' => 'chart',
927 798 'json_tag_separator' => Visualizer_Source_Json::TAG_SEPARATOR,
928 799 'json_tag_separator_view' => Visualizer_Source_Json::TAG_SEPARATOR_VIEW,
929 800 'is_front' => false,
930 - 'rest_base' => get_rest_url( null, 'wc/v3/reports/' ),
931 801 )
932 802 );
933 803
934 804 $render = new Visualizer_Render_Page_Data();
@@ -939,10 +809,11 @@
939 809 if ( filter_input( INPUT_GET, 'library', FILTER_VALIDATE_BOOLEAN ) ) {
940 810 $render->button = filter_input( INPUT_GET, 'action' ) === Visualizer_Plugin::ACTION_EDIT_CHART
941 811 ? esc_html__( 'Save Chart', 'visualizer' )
942 812 : esc_html__( 'Create Chart', 'visualizer' );
943 -
944 - $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 + }
945 816 } else {
946 817 $render->button = esc_attr__( 'Insert Chart', 'visualizer' );
947 818 }
948 819
@@ -965,12 +836,12 @@
965 836 * @access private
966 837 */
967 838 private function _handleTypesPage() {
968 839 // process post request
969 - 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' ) ) ) {
970 841 $type = filter_input( INPUT_POST, 'type' );
971 842 $library = filter_input( INPUT_POST, 'chart-library' );
972 - if ( Visualizer_Module_Admin::checkChartStatus( $type ) ) {
843 + if ( in_array( $type, Visualizer_Plugin::getChartTypes(), true ) ) {
973 844 if ( empty( $library ) ) {
974 845 // library cannot be empty.
975 846 do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, 'Chart library empty while creating the chart! Aborting...', 'error', __FILE__, __LINE__ );
976 847 return;
@@ -991,9 +862,9 @@
991 862 Visualizer_Module_Utility::set_defaults( $this->_chart );
992 863
993 864 // redirect to next tab
994 865 // changed by Ash/Upwork
995 - wp_redirect( esc_url_raw( add_query_arg( 'tab', 'settings' ) ) );
866 + wp_redirect( add_query_arg( 'tab', 'settings' ) );
996 867
997 868 return;
998 869 }
999 870 }
@@ -1022,80 +893,8 @@
1022 893 * Processes the CSV that is sent in the request as a string.
1023 894 *
1024 895 * @since 3.2.0
1025 896 */
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 897 private function handleCSVasString( $data, $editor_type ) {
1099 898 $source = null;
1100 899
1101 900 switch ( $editor_type ) {
@@ -1108,16 +907,8 @@
1108 907 foreach ( $values as $row ) {
1109 908 if ( empty( $row ) ) {
1110 909 continue;
1111 910 }
1112 - $row = explode( ',', $row );
1113 - $row = array_map(
1114 - function ( $r ) {
1115 - return '' === $r ? ' ' : $r;
1116 - },
1117 - $row
1118 - );
1119 - $row = implode( ',', $row );
1120 911 // don't use fpucsv here because we need to just dump the data
1121 912 // minus the empty rows
1122 913 // because fputcsv needs to tokenize
1123 914 // we can standardize the CSV enclosure here and replace all ' with "
@@ -1161,9 +952,9 @@
1161 952 foreach ( $types as $type ) {
1162 953 if ( empty( $type ) ) {
1163 954 $exclude[] = $index;
1164 955 }
1165 - ++$index;
956 + $index++;
1166 957 }
1167 958
1168 959 // when N headers are being renamed, the number of headers increases by N
1169 960 // because of the way datatable duplicates header information
@@ -1223,13 +1014,9 @@
1223 1014 // otherwise, assume this is a normal web request.
1224 1015 $can_die = ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE );
1225 1016
1226 1017 // validate nonce
1227 - if (
1228 - ! isset( $_GET['nonce'] ) ||
1229 - ! wp_verify_nonce( $_GET['nonce'], 'visualizer-upload-data' ) ||
1230 - ! current_user_can( 'edit_posts' )
1231 - ) {
1018 + if ( ! isset( $_GET['nonce'] ) || ! wp_verify_nonce( $_GET['nonce'] ) ) {
1232 1019 if ( ! $can_die ) {
1233 1020 return;
1234 1021 }
1235 1022 status_header( 403 );
@@ -1238,15 +1025,9 @@
1238 1025
1239 1026 // check chart, if chart exists
1240 1027 // do not use filter_input as it does not work for phpunit test cases, use filter_var instead
1241 1028 $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 - ) {
1029 + if ( ! $chart_id || ! ( $chart = get_post( $chart_id ) ) || $chart->post_type !== Visualizer_Plugin::CPT_VISUALIZER ) {
1249 1030 if ( ! $can_die ) {
1250 1031 return;
1251 1032 }
1252 1033 status_header( 400 );
@@ -1287,30 +1068,16 @@
1287 1068 delete_post_meta( $chart_id, Visualizer_Plugin::CF_EDITABLE_TABLE );
1288 1069
1289 1070 $source = null;
1290 1071 $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 - }
1072 + if ( isset( $_POST['remote_data'] ) && filter_var( $_POST['remote_data'], FILTER_VALIDATE_URL ) ) {
1073 + $source = new Visualizer_Source_Csv_Remote( $_POST['remote_data'] );
1303 1074 if ( isset( $_POST['vz-import-time'] ) ) {
1304 - 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'] );
1305 1076 }
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 - }
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'] );
1313 1080 } elseif ( isset( $_POST['chart_data'] ) && strlen( $_POST['chart_data'] ) > 0 ) {
1314 1081 $source = $this->handleCSVasString( $_POST['chart_data'], $_POST['editor-type'] );
1315 1082 update_post_meta( $chart_id, Visualizer_Plugin::CF_EDITOR, $_POST['editor-type'] );
1316 1083 } elseif ( isset( $_POST['table_data'] ) && 'yes' === $_POST['table_data'] ) {
@@ -1317,10 +1084,10 @@
1317 1084 $source = $this->handleTabularData();
1318 1085 update_post_meta( $chart_id, Visualizer_Plugin::CF_EDITOR, $_POST['editor-type'] );
1319 1086 } else {
1320 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__ );
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' ) );
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' ) );
1323 1090 }
1324 1091
1325 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__ );
1326 1093
@@ -1341,9 +1108,8 @@
1341 1108 if ( $populate ) {
1342 1109 $chart->post_content = $content;
1343 1110 }
1344 1111 wp_update_post( $chart->to_array() );
1345 -
1346 1112 update_post_meta( $chart->ID, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
1347 1113 update_post_meta( $chart->ID, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() );
1348 1114 update_post_meta( $chart->ID, Visualizer_Plugin::CF_DEFAULT_DATA, 0 );
1349 1115
@@ -1351,17 +1117,8 @@
1351 1117
1352 1118 Visualizer_Module_Utility::set_defaults( $chart, null );
1353 1119
1354 1120 $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 1121
1365 1122 $render->id = $chart->ID;
1366 1123 $render->data = json_encode( $source->getRawData( get_post_meta( $chart->ID, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) ) );
1367 1124 $render->series = json_encode( $source->getSeries() );
@@ -1368,9 +1125,9 @@
1368 1125 $render->settings = json_encode( $settings );
1369 1126 } else {
1370 1127 $error = $source->get_error();
1371 1128 if ( empty( $error ) ) {
1372 - $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' );
1373 1130 }
1374 1131 $render->message = $error;
1375 1132 do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( '%s for chart %d.', $error, $chart_id ), 'error', __FILE__, __LINE__ );
1376 1133 update_post_meta( $chart_id, Visualizer_Plugin::CF_ERROR, $error );
@@ -1381,9 +1138,9 @@
1381 1138 $render->render();
1382 1139 if ( ! $can_die ) {
1383 1140 return;
1384 1141 }
1385 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1142 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1386 1143 }
1387 1144
1388 1145 /**
1389 1146 * Clones the chart.
@@ -1422,26 +1179,23 @@
1422 1179 if ( strpos( $key, 'visualizer-' ) !== false ) {
1423 1180 add_post_meta( $new_chart_id, $key, maybe_unserialize( $value[0] ) );
1424 1181 }
1425 1182 }
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' )
1183 + $redirect = add_query_arg(
1184 + array(
1185 + 'page' => 'visualizer',
1186 + 'type' => filter_input( INPUT_GET, 'type' ),
1187 + 'vaction' => false,
1434 1188 ),
1435 - null,
1436 - 'db'
1189 + admin_url( 'admin.php' )
1437 1190 );
1438 1191 }
1439 1192 }
1440 1193
1441 - if ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) {
1194 + if ( defined( 'WP_TESTS_DOMAIN' ) ) {
1442 1195 wp_die();
1443 1196 }
1197 +
1444 1198 wp_redirect( $redirect );
1445 1199 exit;
1446 1200 }
1447 1201
@@ -1472,9 +1226,9 @@
1472 1226 }
1473 1227 }
1474 1228 }
1475 1229
1476 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1230 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1477 1231 }
1478 1232
1479 1233 /**
1480 1234 * Handles chart data page.
@@ -1498,11 +1252,10 @@
1498 1252 'visualizer-render',
1499 1253 'visualizer',
1500 1254 array(
1501 1255 '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' ),
1256 + 'invalid_source' => esc_html__( 'You have entered an invalid URL. Please provide a valid URL.', 'visualizer' ),
1257 + 'loading' => esc_html__( 'Loading...', 'visualizer' ),
1505 1258 ),
1506 1259 'charts' => array(
1507 1260 'canvas' => $data,
1508 1261 ),
@@ -1528,24 +1281,12 @@
1528 1281 */
1529 1282 public function getQueryData() {
1530 1283 check_ajax_referer( Visualizer_Plugin::ACTION_FETCH_DB_DATA . Visualizer_Plugin::VERSION, 'security' );
1531 1284
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 1285 $params = wp_parse_args( $_POST['params'] );
1544 1286 $chart_id = filter_var( $params['chart_id'], FILTER_VALIDATE_INT );
1545 - $query = trim( $params['query'], ';' );
1546 1287
1547 - $source = new Visualizer_Source_Query( stripslashes( $query ), $chart_id, $params );
1288 + $source = new Visualizer_Source_Query( stripslashes( $params['query'] ), $chart_id, $params );
1548 1289 $html = $source->fetch( true );
1549 1290 $error = $source->get_error();
1550 1291 if ( ! empty( $error ) ) {
1551 1292 wp_send_json_error( array( 'msg' => $error ) );
@@ -1560,19 +1301,8 @@
1560 1301 */
1561 1302 public function saveQuery() {
1562 1303 check_ajax_referer( Visualizer_Plugin::ACTION_SAVE_DB_QUERY . Visualizer_Plugin::VERSION, 'security' );
1563 1304
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 1305 $chart_id = filter_input(
1576 1306 INPUT_GET,
1577 1307 'chart',
1578 1308 FILTER_VALIDATE_INT,
@@ -1585,9 +1315,9 @@
1585 1315
1586 1316 $hours = filter_input(
1587 1317 INPUT_POST,
1588 1318 'refresh',
1589 - FILTER_VALIDATE_FLOAT,
1319 + FILTER_VALIDATE_INT,
1590 1320 array(
1591 1321 'options' => array(
1592 1322 'min_range' => -1,
1593 1323 'max_range' => apply_filters( 'visualizer_is_business', false ) ? PHP_INT_MAX : -1,
@@ -1594,9 +1324,9 @@
1594 1324 ),
1595 1325 )
1596 1326 );
1597 1327
1598 - if ( ! is_numeric( $hours ) ) {
1328 + if ( ! is_int( $hours ) ) {
1599 1329 $hours = -1;
1600 1330 }
1601 1331
1602 1332 $render = new Visualizer_Render_Page_Update();
@@ -1601,14 +1331,13 @@
1601 1331
1602 1332 $render = new Visualizer_Render_Page_Update();
1603 1333 if ( $chart_id ) {
1604 1334 $params = wp_parse_args( $_POST['params'] );
1605 - $query = trim( $params['query'], ';' );
1606 - $source = new Visualizer_Source_Query( stripslashes( $query ), $chart_id, $params );
1335 + $source = new Visualizer_Source_Query( stripslashes( $params['query'] ), $chart_id, $params );
1607 1336 $source->fetch( false );
1608 1337 $error = $source->get_error();
1609 1338 if ( empty( $error ) ) {
1610 - 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'] ) );
1611 1340 update_post_meta( $chart_id, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() );
1612 1341 update_post_meta( $chart_id, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
1613 1342 update_post_meta( $chart_id, Visualizer_Plugin::CF_DB_SCHEDULE, $hours );
1614 1343 update_post_meta( $chart_id, Visualizer_Plugin::CF_DEFAULT_DATA, 0 );
@@ -1637,9 +1366,9 @@
1637 1366 }
1638 1367 }
1639 1368 $render->render();
1640 1369 if ( ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE ) ) {
1641 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1370 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1642 1371 }
1643 1372 }
1644 1373
1645 1374
@@ -1664,9 +1393,9 @@
1664 1393
1665 1394 $hours = filter_input(
1666 1395 INPUT_POST,
1667 1396 'refresh',
1668 - FILTER_VALIDATE_FLOAT,
1397 + FILTER_VALIDATE_INT,
1669 1398 array(
1670 1399 'options' => array(
1671 1400 'min_range' => -1,
1672 1401 'max_range' => apply_filters( 'visualizer_is_business', false ) ? PHP_INT_MAX : -1,
@@ -1673,9 +1402,9 @@
1673 1402 ),
1674 1403 )
1675 1404 );
1676 1405
1677 - if ( ! is_numeric( $hours ) ) {
1406 + if ( 0 !== $hours && empty( $hours ) ) {
1678 1407 $hours = -1;
1679 1408 }
1680 1409
1681 1410 do_action( 'visualizer_save_filter', $chart_id, $hours );
@@ -1680,61 +1409,8 @@
1680 1409
1681 1410 do_action( 'visualizer_save_filter', $chart_id, $hours );
1682 1411
1683 1412 if ( ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE ) ) {
1684 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1413 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1685 1414 }
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 1415 }
1740 1416 }