PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.4.8
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.4.8
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 -413 4.0.33.4.8 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 );
@@ -1287,30 +1066,16 @@
1287 1066 delete_post_meta( $chart_id, Visualizer_Plugin::CF_EDITABLE_TABLE );
1288 1067
1289 1068 $source = null;
1290 1069 $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 - }
1070 + if ( isset( $_POST['remote_data'] ) && filter_var( $_POST['remote_data'], FILTER_VALIDATE_URL ) ) {
1071 + $source = new Visualizer_Source_Csv_Remote( $_POST['remote_data'] );
1303 1072 if ( isset( $_POST['vz-import-time'] ) ) {
1304 - apply_filters( 'visualizer_pro_chart_schedule', $chart_id, $remote_data, $_POST['vz-import-time'] );
1073 + apply_filters( 'visualizer_pro_chart_schedule', $chart_id, $_POST['remote_data'], $_POST['vz-import-time'] );
1305 1074 }
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 - }
1075 + // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
1076 + } elseif ( isset( $_FILES['local_data'] ) && $_FILES['local_data']['error'] == 0 ) {
1077 + $source = new Visualizer_Source_Csv( $_FILES['local_data']['tmp_name'] );
1313 1078 } elseif ( isset( $_POST['chart_data'] ) && strlen( $_POST['chart_data'] ) > 0 ) {
1314 1079 $source = $this->handleCSVasString( $_POST['chart_data'], $_POST['editor-type'] );
1315 1080 update_post_meta( $chart_id, Visualizer_Plugin::CF_EDITOR, $_POST['editor-type'] );
1316 1081 } elseif ( isset( $_POST['table_data'] ) && 'yes' === $_POST['table_data'] ) {
@@ -1317,10 +1082,10 @@
1317 1082 $source = $this->handleTabularData();
1318 1083 update_post_meta( $chart_id, Visualizer_Plugin::CF_EDITOR, $_POST['editor-type'] );
1319 1084 } else {
1320 1085 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' ) );
1086 + $render->message = esc_html__( 'CSV file with chart data was not uploaded. Please try again.', 'visualizer' );
1087 + update_post_meta( $chart_id, Visualizer_Plugin::CF_ERROR, esc_html__( 'CSV file with chart data was not uploaded. Please try again.', 'visualizer' ) );
1323 1088 }
1324 1089
1325 1090 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 1091
@@ -1341,9 +1106,8 @@
1341 1106 if ( $populate ) {
1342 1107 $chart->post_content = $content;
1343 1108 }
1344 1109 wp_update_post( $chart->to_array() );
1345 -
1346 1110 update_post_meta( $chart->ID, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
1347 1111 update_post_meta( $chart->ID, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() );
1348 1112 update_post_meta( $chart->ID, Visualizer_Plugin::CF_DEFAULT_DATA, 0 );
1349 1113
@@ -1351,17 +1115,8 @@
1351 1115
1352 1116 Visualizer_Module_Utility::set_defaults( $chart, null );
1353 1117
1354 1118 $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 1119
1365 1120 $render->id = $chart->ID;
1366 1121 $render->data = json_encode( $source->getRawData( get_post_meta( $chart->ID, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) ) );
1367 1122 $render->series = json_encode( $source->getSeries() );
@@ -1368,9 +1123,9 @@
1368 1123 $render->settings = json_encode( $settings );
1369 1124 } else {
1370 1125 $error = $source->get_error();
1371 1126 if ( empty( $error ) ) {
1372 - $error = esc_html__( 'The CSV file couldn\'t be read. Check that it\'s properly formatted and try again.', 'visualizer' );
1127 + $error = esc_html__( 'CSV file is broken or invalid. Please try again.', 'visualizer' );
1373 1128 }
1374 1129 $render->message = $error;
1375 1130 do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( '%s for chart %d.', $error, $chart_id ), 'error', __FILE__, __LINE__ );
1376 1131 update_post_meta( $chart_id, Visualizer_Plugin::CF_ERROR, $error );
@@ -1381,9 +1136,9 @@
1381 1136 $render->render();
1382 1137 if ( ! $can_die ) {
1383 1138 return;
1384 1139 }
1385 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1140 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1386 1141 }
1387 1142
1388 1143 /**
1389 1144 * Clones the chart.
@@ -1422,26 +1177,23 @@
1422 1177 if ( strpos( $key, 'visualizer-' ) !== false ) {
1423 1178 add_post_meta( $new_chart_id, $key, maybe_unserialize( $value[0] ) );
1424 1179 }
1425 1180 }
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' )
1181 + $redirect = add_query_arg(
1182 + array(
1183 + 'page' => 'visualizer',
1184 + 'type' => filter_input( INPUT_GET, 'type' ),
1185 + 'vaction' => false,
1434 1186 ),
1435 - null,
1436 - 'db'
1187 + admin_url( 'admin.php' )
1437 1188 );
1438 1189 }
1439 1190 }
1440 1191
1441 - if ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) {
1192 + if ( defined( 'WP_TESTS_DOMAIN' ) ) {
1442 1193 wp_die();
1443 1194 }
1195 +
1444 1196 wp_redirect( $redirect );
1445 1197 exit;
1446 1198 }
1447 1199
@@ -1472,9 +1224,9 @@
1472 1224 }
1473 1225 }
1474 1226 }
1475 1227
1476 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1228 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1477 1229 }
1478 1230
1479 1231 /**
1480 1232 * Handles chart data page.
@@ -1498,11 +1250,10 @@
1498 1250 'visualizer-render',
1499 1251 'visualizer',
1500 1252 array(
1501 1253 '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' ),
1254 + 'invalid_source' => esc_html__( 'You have entered an invalid URL. Please provide a valid URL.', 'visualizer' ),
1255 + 'loading' => esc_html__( 'Loading...', 'visualizer' ),
1505 1256 ),
1506 1257 'charts' => array(
1507 1258 'canvas' => $data,
1508 1259 ),
@@ -1528,24 +1279,12 @@
1528 1279 */
1529 1280 public function getQueryData() {
1530 1281 check_ajax_referer( Visualizer_Plugin::ACTION_FETCH_DB_DATA . Visualizer_Plugin::VERSION, 'security' );
1531 1282
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 1283 $params = wp_parse_args( $_POST['params'] );
1544 1284 $chart_id = filter_var( $params['chart_id'], FILTER_VALIDATE_INT );
1545 - $query = trim( $params['query'], ';' );
1546 1285
1547 - $source = new Visualizer_Source_Query( stripslashes( $query ), $chart_id, $params );
1286 + $source = new Visualizer_Source_Query( stripslashes( $params['query'] ), $chart_id, $params );
1548 1287 $html = $source->fetch( true );
1549 1288 $error = $source->get_error();
1550 1289 if ( ! empty( $error ) ) {
1551 1290 wp_send_json_error( array( 'msg' => $error ) );
@@ -1560,19 +1299,8 @@
1560 1299 */
1561 1300 public function saveQuery() {
1562 1301 check_ajax_referer( Visualizer_Plugin::ACTION_SAVE_DB_QUERY . Visualizer_Plugin::VERSION, 'security' );
1563 1302
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 1303 $chart_id = filter_input(
1576 1304 INPUT_GET,
1577 1305 'chart',
1578 1306 FILTER_VALIDATE_INT,
@@ -1585,9 +1313,9 @@
1585 1313
1586 1314 $hours = filter_input(
1587 1315 INPUT_POST,
1588 1316 'refresh',
1589 - FILTER_VALIDATE_FLOAT,
1317 + FILTER_VALIDATE_INT,
1590 1318 array(
1591 1319 'options' => array(
1592 1320 'min_range' => -1,
1593 1321 'max_range' => apply_filters( 'visualizer_is_business', false ) ? PHP_INT_MAX : -1,
@@ -1594,9 +1322,9 @@
1594 1322 ),
1595 1323 )
1596 1324 );
1597 1325
1598 - if ( ! is_numeric( $hours ) ) {
1326 + if ( ! is_int( $hours ) ) {
1599 1327 $hours = -1;
1600 1328 }
1601 1329
1602 1330 $render = new Visualizer_Render_Page_Update();
@@ -1601,14 +1329,13 @@
1601 1329
1602 1330 $render = new Visualizer_Render_Page_Update();
1603 1331 if ( $chart_id ) {
1604 1332 $params = wp_parse_args( $_POST['params'] );
1605 - $query = trim( $params['query'], ';' );
1606 - $source = new Visualizer_Source_Query( stripslashes( $query ), $chart_id, $params );
1333 + $source = new Visualizer_Source_Query( stripslashes( $params['query'] ), $chart_id, $params );
1607 1334 $source->fetch( false );
1608 1335 $error = $source->get_error();
1609 1336 if ( empty( $error ) ) {
1610 - update_post_meta( $chart_id, Visualizer_Plugin::CF_DB_QUERY, stripslashes( $query ) );
1337 + update_post_meta( $chart_id, Visualizer_Plugin::CF_DB_QUERY, stripslashes( $params['query'] ) );
1611 1338 update_post_meta( $chart_id, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() );
1612 1339 update_post_meta( $chart_id, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
1613 1340 update_post_meta( $chart_id, Visualizer_Plugin::CF_DB_SCHEDULE, $hours );
1614 1341 update_post_meta( $chart_id, Visualizer_Plugin::CF_DEFAULT_DATA, 0 );
@@ -1637,9 +1364,9 @@
1637 1364 }
1638 1365 }
1639 1366 $render->render();
1640 1367 if ( ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE ) ) {
1641 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1368 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1642 1369 }
1643 1370 }
1644 1371
1645 1372
@@ -1664,9 +1391,9 @@
1664 1391
1665 1392 $hours = filter_input(
1666 1393 INPUT_POST,
1667 1394 'refresh',
1668 - FILTER_VALIDATE_FLOAT,
1395 + FILTER_VALIDATE_INT,
1669 1396 array(
1670 1397 'options' => array(
1671 1398 'min_range' => -1,
1672 1399 'max_range' => apply_filters( 'visualizer_is_business', false ) ? PHP_INT_MAX : -1,
@@ -1673,9 +1400,9 @@
1673 1400 ),
1674 1401 )
1675 1402 );
1676 1403
1677 - if ( ! is_numeric( $hours ) ) {
1404 + if ( ! $hours ) {
1678 1405 $hours = -1;
1679 1406 }
1680 1407
1681 1408 do_action( 'visualizer_save_filter', $chart_id, $hours );
@@ -1680,61 +1407,8 @@
1680 1407
1681 1408 do_action( 'visualizer_save_filter', $chart_id, $hours );
1682 1409
1683 1410 if ( ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE ) ) {
1684 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1411 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1685 1412 }
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 1413 }
1740 1414 }