PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.4.7
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.4.7
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 -416 4.0.33.4.7 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,44 @@
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 - // Set current screen for the render chart.
541 - set_current_screen( 'visualizer_render_chart' );
542 489 // check chart, if chart not exists, will create new one and redirects to the same page with proper chart id
543 490 $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(
491 + if ( ! $chart_id || ! ( $chart = get_post( $chart_id ) ) || $chart->post_type !== Visualizer_Plugin::CPT_VISUALIZER ) {
492 + $this->deleteOldCharts();
493 + $default_type = isset( $_GET['type'] ) && ! empty( $_GET['type'] ) ? $_GET['type'] : 'line';
494 + $source = new Visualizer_Source_Csv( VISUALIZER_ABSPATH . DIRECTORY_SEPARATOR . 'samples' . DIRECTORY_SEPARATOR . $default_type . '.csv' );
495 + $source->fetch();
496 + $chart_id = wp_insert_post(
497 + array(
498 + 'post_type' => Visualizer_Plugin::CPT_VISUALIZER,
499 + 'post_title' => 'Visualization',
500 + 'post_author' => get_current_user_id(),
501 + 'post_status' => 'auto-draft',
502 + 'post_content' => $source->getData( get_post_meta( $chart_id, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) ),
503 + )
504 + );
505 + if ( $chart_id && ! is_wp_error( $chart_id ) ) {
506 + add_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_TYPE, $default_type );
507 + add_post_meta( $chart_id, Visualizer_Plugin::CF_DEFAULT_DATA, 1 );
508 + add_post_meta( $chart_id, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() );
509 + add_post_meta( $chart_id, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
510 + add_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_LIBRARY, '' );
511 + add_post_meta(
512 + $chart_id,
513 + Visualizer_Plugin::CF_SETTINGS,
559 514 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 ) ),
515 + 'focusTarget' => 'datum',
565 516 )
566 517 );
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 518 do_action( 'visualizer_pro_new_chart_defaults', $chart_id );
614 519 }
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();
520 + wp_redirect( add_query_arg( 'chart', (int) $chart_id ) );
521 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
621 522 }
622 523
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 524 $lib = $this->load_chart_type( $chart_id );
633 525
634 526 // the alpha color picker (RGBA) is not supported by google.
635 527 $color_picker_dep = 'wp-color-picker';
@@ -691,16 +583,8 @@
691 583 // if the edit button is clicked.
692 584 $this->_chart = $this->handleExistingRevisions( $chart_id, $this->_chart );
693 585 }
694 586
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 587 switch ( $tab ) {
704 588 case 'settings':
705 589 $this->_handleDataAndSettingsPage();
706 590 break;
@@ -711,9 +595,9 @@
711 595 default:
712 596 // this should never happen.
713 597 break;
714 598 }
715 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
599 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
716 600 }
717 601
718 602 /**
719 603 * Load code editor assets.
@@ -725,9 +609,9 @@
725 609
726 610 // data tables assets.
727 611 wp_register_script( 'visualizer-datatables', VISUALIZER_ABSURL . 'js/lib/datatables.min.js', array( 'jquery-ui-core' ), Visualizer_Plugin::VERSION );
728 612 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 );
613 + 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 614 wp_enqueue_script( 'visualizer-datatables' );
731 615 wp_enqueue_style( 'visualizer-jquery-ui' );
732 616
733 617 if ( ! Visualizer_Module::is_pro() ) {
@@ -743,9 +627,9 @@
743 627 wp_register_script( 'visualizer-codemirror-matchbrackets', '//codemirror.net/addon/edit/matchbrackets.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
744 628 wp_register_script( 'visualizer-codemirror-closebrackets', '//codemirror.net/addon/edit/closebrackets.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
745 629 wp_register_script( 'visualizer-codemirror-sql', '//codemirror.net/mode/sql/sql.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
746 630 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 );
631 + 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 632 wp_register_style( 'visualizer-codemirror-core', '//codemirror.net/lib/codemirror.css', array(), Visualizer_Plugin::VERSION );
749 633 wp_register_style( 'visualizer-codemirror-hint', '//codemirror.net/addon/hint/show-hint.css', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
750 634
751 635 wp_enqueue_script( 'visualizer-codemirror-hint' );
@@ -759,9 +643,9 @@
759 643 'lineWrapping' => true,
760 644 'dragDrop' => false,
761 645 'matchBrackets' => true,
762 646 'autoCloseBrackets' => true,
763 - 'extraKeys' => array( 'Shift-Space' => 'autocomplete' ),
647 + 'extraKeys' => array( 'Ctrl-Space' => 'autocomplete' ),
764 648 'hintOptions' => array( 'tables' => $table_col_mapping ),
765 649 ),
766 650 )
767 651 );
@@ -795,12 +679,9 @@
795 679 update_option( 'visualizer-map-api-key', $_POST['map_api_key'] );
796 680 }
797 681
798 682 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 ) {
683 + if ( $this->_chart->post_status === 'auto-draft' ) {
803 684 $this->_chart->post_status = 'publish';
804 685
805 686 // 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 687 // we do not want any difference in data so disable revisions temporarily.
@@ -808,15 +689,10 @@
808 689
809 690 wp_update_post( $this->_chart->to_array() );
810 691 }
811 692 // 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 );
693 + if ( ! ( isset( $_POST['cancel'] ) && 1 === intval( $_POST['cancel'] ) ) ) {
694 + update_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SETTINGS, $_POST );
819 695
820 696 // we will keep a parameter called 'internal_title' that will be set to the given title or, if empty, the chart ID
821 697 // this will help in searching with the chart id.
822 698 $settings = get_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SETTINGS, true );
@@ -830,14 +706,8 @@
830 706 if ( empty( $title ) ) {
831 707 $title = $this->_chart->ID;
832 708 }
833 709 $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 710 update_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SETTINGS, $settings );
841 711 }
842 712 $render = new Visualizer_Render_Page_Send();
843 713 $render->text = sprintf( '[visualizer id="%d"]', $this->_chart->ID );
@@ -863,9 +733,8 @@
863 733 wp_enqueue_style( 'visualizer-frame' );
864 734 wp_enqueue_script( 'visualizer-preview' );
865 735 wp_enqueue_script( 'visualizer-chosen' );
866 736 wp_enqueue_script( 'visualizer-render' );
867 - wp_enqueue_code_editor( array( 'type' => 'application/json' ) );
868 737
869 738 if ( Visualizer_Module::can_show_feature( 'simple-editor' ) ) {
870 739 wp_enqueue_script( 'visualizer-editor-simple' );
871 740 wp_localize_script(
@@ -873,10 +742,12 @@
873 742 'visualizer1',
874 743 array(
875 744 'ajax' => array(
876 745 'url' => admin_url( 'admin-ajax.php' ),
877 - 'nonces' => array(),
878 - 'actions' => array(),
746 + 'nonces' => array(
747 + ),
748 + 'actions' => array(
749 + ),
879 750 ),
880 751 )
881 752 );
882 753 }
@@ -887,15 +758,13 @@
887 758 'visualizer-render',
888 759 'visualizer',
889 760 array(
890 761 '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' ),
762 + 'invalid_source' => esc_html__( 'You have entered an invalid URL. Please provide a valid URL.', 'visualizer' ),
763 + 'loading' => esc_html__( 'Loading...', 'visualizer' ),
764 + 'json_error' => esc_html__( 'An error occured in fetching data.', 'visualizer' ),
765 + 'select_columns' => esc_html__( 'Please select a few columns to include in the chart.', 'visualizer' ),
766 + '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 767 ),
899 768 'charts' => array(
900 769 'canvas' => $data,
901 770 'id' => $this->_chart->ID,
@@ -926,9 +795,8 @@
926 795 'page_type' => 'chart',
927 796 'json_tag_separator' => Visualizer_Source_Json::TAG_SEPARATOR,
928 797 'json_tag_separator_view' => Visualizer_Source_Json::TAG_SEPARATOR_VIEW,
929 798 'is_front' => false,
930 - 'rest_base' => get_rest_url( null, 'wc/v3/reports/' ),
931 799 )
932 800 );
933 801
934 802 $render = new Visualizer_Render_Page_Data();
@@ -939,10 +807,11 @@
939 807 if ( filter_input( INPUT_GET, 'library', FILTER_VALIDATE_BOOLEAN ) ) {
940 808 $render->button = filter_input( INPUT_GET, 'action' ) === Visualizer_Plugin::ACTION_EDIT_CHART
941 809 ? esc_html__( 'Save Chart', 'visualizer' )
942 810 : esc_html__( 'Create Chart', 'visualizer' );
943 -
944 - $render->cancel_button = esc_html__( 'Cancel', 'visualizer' );
811 + if ( filter_input( INPUT_GET, 'action' ) === Visualizer_Plugin::ACTION_EDIT_CHART ) {
812 + $render->cancel_button = esc_html__( 'Cancel', 'visualizer' );
813 + }
945 814 } else {
946 815 $render->button = esc_attr__( 'Insert Chart', 'visualizer' );
947 816 }
948 817
@@ -965,12 +834,12 @@
965 834 * @access private
966 835 */
967 836 private function _handleTypesPage() {
968 837 // process post request
969 - if ( $_SERVER['REQUEST_METHOD'] === 'POST' && wp_verify_nonce( filter_input( INPUT_POST, 'nonce' ), 'visualizer-upload-data' ) ) {
838 + if ( $_SERVER['REQUEST_METHOD'] === 'POST' && wp_verify_nonce( filter_input( INPUT_POST, 'nonce' ) ) ) {
970 839 $type = filter_input( INPUT_POST, 'type' );
971 840 $library = filter_input( INPUT_POST, 'chart-library' );
972 - if ( Visualizer_Module_Admin::checkChartStatus( $type ) ) {
841 + if ( in_array( $type, Visualizer_Plugin::getChartTypes(), true ) ) {
973 842 if ( empty( $library ) ) {
974 843 // library cannot be empty.
975 844 do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, 'Chart library empty while creating the chart! Aborting...', 'error', __FILE__, __LINE__ );
976 845 return;
@@ -991,9 +860,9 @@
991 860 Visualizer_Module_Utility::set_defaults( $this->_chart );
992 861
993 862 // redirect to next tab
994 863 // changed by Ash/Upwork
995 - wp_redirect( esc_url_raw( add_query_arg( 'tab', 'settings' ) ) );
864 + wp_redirect( add_query_arg( 'tab', 'settings' ) );
996 865
997 866 return;
998 867 }
999 868 }
@@ -1022,80 +891,8 @@
1022 891 * Processes the CSV that is sent in the request as a string.
1023 892 *
1024 893 * @since 3.2.0
1025 894 */
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 895 private function handleCSVasString( $data, $editor_type ) {
1099 896 $source = null;
1100 897
1101 898 switch ( $editor_type ) {
@@ -1108,16 +905,8 @@
1108 905 foreach ( $values as $row ) {
1109 906 if ( empty( $row ) ) {
1110 907 continue;
1111 908 }
1112 - $row = explode( ',', $row );
1113 - $row = array_map(
1114 - function ( $r ) {
1115 - return '' === $r ? ' ' : $r;
1116 - },
1117 - $row
1118 - );
1119 - $row = implode( ',', $row );
1120 909 // don't use fpucsv here because we need to just dump the data
1121 910 // minus the empty rows
1122 911 // because fputcsv needs to tokenize
1123 912 // we can standardize the CSV enclosure here and replace all ' with "
@@ -1161,9 +950,9 @@
1161 950 foreach ( $types as $type ) {
1162 951 if ( empty( $type ) ) {
1163 952 $exclude[] = $index;
1164 953 }
1165 - ++$index;
954 + $index++;
1166 955 }
1167 956
1168 957 // when N headers are being renamed, the number of headers increases by N
1169 958 // because of the way datatable duplicates header information
@@ -1223,13 +1012,9 @@
1223 1012 // otherwise, assume this is a normal web request.
1224 1013 $can_die = ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE );
1225 1014
1226 1015 // validate nonce
1227 - if (
1228 - ! isset( $_GET['nonce'] ) ||
1229 - ! wp_verify_nonce( $_GET['nonce'], 'visualizer-upload-data' ) ||
1230 - ! current_user_can( 'edit_posts' )
1231 - ) {
1016 + if ( ! isset( $_GET['nonce'] ) || ! wp_verify_nonce( $_GET['nonce'] ) ) {
1232 1017 if ( ! $can_die ) {
1233 1018 return;
1234 1019 }
1235 1020 status_header( 403 );
@@ -1238,15 +1023,9 @@
1238 1023
1239 1024 // check chart, if chart exists
1240 1025 // do not use filter_input as it does not work for phpunit test cases, use filter_var instead
1241 1026 $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 - ) {
1027 + if ( ! $chart_id || ! ( $chart = get_post( $chart_id ) ) || $chart->post_type !== Visualizer_Plugin::CPT_VISUALIZER ) {
1249 1028 if ( ! $can_die ) {
1250 1029 return;
1251 1030 }
1252 1031 status_header( 400 );
@@ -1282,35 +1061,18 @@
1282 1061
1283 1062 // delete editor related data.
1284 1063 delete_post_meta( $chart_id, Visualizer_Plugin::CF_EDITOR );
1285 1064
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 1065 $source = null;
1290 1066 $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 - }
1067 + if ( isset( $_POST['remote_data'] ) && filter_var( $_POST['remote_data'], FILTER_VALIDATE_URL ) ) {
1068 + $source = new Visualizer_Source_Csv_Remote( $_POST['remote_data'] );
1303 1069 if ( isset( $_POST['vz-import-time'] ) ) {
1304 - apply_filters( 'visualizer_pro_chart_schedule', $chart_id, $remote_data, $_POST['vz-import-time'] );
1070 + apply_filters( 'visualizer_pro_chart_schedule', $chart_id, $_POST['remote_data'], $_POST['vz-import-time'] );
1305 1071 }
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 - }
1072 + // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
1073 + } elseif ( isset( $_FILES['local_data'] ) && $_FILES['local_data']['error'] == 0 ) {
1074 + $source = new Visualizer_Source_Csv( $_FILES['local_data']['tmp_name'] );
1313 1075 } elseif ( isset( $_POST['chart_data'] ) && strlen( $_POST['chart_data'] ) > 0 ) {
1314 1076 $source = $this->handleCSVasString( $_POST['chart_data'], $_POST['editor-type'] );
1315 1077 update_post_meta( $chart_id, Visualizer_Plugin::CF_EDITOR, $_POST['editor-type'] );
1316 1078 } elseif ( isset( $_POST['table_data'] ) && 'yes' === $_POST['table_data'] ) {
@@ -1317,10 +1079,10 @@
1317 1079 $source = $this->handleTabularData();
1318 1080 update_post_meta( $chart_id, Visualizer_Plugin::CF_EDITOR, $_POST['editor-type'] );
1319 1081 } else {
1320 1082 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' ) );
1083 + $render->message = esc_html__( 'CSV file with chart data was not uploaded. Please try again.', 'visualizer' );
1084 + update_post_meta( $chart_id, Visualizer_Plugin::CF_ERROR, esc_html__( 'CSV file with chart data was not uploaded. Please try again.', 'visualizer' ) );
1323 1085 }
1324 1086
1325 1087 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 1088
@@ -1341,9 +1103,8 @@
1341 1103 if ( $populate ) {
1342 1104 $chart->post_content = $content;
1343 1105 }
1344 1106 wp_update_post( $chart->to_array() );
1345 -
1346 1107 update_post_meta( $chart->ID, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
1347 1108 update_post_meta( $chart->ID, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() );
1348 1109 update_post_meta( $chart->ID, Visualizer_Plugin::CF_DEFAULT_DATA, 0 );
1349 1110
@@ -1351,17 +1112,8 @@
1351 1112
1352 1113 Visualizer_Module_Utility::set_defaults( $chart, null );
1353 1114
1354 1115 $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 1116
1365 1117 $render->id = $chart->ID;
1366 1118 $render->data = json_encode( $source->getRawData( get_post_meta( $chart->ID, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) ) );
1367 1119 $render->series = json_encode( $source->getSeries() );
@@ -1368,9 +1120,9 @@
1368 1120 $render->settings = json_encode( $settings );
1369 1121 } else {
1370 1122 $error = $source->get_error();
1371 1123 if ( empty( $error ) ) {
1372 - $error = esc_html__( 'The CSV file couldn\'t be read. Check that it\'s properly formatted and try again.', 'visualizer' );
1124 + $error = esc_html__( 'CSV file is broken or invalid. Please try again.', 'visualizer' );
1373 1125 }
1374 1126 $render->message = $error;
1375 1127 do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( '%s for chart %d.', $error, $chart_id ), 'error', __FILE__, __LINE__ );
1376 1128 update_post_meta( $chart_id, Visualizer_Plugin::CF_ERROR, $error );
@@ -1381,9 +1133,9 @@
1381 1133 $render->render();
1382 1134 if ( ! $can_die ) {
1383 1135 return;
1384 1136 }
1385 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1137 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1386 1138 }
1387 1139
1388 1140 /**
1389 1141 * Clones the chart.
@@ -1422,26 +1174,23 @@
1422 1174 if ( strpos( $key, 'visualizer-' ) !== false ) {
1423 1175 add_post_meta( $new_chart_id, $key, maybe_unserialize( $value[0] ) );
1424 1176 }
1425 1177 }
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' )
1178 + $redirect = add_query_arg(
1179 + array(
1180 + 'page' => 'visualizer',
1181 + 'type' => filter_input( INPUT_GET, 'type' ),
1182 + 'vaction' => false,
1434 1183 ),
1435 - null,
1436 - 'db'
1184 + admin_url( 'admin.php' )
1437 1185 );
1438 1186 }
1439 1187 }
1440 1188
1441 - if ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) {
1189 + if ( defined( 'WP_TESTS_DOMAIN' ) ) {
1442 1190 wp_die();
1443 1191 }
1192 +
1444 1193 wp_redirect( $redirect );
1445 1194 exit;
1446 1195 }
1447 1196
@@ -1472,9 +1221,9 @@
1472 1221 }
1473 1222 }
1474 1223 }
1475 1224
1476 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1225 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1477 1226 }
1478 1227
1479 1228 /**
1480 1229 * Handles chart data page.
@@ -1498,11 +1247,10 @@
1498 1247 'visualizer-render',
1499 1248 'visualizer',
1500 1249 array(
1501 1250 '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' ),
1251 + 'invalid_source' => esc_html__( 'You have entered an invalid URL. Please provide a valid URL.', 'visualizer' ),
1252 + 'loading' => esc_html__( 'Loading...', 'visualizer' ),
1505 1253 ),
1506 1254 'charts' => array(
1507 1255 'canvas' => $data,
1508 1256 ),
@@ -1528,24 +1276,12 @@
1528 1276 */
1529 1277 public function getQueryData() {
1530 1278 check_ajax_referer( Visualizer_Plugin::ACTION_FETCH_DB_DATA . Visualizer_Plugin::VERSION, 'security' );
1531 1279
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 1280 $params = wp_parse_args( $_POST['params'] );
1544 1281 $chart_id = filter_var( $params['chart_id'], FILTER_VALIDATE_INT );
1545 - $query = trim( $params['query'], ';' );
1546 1282
1547 - $source = new Visualizer_Source_Query( stripslashes( $query ), $chart_id, $params );
1283 + $source = new Visualizer_Source_Query( stripslashes( $params['query'] ), $chart_id, $params );
1548 1284 $html = $source->fetch( true );
1549 1285 $error = $source->get_error();
1550 1286 if ( ! empty( $error ) ) {
1551 1287 wp_send_json_error( array( 'msg' => $error ) );
@@ -1560,19 +1296,8 @@
1560 1296 */
1561 1297 public function saveQuery() {
1562 1298 check_ajax_referer( Visualizer_Plugin::ACTION_SAVE_DB_QUERY . Visualizer_Plugin::VERSION, 'security' );
1563 1299
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 1300 $chart_id = filter_input(
1576 1301 INPUT_GET,
1577 1302 'chart',
1578 1303 FILTER_VALIDATE_INT,
@@ -1585,9 +1310,9 @@
1585 1310
1586 1311 $hours = filter_input(
1587 1312 INPUT_POST,
1588 1313 'refresh',
1589 - FILTER_VALIDATE_FLOAT,
1314 + FILTER_VALIDATE_INT,
1590 1315 array(
1591 1316 'options' => array(
1592 1317 'min_range' => -1,
1593 1318 'max_range' => apply_filters( 'visualizer_is_business', false ) ? PHP_INT_MAX : -1,
@@ -1594,9 +1319,9 @@
1594 1319 ),
1595 1320 )
1596 1321 );
1597 1322
1598 - if ( ! is_numeric( $hours ) ) {
1323 + if ( ! is_int( $hours ) ) {
1599 1324 $hours = -1;
1600 1325 }
1601 1326
1602 1327 $render = new Visualizer_Render_Page_Update();
@@ -1601,14 +1326,13 @@
1601 1326
1602 1327 $render = new Visualizer_Render_Page_Update();
1603 1328 if ( $chart_id ) {
1604 1329 $params = wp_parse_args( $_POST['params'] );
1605 - $query = trim( $params['query'], ';' );
1606 - $source = new Visualizer_Source_Query( stripslashes( $query ), $chart_id, $params );
1330 + $source = new Visualizer_Source_Query( stripslashes( $params['query'] ), $chart_id, $params );
1607 1331 $source->fetch( false );
1608 1332 $error = $source->get_error();
1609 1333 if ( empty( $error ) ) {
1610 - update_post_meta( $chart_id, Visualizer_Plugin::CF_DB_QUERY, stripslashes( $query ) );
1334 + update_post_meta( $chart_id, Visualizer_Plugin::CF_DB_QUERY, stripslashes( $params['query'] ) );
1611 1335 update_post_meta( $chart_id, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() );
1612 1336 update_post_meta( $chart_id, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
1613 1337 update_post_meta( $chart_id, Visualizer_Plugin::CF_DB_SCHEDULE, $hours );
1614 1338 update_post_meta( $chart_id, Visualizer_Plugin::CF_DEFAULT_DATA, 0 );
@@ -1637,9 +1361,9 @@
1637 1361 }
1638 1362 }
1639 1363 $render->render();
1640 1364 if ( ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE ) ) {
1641 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1365 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1642 1366 }
1643 1367 }
1644 1368
1645 1369
@@ -1664,9 +1388,9 @@
1664 1388
1665 1389 $hours = filter_input(
1666 1390 INPUT_POST,
1667 1391 'refresh',
1668 - FILTER_VALIDATE_FLOAT,
1392 + FILTER_VALIDATE_INT,
1669 1393 array(
1670 1394 'options' => array(
1671 1395 'min_range' => -1,
1672 1396 'max_range' => apply_filters( 'visualizer_is_business', false ) ? PHP_INT_MAX : -1,
@@ -1673,9 +1397,9 @@
1673 1397 ),
1674 1398 )
1675 1399 );
1676 1400
1677 - if ( ! is_numeric( $hours ) ) {
1401 + if ( ! $hours ) {
1678 1402 $hours = -1;
1679 1403 }
1680 1404
1681 1405 do_action( 'visualizer_save_filter', $chart_id, $hours );
@@ -1680,61 +1404,8 @@
1680 1404
1681 1405 do_action( 'visualizer_save_filter', $chart_id, $hours );
1682 1406
1683 1407 if ( ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE ) ) {
1684 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1408 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1685 1409 }
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 1410 }
1740 1411 }