PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.7.0
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.7.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 +86 -341 4.0.53.7.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,22 +134,8 @@
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 );
@@ -169,12 +156,8 @@
169 156 */
170 157 public function getJsonRoots() {
171 158 check_ajax_referer( Visualizer_Plugin::ACTION_JSON_GET_ROOTS . Visualizer_Plugin::VERSION, 'security' );
172 159
173 - if ( ! current_user_can( 'edit_posts' ) ) {
174 - wp_send_json_error( array( 'msg' => esc_html__( 'You do not have permission to perform this action.', 'visualizer' ) ) );
175 - }
176 -
177 160 $params = wp_parse_args( $_POST['params'] );
178 161
179 162 $source = new Visualizer_Source_Json( $params );
180 163
@@ -195,12 +178,8 @@
195 178 */
196 179 public function getJsonData() {
197 180 check_ajax_referer( Visualizer_Plugin::ACTION_JSON_GET_DATA . Visualizer_Plugin::VERSION, 'security' );
198 181
199 - if ( ! current_user_can( 'edit_posts' ) ) {
200 - wp_send_json_error( array( 'msg' => esc_html__( 'You do not have permission to perform this action.', 'visualizer' ) ) );
201 - }
202 -
203 182 $params = wp_parse_args( $_POST['params'] );
204 183
205 184 $chart_id = $params['chart'];
206 185
@@ -266,16 +245,8 @@
266 245 if ( ! empty( $params['paging'] ) ) {
267 246 add_post_meta( $chart->ID, Visualizer_Plugin::CF_JSON_PAGING, $params['paging'] );
268 247 }
269 248
270 - if ( Visualizer_Module::is_pro() ) {
271 - if ( ! empty( $params['vz_woo_source'] ) ) {
272 - update_post_meta( $chart->ID, Visualizer_Plugin::CF_JSON_WOOCOMMERCE_SOURCE, $params['vz_woo_source'] );
273 - } else {
274 - delete_post_meta( $chart->ID, Visualizer_Plugin::CF_JSON_WOOCOMMERCE_SOURCE );
275 - }
276 - }
277 -
278 249 $time = filter_input(
279 250 INPUT_POST,
280 251 'time',
281 252 FILTER_VALIDATE_INT,
@@ -303,9 +274,9 @@
303 274 $render->data = json_encode( $source->getRawData( get_post_meta( $chart_id, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) ) );
304 275 $render->series = json_encode( $source->getSeries() );
305 276 $render->render();
306 277
307 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
278 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
308 279 }
309 280
310 281
311 282 /**
@@ -381,13 +352,13 @@
381 352 * @since 1.0.0
382 353 *
383 354 * @access private
384 355 *
385 - * @param WP_Post|null $chart The chart object.
356 + * @param WP_Post $chart The chart object.
386 357 *
387 358 * @return array The array of chart data.
388 359 */
389 - private function _getChartArray( $chart = null ) {
360 + private function _getChartArray( WP_Post $chart = null ) {
390 361 if ( is_null( $chart ) ) {
391 362 $chart = $this->_chart;
392 363 }
393 364 $type = get_post_meta( $chart->ID, Visualizer_Plugin::CF_CHART_TYPE, true );
@@ -409,13 +380,8 @@
409 380 }
410 381
411 382 $date_formats = Visualizer_Source::get_date_formats_if_exists( $series, $data );
412 383
413 - $code = '';
414 - if ( 'd3' === $library ) {
415 - $code = get_post_meta( $chart->ID, Visualizer_Module_AIBuilder::CF_D3_CODE, true );
416 - }
417 -
418 384 return array(
419 385 'type' => $type,
420 386 'series' => $series,
421 387 'settings' => $settings,
@@ -420,9 +386,8 @@
420 386 'series' => $series,
421 387 'settings' => $settings,
422 388 'data' => $data,
423 389 'library' => $library,
424 - 'code' => $code,
425 390 'css' => $css,
426 391 'date_formats' => $date_formats,
427 392 );
428 393 }
@@ -439,9 +404,9 @@
439 404 public static function _sendResponse( $results ) {
440 405 header( 'Content-type: application/json' );
441 406 nocache_headers();
442 407 echo json_encode( $results );
443 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
408 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
444 409 }
445 410
446 411 /**
447 412 * Deletes a chart from database.
@@ -473,22 +438,9 @@
473 438 $success = $chart && $chart->post_type === Visualizer_Plugin::CPT_VISUALIZER;
474 439 }
475 440 }
476 441 if ( $success ) {
477 - global $sitepress;
478 - if ( Visualizer_Module::is_pro() && ( function_exists( 'icl_get_languages' ) && $sitepress instanceof \SitePress ) ) {
479 - $trid = $sitepress->get_element_trid( $chart_id, 'post_' . Visualizer_Plugin::CPT_VISUALIZER );
480 - $translations = $sitepress->get_element_translations( $trid );
481 - if ( ! empty( $translations ) ) {
482 - foreach ( $translations as $translated_post ) {
483 - wp_delete_post( $translated_post->element_id, true );
484 - }
485 - } else {
486 - wp_delete_post( $chart_id, true );
487 - }
488 - } else {
489 - wp_delete_post( $chart_id, true );
490 - }
442 + wp_delete_post( $chart_id, true );
491 443 }
492 444 if ( $is_post ) {
493 445 self::_sendResponse(
494 446 array(
@@ -536,101 +488,47 @@
536 488 *
537 489 * @access public
538 490 */
539 491 public function renderChartPages() {
540 - if ( ! current_user_can( 'edit_posts' ) ) {
541 - wp_die( __( 'You do not have permission to access this page.', 'visualizer' ) );
542 - }
543 -
544 492 defined( 'IFRAME_REQUEST' ) || define( 'IFRAME_REQUEST', 1 );
545 - if ( ! defined( 'ET_BUILDER_PRODUCT_VERSION' ) && function_exists( 'et_get_theme_version' ) ) {
546 - define( 'ET_BUILDER_PRODUCT_VERSION', et_get_theme_version() );
547 - }
548 493 // Set current screen for the render chart.
549 494 set_current_screen( 'visualizer_render_chart' );
550 495 // check chart, if chart not exists, will create new one and redirects to the same page with proper chart id
551 496 $chart_id = isset( $_GET['chart'] ) ? filter_var( $_GET['chart'], FILTER_VALIDATE_INT ) : '';
552 - if ( ! empty( $_POST ) ) {
553 - $_POST = map_deep( $_POST, 'wp_strip_all_tags' );
554 - }
555 - $chart = $chart_id ? get_post( $chart_id ) : null;
556 - if ( ! $chart_id || ! $chart || $chart->post_type !== Visualizer_Plugin::CPT_VISUALIZER ) {
557 - if ( empty( $_GET['lang'] ) || empty( $_GET['parent_chart_id'] ) ) {
558 - $this->deleteOldCharts();
559 - $default_type = isset( $_GET['type'] ) && ! empty( $_GET['type'] ) ? $_GET['type'] : 'line';
560 - $chart_status = Visualizer_Module_Admin::checkChartStatus( $default_type );
561 - if ( ! $chart_status ) {
562 - $default_type = 'line';
563 - }
564 - $source = new Visualizer_Source_Csv( VISUALIZER_ABSPATH . DIRECTORY_SEPARATOR . 'samples' . DIRECTORY_SEPARATOR . $default_type . '.csv' );
565 - $source->fetch();
566 - $chart_id = wp_insert_post(
497 + if ( ! $chart_id || ! ( $chart = get_post( $chart_id ) ) || $chart->post_type !== Visualizer_Plugin::CPT_VISUALIZER ) {
498 + $this->deleteOldCharts();
499 + $default_type = isset( $_GET['type'] ) && ! empty( $_GET['type'] ) ? $_GET['type'] : 'line';
500 + $source = new Visualizer_Source_Csv( VISUALIZER_ABSPATH . DIRECTORY_SEPARATOR . 'samples' . DIRECTORY_SEPARATOR . $default_type . '.csv' );
501 + $source->fetch();
502 + $chart_id = wp_insert_post(
503 + array(
504 + 'post_type' => Visualizer_Plugin::CPT_VISUALIZER,
505 + 'post_title' => 'Visualization',
506 + 'post_author' => get_current_user_id(),
507 + 'post_status' => 'auto-draft',
508 + 'post_content' => $source->getData( get_post_meta( $chart_id, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) ),
509 + )
510 + );
511 + if ( $chart_id && ! is_wp_error( $chart_id ) ) {
512 + add_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_TYPE, $default_type );
513 + add_post_meta( $chart_id, Visualizer_Plugin::CF_DEFAULT_DATA, 1 );
514 + add_post_meta( $chart_id, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() );
515 + add_post_meta( $chart_id, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
516 + add_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_LIBRARY, '' );
517 + add_post_meta(
518 + $chart_id,
519 + Visualizer_Plugin::CF_SETTINGS,
567 520 array(
568 - 'post_type' => Visualizer_Plugin::CPT_VISUALIZER,
569 - 'post_title' => 'Visualization',
570 - 'post_author' => get_current_user_id(),
571 - 'post_status' => 'auto-draft',
572 - 'post_content' => $source->getData( get_post_meta( $chart_id, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) ),
521 + 'focusTarget' => 'datum',
573 522 )
574 523 );
575 - if ( $chart_id && ! is_wp_error( $chart_id ) ) {
576 - add_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_TYPE, $default_type );
577 - add_post_meta( $chart_id, Visualizer_Plugin::CF_DEFAULT_DATA, 1 );
578 - add_post_meta( $chart_id, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() );
579 - add_post_meta( $chart_id, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
580 - add_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_LIBRARY, '' );
581 - add_post_meta(
582 - $chart_id,
583 - Visualizer_Plugin::CF_SETTINGS,
584 - array(
585 - 'focusTarget' => 'datum',
586 - )
587 - );
588 -
589 - do_action( 'visualizer_pro_new_chart_defaults', $chart_id );
590 - }
591 - } else {
592 - $parent_chart_id = filter_var( $_GET['parent_chart_id'], FILTER_VALIDATE_INT );
593 - $success = false;
594 - if ( $parent_chart_id ) {
595 - $parent_chart = get_post( $parent_chart_id );
596 - $success = $parent_chart && $parent_chart->post_type === Visualizer_Plugin::CPT_VISUALIZER;
597 - }
598 - if ( $success ) {
599 - $new_chart_id = wp_insert_post(
600 - array(
601 - 'post_type' => Visualizer_Plugin::CPT_VISUALIZER,
602 - 'post_title' => 'Visualization',
603 - 'post_author' => get_current_user_id(),
604 - 'post_status' => $parent_chart->post_status,
605 - 'post_content' => $parent_chart->post_content,
606 - )
607 - );
608 -
609 - if ( is_wp_error( $new_chart_id ) ) {
610 - do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( 'Error while cloning chart %d = %s', $parent_chart_id, print_r( $new_chart_id, true ) ), 'error', __FILE__, __LINE__ );
611 - } else {
612 - $post_meta = get_post_meta( $parent_chart_id );
613 - $chart_id = $new_chart_id;
614 - foreach ( $post_meta as $key => $value ) {
615 - if ( strpos( $key, 'visualizer-' ) !== false ) {
616 - add_post_meta( $new_chart_id, $key, maybe_unserialize( $value[0] ) );
617 - }
618 - }
619 - }
620 - }
621 524 do_action( 'visualizer_pro_new_chart_defaults', $chart_id );
622 525 }
623 - wp_redirect( esc_url_raw( add_query_arg( 'chart', (int) $chart_id ) ) );
624 -
625 - if ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) {
626 - wp_die();
627 - }
628 - exit();
526 + wp_redirect( add_query_arg( 'chart', (int) $chart_id ) );
527 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
629 528 }
630 529
631 530 $_POST['save_chart_image'] = isset( $_POST['save_chart_image'] ) && 'yes' === $_POST['save_chart_image'] ? true : false;
632 - $_POST['lazy_load_chart'] = isset( $_POST['lazy_load_chart'] ) && 'yes' === $_POST['lazy_load_chart'] ? true : false;
633 531
634 532 if ( isset( $_POST['chart-img'] ) && ! empty( $_POST['chart-img'] ) ) {
635 533 $attachment_id = $this->save_chart_image( $_POST['chart-img'], $chart_id, $_POST['save_chart_image'] );
636 534 if ( $attachment_id ) {
@@ -719,9 +617,9 @@
719 617 default:
720 618 // this should never happen.
721 619 break;
722 620 }
723 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
621 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
724 622 }
725 623
726 624 /**
727 625 * Load code editor assets.
@@ -733,9 +631,9 @@
733 631
734 632 // data tables assets.
735 633 wp_register_script( 'visualizer-datatables', VISUALIZER_ABSURL . 'js/lib/datatables.min.js', array( 'jquery-ui-core' ), Visualizer_Plugin::VERSION );
736 634 wp_register_style( 'visualizer-datatables', VISUALIZER_ABSURL . 'css/lib/datatables.min.css', array(), Visualizer_Plugin::VERSION );
737 - wp_register_style( 'visualizer-jquery-ui', sprintf( '//code.jquery.com/ui/%s/themes/smoothness/jquery-ui.css', $wp_scripts->registered['jquery-ui-core']->ver ), array( 'visualizer-datatables' ), Visualizer_Plugin::VERSION );
635 + wp_register_style( 'visualizer-jquery-ui', sprintf( '//ajax.googleapis.com/ajax/libs/jqueryui/%s/themes/smoothness/jquery-ui.css', $wp_scripts->registered['jquery-ui-core']->ver ), array( 'visualizer-datatables' ), Visualizer_Plugin::VERSION );
738 636 wp_enqueue_script( 'visualizer-datatables' );
739 637 wp_enqueue_style( 'visualizer-jquery-ui' );
740 638
741 639 if ( ! Visualizer_Module::is_pro() ) {
@@ -751,9 +649,9 @@
751 649 wp_register_script( 'visualizer-codemirror-matchbrackets', '//codemirror.net/addon/edit/matchbrackets.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
752 650 wp_register_script( 'visualizer-codemirror-closebrackets', '//codemirror.net/addon/edit/closebrackets.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
753 651 wp_register_script( 'visualizer-codemirror-sql', '//codemirror.net/mode/sql/sql.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
754 652 wp_register_script( 'visualizer-codemirror-sql-hint', '//codemirror.net/addon/hint/sql-hint.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
755 - wp_register_script( 'visualizer-codemirror-hint', '//codemirror.net/addon/hint/show-hint.js', array( 'visualizer-codemirror-sql', 'visualizer-codemirror-sql-hint', 'visualizer-codemirror-placeholder', 'visualizer-codemirror-matchbrackets', 'visualizer-codemirror-closebrackets' ), Visualizer_Plugin::VERSION );
653 + wp_register_script( 'visualizer-codemirror-hint', '//codemirror.net/addon/hint/show-hint.js', array( 'visualizer-codemirror-sql', 'visualizer-codemirror-sql-hint', 'visualizer-codemirror-placeholder', 'visualizer-codemirror-matchbrackets', 'visualizer-codemirror-closebrackets' ), Visualizer_Plugin::VERSION );
756 654 wp_register_style( 'visualizer-codemirror-core', '//codemirror.net/lib/codemirror.css', array(), Visualizer_Plugin::VERSION );
757 655 wp_register_style( 'visualizer-codemirror-hint', '//codemirror.net/addon/hint/show-hint.css', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
758 656
759 657 wp_enqueue_script( 'visualizer-codemirror-hint' );
@@ -767,9 +665,9 @@
767 665 'lineWrapping' => true,
768 666 'dragDrop' => false,
769 667 'matchBrackets' => true,
770 668 'autoCloseBrackets' => true,
771 - 'extraKeys' => array( 'Shift-Space' => 'autocomplete' ),
669 + 'extraKeys' => array( 'Ctrl-Space' => 'autocomplete' ),
772 670 'hintOptions' => array( 'tables' => $table_col_mapping ),
773 671 ),
774 672 )
775 673 );
@@ -803,12 +701,9 @@
803 701 update_option( 'visualizer-map-api-key', $_POST['map_api_key'] );
804 702 }
805 703
806 704 if ( $_SERVER['REQUEST_METHOD'] === 'POST' && isset( $_GET['nonce'] ) && wp_verify_nonce( $_GET['nonce'] ) ) {
807 - $is_canceled = isset( $_POST['cancel'] ) && 1 === intval( $_POST['cancel'] );
808 - $is_newly_created = $this->_chart->post_status === 'auto-draft';
809 -
810 - if ( $is_newly_created && ! $is_canceled ) {
705 + if ( $this->_chart->post_status === 'auto-draft' ) {
811 706 $this->_chart->post_status = 'publish';
812 707
813 708 // ensure that a revision is not created. If a revision is created it will have the proper data and the parent of the revision will have default data.
814 709 // we do not want any difference in data so disable revisions temporarily.
@@ -816,15 +711,10 @@
816 711
817 712 wp_update_post( $this->_chart->to_array() );
818 713 }
819 714 // save meta data only when it is NOT being canceled.
820 - if ( ! $is_canceled ) {
821 - $post_settings = $_POST;
822 - $existing = get_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SETTINGS, true );
823 - if ( isset( $existing['colors'] ) && is_array( $existing['colors'] ) && ! isset( $post_settings['colors'] ) ) {
824 - $post_settings['colors'] = $existing['colors'];
825 - }
826 - update_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SETTINGS, $post_settings );
715 + if ( ! ( isset( $_POST['cancel'] ) && 1 === intval( $_POST['cancel'] ) ) ) {
716 + update_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SETTINGS, $_POST );
827 717
828 718 // we will keep a parameter called 'internal_title' that will be set to the given title or, if empty, the chart ID
829 719 // this will help in searching with the chart id.
830 720 $settings = get_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SETTINGS, true );
@@ -838,14 +728,8 @@
838 728 if ( empty( $title ) ) {
839 729 $title = $this->_chart->ID;
840 730 }
841 731 $settings['internal_title'] = $title;
842 - $settings_label = isset( $settings['pieResidueSliceLabel'] ) ? $settings['pieResidueSliceLabel'] : '';
843 - if ( empty( $settings_label ) ) {
844 - $settings['pieResidueSliceLabel'] = esc_html__( 'Other', 'visualizer' );
845 - } else {
846 - $settings['pieResidueSliceLabel'] = $settings_label;
847 - }
848 732 update_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SETTINGS, $settings );
849 733 }
850 734 $render = new Visualizer_Render_Page_Send();
851 735 $render->text = sprintf( '[visualizer id="%d"]', $this->_chart->ID );
@@ -871,9 +755,8 @@
871 755 wp_enqueue_style( 'visualizer-frame' );
872 756 wp_enqueue_script( 'visualizer-preview' );
873 757 wp_enqueue_script( 'visualizer-chosen' );
874 758 wp_enqueue_script( 'visualizer-render' );
875 - wp_enqueue_code_editor( array( 'type' => 'application/json' ) );
876 759
877 760 if ( Visualizer_Module::can_show_feature( 'simple-editor' ) ) {
878 761 wp_enqueue_script( 'visualizer-editor-simple' );
879 762 wp_localize_script(
@@ -881,10 +764,12 @@
881 764 'visualizer1',
882 765 array(
883 766 'ajax' => array(
884 767 'url' => admin_url( 'admin-ajax.php' ),
885 - 'nonces' => array(),
886 - 'actions' => array(),
768 + 'nonces' => array(
769 + ),
770 + 'actions' => array(
771 + ),
887 772 ),
888 773 )
889 774 );
890 775 }
@@ -895,15 +780,13 @@
895 780 'visualizer-render',
896 781 'visualizer',
897 782 array(
898 783 'l10n' => array(
899 - 'invalid_source' => esc_html__( 'The URL you entered is invalid. Please enter a valid URL.', 'visualizer' ),
900 - 'loading' => esc_html__( 'Loading...', 'visualizer' ),
901 - 'json_error' => esc_html__( 'An error occured in fetching data.', 'visualizer' ),
902 - 'select_columns' => esc_html__( 'Please select a few columns to include in the chart.', 'visualizer' ),
903 - 'save_settings' => __( 'You have modified the chart\'s settings. To modify the source/data again, you must save this chart and reopen it for editing. If you continue without saving the chart, you may lose your changes.', 'visualizer' ),
904 - 'copied' => __( 'The data has been copied to your clipboard. Hit Ctrl-V/Cmd-V in your spreadsheet editor to paste the data.', 'visualizer' ),
905 - 'invalid_format' => esc_html__( 'This format pattern is not supported in the series settings field. Use the Manual Configuration option instead.', 'visualizer' ),
784 + 'invalid_source' => esc_html__( 'You have entered an invalid URL. Please provide a valid URL.', 'visualizer' ),
785 + 'loading' => esc_html__( 'Loading...', 'visualizer' ),
786 + 'json_error' => esc_html__( 'An error occured in fetching data.', 'visualizer' ),
787 + 'select_columns' => esc_html__( 'Please select a few columns to include in the chart.', 'visualizer' ),
788 + 'save_settings' => __( 'You have modified the chart\'s settings. To modify the source/data again, you must save this chart and reopen it for editing. If you continue without saving the chart, you may lose your changes.', 'visualizer' ),
906 789 ),
907 790 'charts' => array(
908 791 'canvas' => $data,
909 792 'id' => $this->_chart->ID,
@@ -934,9 +817,8 @@
934 817 'page_type' => 'chart',
935 818 'json_tag_separator' => Visualizer_Source_Json::TAG_SEPARATOR,
936 819 'json_tag_separator_view' => Visualizer_Source_Json::TAG_SEPARATOR_VIEW,
937 820 'is_front' => false,
938 - 'rest_base' => get_rest_url( null, 'wc/v3/reports/' ),
939 821 )
940 822 );
941 823
942 824 $render = new Visualizer_Render_Page_Data();
@@ -947,10 +829,11 @@
947 829 if ( filter_input( INPUT_GET, 'library', FILTER_VALIDATE_BOOLEAN ) ) {
948 830 $render->button = filter_input( INPUT_GET, 'action' ) === Visualizer_Plugin::ACTION_EDIT_CHART
949 831 ? esc_html__( 'Save Chart', 'visualizer' )
950 832 : esc_html__( 'Create Chart', 'visualizer' );
951 -
952 - $render->cancel_button = esc_html__( 'Cancel', 'visualizer' );
833 + if ( filter_input( INPUT_GET, 'action' ) === Visualizer_Plugin::ACTION_EDIT_CHART ) {
834 + $render->cancel_button = esc_html__( 'Cancel', 'visualizer' );
835 + }
953 836 } else {
954 837 $render->button = esc_attr__( 'Insert Chart', 'visualizer' );
955 838 }
956 839
@@ -973,12 +856,12 @@
973 856 * @access private
974 857 */
975 858 private function _handleTypesPage() {
976 859 // process post request
977 - if ( $_SERVER['REQUEST_METHOD'] === 'POST' && wp_verify_nonce( filter_input( INPUT_POST, 'nonce' ), 'visualizer-upload-data' ) ) {
860 + if ( $_SERVER['REQUEST_METHOD'] === 'POST' && wp_verify_nonce( filter_input( INPUT_POST, 'nonce' ) ) ) {
978 861 $type = filter_input( INPUT_POST, 'type' );
979 862 $library = filter_input( INPUT_POST, 'chart-library' );
980 - if ( Visualizer_Module_Admin::checkChartStatus( $type ) ) {
863 + if ( in_array( $type, Visualizer_Plugin::getChartTypes(), true ) ) {
981 864 if ( empty( $library ) ) {
982 865 // library cannot be empty.
983 866 do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, 'Chart library empty while creating the chart! Aborting...', 'error', __FILE__, __LINE__ );
984 867 return;
@@ -999,9 +882,9 @@
999 882 Visualizer_Module_Utility::set_defaults( $this->_chart );
1000 883
1001 884 // redirect to next tab
1002 885 // changed by Ash/Upwork
1003 - wp_redirect( esc_url_raw( add_query_arg( 'tab', 'settings' ) ) );
886 + wp_redirect( add_query_arg( 'tab', 'settings' ) );
1004 887
1005 888 return;
1006 889 }
1007 890 }
@@ -1030,80 +913,8 @@
1030 913 * Processes the CSV that is sent in the request as a string.
1031 914 *
1032 915 * @since 3.2.0
1033 916 */
1034 - /**
1035 - * Determines whether a remote URL serves an XLSX file.
1036 - *
1037 - * Used as a fallback when the URL path has no recognisable file extension
1038 - * (e.g. SharePoint, signed S3 URLs, or "download?id=…" endpoints).
1039 - *
1040 - * Uses wp_safe_remote_get() to block requests to private/loopback addresses,
1041 - * and streams the response to a temp file so no body data is held in memory
1042 - * regardless of whether the server honours the Range header.
1043 - *
1044 - * The check relies on the ZIP magic number (PK\x03\x04) that every XLSX
1045 - * file begins with, making it immune to misleading Content-Type headers
1046 - * such as application/octet-stream. Content-Type is used as a last-resort
1047 - * fallback only when the temp file is empty (e.g. a HEAD-only server).
1048 - *
1049 - * @access private
1050 - * @param string $url The remote URL to probe.
1051 - * @return bool TRUE if the file appears to be XLSX, FALSE otherwise.
1052 - */
1053 - private static function _url_is_xlsx( $url ) {
1054 - $tmpfile = wp_tempnam( 'visualizer_xlsx_probe' );
1055 - if ( ! $tmpfile ) {
1056 - return false;
1057 - }
1058 -
1059 - $response = wp_safe_remote_get(
1060 - $url,
1061 - array(
1062 - 'timeout' => 10,
1063 - 'user-agent' => 'WordPress/' . get_bloginfo( 'version' ),
1064 - 'headers' => array( 'Range' => 'bytes=0-3' ),
1065 - 'stream' => true,
1066 - 'filename' => $tmpfile,
1067 - )
1068 - );
1069 -
1070 - if ( is_wp_error( $response ) ) {
1071 - @unlink( $tmpfile ); // phpcs:ignore WordPress.PHP.NoSilencedErrors
1072 - return false;
1073 - }
1074 -
1075 - $magic = '';
1076 - // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fopen
1077 - $fh = @fopen( $tmpfile, 'rb' ); // phpcs:ignore WordPress.PHP.NoSilencedErrors
1078 - if ( $fh ) {
1079 - $magic = fread( $fh, 4 ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fread
1080 - fclose( $fh ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose
1081 - }
1082 - @unlink( $tmpfile ); // phpcs:ignore WordPress.PHP.NoSilencedErrors
1083 -
1084 - if ( strlen( $magic ) >= 4 ) {
1085 - // XLSX (and all ZIP-based Office formats) start with PK\x03\x04.
1086 - return $magic === "PK\x03\x04";
1087 - }
1088 -
1089 - // Last resort: server returned an empty body (e.g. ignored Range and
1090 - // returned only headers). Check Content-Type from the same response.
1091 - // application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
1092 - return false !== strpos(
1093 - wp_remote_retrieve_header( $response, 'content-type' ),
1094 - 'spreadsheetml'
1095 - );
1096 - }
1097 -
1098 - /**
1099 - * Parses a raw CSV string or editor payload and returns a source object.
1100 - *
1101 - * @access private
1102 - * @param string $data The raw CSV data string.
1103 - * @param string $editor_type The editor type ('text' or 'tabular').
1104 - * @return Visualizer_Source|null The populated source object, or null on failure.
1105 - */
1106 917 private function handleCSVasString( $data, $editor_type ) {
1107 918 $source = null;
1108 919
1109 920 switch ( $editor_type ) {
@@ -1118,9 +929,9 @@
1118 929 continue;
1119 930 }
1120 931 $row = explode( ',', $row );
1121 932 $row = array_map(
1122 - function ( $r ) {
933 + function( $r ) {
1123 934 return '' === $r ? ' ' : $r;
1124 935 },
1125 936 $row
1126 937 );
@@ -1169,9 +980,9 @@
1169 980 foreach ( $types as $type ) {
1170 981 if ( empty( $type ) ) {
1171 982 $exclude[] = $index;
1172 983 }
1173 - ++$index;
984 + $index++;
1174 985 }
1175 986
1176 987 // when N headers are being renamed, the number of headers increases by N
1177 988 // because of the way datatable duplicates header information
@@ -1231,13 +1042,9 @@
1231 1042 // otherwise, assume this is a normal web request.
1232 1043 $can_die = ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE );
1233 1044
1234 1045 // validate nonce
1235 - if (
1236 - ! isset( $_GET['nonce'] ) ||
1237 - ! wp_verify_nonce( $_GET['nonce'], 'visualizer-upload-data' ) ||
1238 - ! current_user_can( 'edit_posts' )
1239 - ) {
1046 + if ( ! isset( $_GET['nonce'] ) || ! wp_verify_nonce( $_GET['nonce'] ) ) {
1240 1047 if ( ! $can_die ) {
1241 1048 return;
1242 1049 }
1243 1050 status_header( 403 );
@@ -1246,15 +1053,9 @@
1246 1053
1247 1054 // check chart, if chart exists
1248 1055 // do not use filter_input as it does not work for phpunit test cases, use filter_var instead
1249 1056 $chart_id = isset( $_GET['chart'] ) ? filter_var( $_GET['chart'], FILTER_VALIDATE_INT ) : '';
1250 - $chart = $chart_id ? get_post( $chart_id ) : null;
1251 - if (
1252 - ! $chart_id ||
1253 - ! $chart ||
1254 - $chart->post_type !== Visualizer_Plugin::CPT_VISUALIZER ||
1255 - ! current_user_can( 'edit_post', $chart_id )
1256 - ) {
1057 + if ( ! $chart_id || ! ( $chart = get_post( $chart_id ) ) || $chart->post_type !== Visualizer_Plugin::CPT_VISUALIZER ) {
1257 1058 if ( ! $can_die ) {
1258 1059 return;
1259 1060 }
1260 1061 status_header( 400 );
@@ -1295,30 +1096,16 @@
1295 1096 delete_post_meta( $chart_id, Visualizer_Plugin::CF_EDITABLE_TABLE );
1296 1097
1297 1098 $source = null;
1298 1099 $render = new Visualizer_Render_Page_Update();
1299 -
1300 - $remote_data = false;
1301 - if ( isset( $_POST['remote_data'] ) && function_exists( 'wp_http_validate_url' ) ) {
1302 - $remote_data = wp_http_validate_url( $_POST['remote_data'] );
1303 - }
1304 - if ( false !== $remote_data ) {
1305 - $remote_ext = strtolower( pathinfo( parse_url( $remote_data, PHP_URL_PATH ), PATHINFO_EXTENSION ) );
1306 - if ( 'xlsx' === $remote_ext || ( 'csv' !== $remote_ext && self::_url_is_xlsx( $remote_data ) ) ) {
1307 - $source = new Visualizer_Source_Xlsx_Remote( $remote_data );
1308 - } else {
1309 - $source = new Visualizer_Source_Csv_Remote( $remote_data );
1310 - }
1100 + if ( isset( $_POST['remote_data'] ) && filter_var( $_POST['remote_data'], FILTER_VALIDATE_URL ) ) {
1101 + $source = new Visualizer_Source_Csv_Remote( $_POST['remote_data'] );
1311 1102 if ( isset( $_POST['vz-import-time'] ) ) {
1312 - apply_filters( 'visualizer_pro_chart_schedule', $chart_id, $remote_data, $_POST['vz-import-time'] );
1103 + apply_filters( 'visualizer_pro_chart_schedule', $chart_id, $_POST['remote_data'], $_POST['vz-import-time'] );
1313 1104 }
1314 - } elseif ( isset( $_FILES['local_data'] ) && $_FILES['local_data']['error'] === 0 ) {
1315 - $local_ext = strtolower( pathinfo( isset( $_FILES['local_data']['name'] ) ? $_FILES['local_data']['name'] : '', PATHINFO_EXTENSION ) );
1316 - if ( 'xlsx' === $local_ext ) {
1317 - $source = new Visualizer_Source_Xlsx( $_FILES['local_data']['tmp_name'] );
1318 - } else {
1319 - $source = new Visualizer_Source_Csv( $_FILES['local_data']['tmp_name'] );
1320 - }
1105 + // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
1106 + } elseif ( isset( $_FILES['local_data'] ) && $_FILES['local_data']['error'] == 0 ) {
1107 + $source = new Visualizer_Source_Csv( $_FILES['local_data']['tmp_name'] );
1321 1108 } elseif ( isset( $_POST['chart_data'] ) && strlen( $_POST['chart_data'] ) > 0 ) {
1322 1109 $source = $this->handleCSVasString( $_POST['chart_data'], $_POST['editor-type'] );
1323 1110 update_post_meta( $chart_id, Visualizer_Plugin::CF_EDITOR, $_POST['editor-type'] );
1324 1111 } elseif ( isset( $_POST['table_data'] ) && 'yes' === $_POST['table_data'] ) {
@@ -1325,10 +1112,10 @@
1325 1112 $source = $this->handleTabularData();
1326 1113 update_post_meta( $chart_id, Visualizer_Plugin::CF_EDITOR, $_POST['editor-type'] );
1327 1114 } else {
1328 1115 do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( 'CSV file with chart data was not uploaded for chart %d.', $chart_id ), 'error', __FILE__, __LINE__ );
1329 - $render->message = esc_html__( 'No CSV file was received. Select a file and try uploading again.', 'visualizer' );
1330 - update_post_meta( $chart_id, Visualizer_Plugin::CF_ERROR, esc_html__( 'No CSV file was received. Select a file and try uploading again.', 'visualizer' ) );
1116 + $render->message = esc_html__( 'CSV file with chart data was not uploaded. Please try again.', 'visualizer' );
1117 + update_post_meta( $chart_id, Visualizer_Plugin::CF_ERROR, esc_html__( 'CSV file with chart data was not uploaded. Please try again.', 'visualizer' ) );
1331 1118 }
1332 1119
1333 1120 do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( 'Uploaded data for chart %d with source %s', $chart_id, print_r( $source, true ) ), 'debug', __FILE__, __LINE__ );
1334 1121
@@ -1349,9 +1136,8 @@
1349 1136 if ( $populate ) {
1350 1137 $chart->post_content = $content;
1351 1138 }
1352 1139 wp_update_post( $chart->to_array() );
1353 -
1354 1140 update_post_meta( $chart->ID, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
1355 1141 update_post_meta( $chart->ID, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() );
1356 1142 update_post_meta( $chart->ID, Visualizer_Plugin::CF_DEFAULT_DATA, 0 );
1357 1143
@@ -1359,17 +1145,8 @@
1359 1145
1360 1146 Visualizer_Module_Utility::set_defaults( $chart, null );
1361 1147
1362 1148 $settings = get_post_meta( $chart->ID, Visualizer_Plugin::CF_SETTINGS, true );
1363 - if ( isset( $settings['series'] ) && ! ( count( $settings['series'] ) - count( $source->getSeries() ) > 1 ) ) {
1364 - $diff_total_series = abs( count( $settings['series'] ) - count( $source->getSeries() ) );
1365 - if ( $diff_total_series ) {
1366 - foreach ( range( 1, $diff_total_series ) as $k => $diff_series ) {
1367 - $settings['series'][] = end( $settings['series'] );
1368 - }
1369 - update_post_meta( $chart->ID, Visualizer_Plugin::CF_SETTINGS, $settings );
1370 - }
1371 - }
1372 1149
1373 1150 $render->id = $chart->ID;
1374 1151 $render->data = json_encode( $source->getRawData( get_post_meta( $chart->ID, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) ) );
1375 1152 $render->series = json_encode( $source->getSeries() );
@@ -1376,9 +1153,9 @@
1376 1153 $render->settings = json_encode( $settings );
1377 1154 } else {
1378 1155 $error = $source->get_error();
1379 1156 if ( empty( $error ) ) {
1380 - $error = esc_html__( 'The CSV file couldn\'t be read. Check that it\'s properly formatted and try again.', 'visualizer' );
1157 + $error = esc_html__( 'CSV file is broken or invalid. Please try again.', 'visualizer' );
1381 1158 }
1382 1159 $render->message = $error;
1383 1160 do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( '%s for chart %d.', $error, $chart_id ), 'error', __FILE__, __LINE__ );
1384 1161 update_post_meta( $chart_id, Visualizer_Plugin::CF_ERROR, $error );
@@ -1389,9 +1166,9 @@
1389 1166 $render->render();
1390 1167 if ( ! $can_die ) {
1391 1168 return;
1392 1169 }
1393 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1170 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1394 1171 }
1395 1172
1396 1173 /**
1397 1174 * Clones the chart.
@@ -1430,26 +1207,23 @@
1430 1207 if ( strpos( $key, 'visualizer-' ) !== false ) {
1431 1208 add_post_meta( $new_chart_id, $key, maybe_unserialize( $value[0] ) );
1432 1209 }
1433 1210 }
1434 - $redirect = esc_url(
1435 - add_query_arg(
1436 - array(
1437 - 'page' => 'visualizer',
1438 - 'type' => filter_input( INPUT_GET, 'type' ),
1439 - 'vaction' => false,
1440 - ),
1441 - admin_url( 'admin.php' )
1211 + $redirect = add_query_arg(
1212 + array(
1213 + 'page' => 'visualizer',
1214 + 'type' => filter_input( INPUT_GET, 'type' ),
1215 + 'vaction' => false,
1442 1216 ),
1443 - null,
1444 - 'db'
1217 + admin_url( 'admin.php' )
1445 1218 );
1446 1219 }
1447 1220 }
1448 1221
1449 - if ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) {
1222 + if ( defined( 'WP_TESTS_DOMAIN' ) ) {
1450 1223 wp_die();
1451 1224 }
1225 +
1452 1226 wp_redirect( $redirect );
1453 1227 exit;
1454 1228 }
1455 1229
@@ -1480,9 +1254,9 @@
1480 1254 }
1481 1255 }
1482 1256 }
1483 1257
1484 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1258 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1485 1259 }
1486 1260
1487 1261 /**
1488 1262 * Handles chart data page.
@@ -1506,11 +1280,10 @@
1506 1280 'visualizer-render',
1507 1281 'visualizer',
1508 1282 array(
1509 1283 'l10n' => array(
1510 - 'invalid_source' => esc_html__( 'The URL you entered is invalid. Please enter a valid URL.', 'visualizer' ),
1511 - 'loading' => esc_html__( 'Loading...', 'visualizer' ),
1512 - 'invalid_format' => esc_html__( 'This format pattern is not supported in the series settings field. To display percentages, use the Manual Configuration option instead.', 'visualizer' ),
1284 + 'invalid_source' => esc_html__( 'You have entered an invalid URL. Please provide a valid URL.', 'visualizer' ),
1285 + 'loading' => esc_html__( 'Loading...', 'visualizer' ),
1513 1286 ),
1514 1287 'charts' => array(
1515 1288 'canvas' => $data,
1516 1289 ),
@@ -1536,24 +1309,12 @@
1536 1309 */
1537 1310 public function getQueryData() {
1538 1311 check_ajax_referer( Visualizer_Plugin::ACTION_FETCH_DB_DATA . Visualizer_Plugin::VERSION, 'security' );
1539 1312
1540 - if ( ! current_user_can( 'administrator' ) ) {
1541 - wp_send_json_error( array( 'msg' => __( 'Action not allowed for this user.', 'visualizer' ) ) );
1542 - }
1543 - if ( ! is_super_admin() ) {
1544 - wp_send_json_error( array( 'msg' => __( 'Action not allowed for this user.', 'visualizer' ) ) );
1545 - }
1546 -
1547 - if ( ! Visualizer_Module::is_pro() ) {
1548 - wp_send_json_error( array( 'msg' => __( 'Feature is not available.', 'visualizer' ) ) );
1549 - }
1550 -
1551 1313 $params = wp_parse_args( $_POST['params'] );
1552 1314 $chart_id = filter_var( $params['chart_id'], FILTER_VALIDATE_INT );
1553 - $query = trim( $params['query'], ';' );
1554 1315
1555 - $source = new Visualizer_Source_Query( stripslashes( $query ), $chart_id, $params );
1316 + $source = new Visualizer_Source_Query( stripslashes( $params['query'] ), $chart_id, $params );
1556 1317 $html = $source->fetch( true );
1557 1318 $error = $source->get_error();
1558 1319 if ( ! empty( $error ) ) {
1559 1320 wp_send_json_error( array( 'msg' => $error ) );
@@ -1568,19 +1329,8 @@
1568 1329 */
1569 1330 public function saveQuery() {
1570 1331 check_ajax_referer( Visualizer_Plugin::ACTION_SAVE_DB_QUERY . Visualizer_Plugin::VERSION, 'security' );
1571 1332
1572 - if ( ! current_user_can( 'administrator' ) ) {
1573 - wp_send_json_error( array( 'msg' => __( 'Action not allowed for this user.', 'visualizer' ) ) );
1574 - }
1575 - if ( ! is_super_admin() ) {
1576 - wp_send_json_error( array( 'msg' => __( 'Action not allowed for this user.', 'visualizer' ) ) );
1577 - }
1578 -
1579 - if ( ! Visualizer_Module::is_pro() ) {
1580 - wp_send_json_error( array( 'msg' => __( 'Feature is not available.', 'visualizer' ) ) );
1581 - }
1582 -
1583 1333 $chart_id = filter_input(
1584 1334 INPUT_GET,
1585 1335 'chart',
1586 1336 FILTER_VALIDATE_INT,
@@ -1609,14 +1359,13 @@
1609 1359
1610 1360 $render = new Visualizer_Render_Page_Update();
1611 1361 if ( $chart_id ) {
1612 1362 $params = wp_parse_args( $_POST['params'] );
1613 - $query = trim( $params['query'], ';' );
1614 - $source = new Visualizer_Source_Query( stripslashes( $query ), $chart_id, $params );
1363 + $source = new Visualizer_Source_Query( stripslashes( $params['query'] ), $chart_id, $params );
1615 1364 $source->fetch( false );
1616 1365 $error = $source->get_error();
1617 1366 if ( empty( $error ) ) {
1618 - update_post_meta( $chart_id, Visualizer_Plugin::CF_DB_QUERY, stripslashes( $query ) );
1367 + update_post_meta( $chart_id, Visualizer_Plugin::CF_DB_QUERY, stripslashes( $params['query'] ) );
1619 1368 update_post_meta( $chart_id, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() );
1620 1369 update_post_meta( $chart_id, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
1621 1370 update_post_meta( $chart_id, Visualizer_Plugin::CF_DB_SCHEDULE, $hours );
1622 1371 update_post_meta( $chart_id, Visualizer_Plugin::CF_DEFAULT_DATA, 0 );
@@ -1645,9 +1394,9 @@
1645 1394 }
1646 1395 }
1647 1396 $render->render();
1648 1397 if ( ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE ) ) {
1649 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1398 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1650 1399 }
1651 1400 }
1652 1401
1653 1402
@@ -1672,9 +1421,9 @@
1672 1421
1673 1422 $hours = filter_input(
1674 1423 INPUT_POST,
1675 1424 'refresh',
1676 - FILTER_VALIDATE_FLOAT,
1425 + FILTER_VALIDATE_INT,
1677 1426 array(
1678 1427 'options' => array(
1679 1428 'min_range' => -1,
1680 1429 'max_range' => apply_filters( 'visualizer_is_business', false ) ? PHP_INT_MAX : -1,
@@ -1681,9 +1430,9 @@
1681 1430 ),
1682 1431 )
1683 1432 );
1684 1433
1685 - if ( ! is_numeric( $hours ) ) {
1434 + if ( 0 !== $hours && empty( $hours ) ) {
1686 1435 $hours = -1;
1687 1436 }
1688 1437
1689 1438 do_action( 'visualizer_save_filter', $chart_id, $hours );
@@ -1688,9 +1437,9 @@
1688 1437
1689 1438 do_action( 'visualizer_save_filter', $chart_id, $hours );
1690 1439
1691 1440 if ( ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE ) ) {
1692 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1441 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1693 1442 }
1694 1443 }
1695 1444
1696 1445 /**
@@ -1726,12 +1475,8 @@
1726 1475 // Save the image in the uploads directory.
1727 1476 require_once ABSPATH . '/wp-admin/includes/file.php';
1728 1477 \WP_Filesystem();
1729 1478 global $wp_filesystem;
1730 - if ( ! is_a( $wp_filesystem, 'WP_Filesystem_Base' ) ) {
1731 - $creds = request_filesystem_credentials( site_url() );
1732 - wp_filesystem( $creds );
1733 - }
1734 1479 $upload_file = $wp_filesystem->put_contents( $upload_path . $hashed_filename, $decoded );
1735 1480
1736 1481 // Insert new chart image.
1737 1482 $attachment = array(