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 -333 4.0.33.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 );
@@ -258,16 +245,8 @@
258 245 if ( ! empty( $params['paging'] ) ) {
259 246 add_post_meta( $chart->ID, Visualizer_Plugin::CF_JSON_PAGING, $params['paging'] );
260 247 }
261 248
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 249 $time = filter_input(
271 250 INPUT_POST,
272 251 'time',
273 252 FILTER_VALIDATE_INT,
@@ -295,9 +274,9 @@
295 274 $render->data = json_encode( $source->getRawData( get_post_meta( $chart_id, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) ) );
296 275 $render->series = json_encode( $source->getSeries() );
297 276 $render->render();
298 277
299 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
278 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
300 279 }
301 280
302 281
303 282 /**
@@ -373,13 +352,13 @@
373 352 * @since 1.0.0
374 353 *
375 354 * @access private
376 355 *
377 - * @param WP_Post|null $chart The chart object.
356 + * @param WP_Post $chart The chart object.
378 357 *
379 358 * @return array The array of chart data.
380 359 */
381 - private function _getChartArray( $chart = null ) {
360 + private function _getChartArray( WP_Post $chart = null ) {
382 361 if ( is_null( $chart ) ) {
383 362 $chart = $this->_chart;
384 363 }
385 364 $type = get_post_meta( $chart->ID, Visualizer_Plugin::CF_CHART_TYPE, true );
@@ -401,13 +380,8 @@
401 380 }
402 381
403 382 $date_formats = Visualizer_Source::get_date_formats_if_exists( $series, $data );
404 383
405 - $code = '';
406 - if ( 'd3' === $library ) {
407 - $code = get_post_meta( $chart->ID, Visualizer_Module_AIBuilder::CF_D3_CODE, true );
408 - }
409 -
410 384 return array(
411 385 'type' => $type,
412 386 'series' => $series,
413 387 'settings' => $settings,
@@ -412,9 +386,8 @@
412 386 'series' => $series,
413 387 'settings' => $settings,
414 388 'data' => $data,
415 389 'library' => $library,
416 - 'code' => $code,
417 390 'css' => $css,
418 391 'date_formats' => $date_formats,
419 392 );
420 393 }
@@ -431,9 +404,9 @@
431 404 public static function _sendResponse( $results ) {
432 405 header( 'Content-type: application/json' );
433 406 nocache_headers();
434 407 echo json_encode( $results );
435 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
408 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
436 409 }
437 410
438 411 /**
439 412 * Deletes a chart from database.
@@ -465,22 +438,9 @@
465 438 $success = $chart && $chart->post_type === Visualizer_Plugin::CPT_VISUALIZER;
466 439 }
467 440 }
468 441 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 - }
442 + wp_delete_post( $chart_id, true );
483 443 }
484 444 if ( $is_post ) {
485 445 self::_sendResponse(
486 446 array(
@@ -528,101 +488,47 @@
528 488 *
529 489 * @access public
530 490 */
531 491 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 492 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 493 // Set current screen for the render chart.
541 494 set_current_screen( 'visualizer_render_chart' );
542 495 // check chart, if chart not exists, will create new one and redirects to the same page with proper chart id
543 496 $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(
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,
559 520 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 ) ),
521 + 'focusTarget' => 'datum',
565 522 )
566 523 );
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 524 do_action( 'visualizer_pro_new_chart_defaults', $chart_id );
614 525 }
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();
526 + wp_redirect( add_query_arg( 'chart', (int) $chart_id ) );
527 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
621 528 }
622 529
623 530 $_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 531
626 532 if ( isset( $_POST['chart-img'] ) && ! empty( $_POST['chart-img'] ) ) {
627 533 $attachment_id = $this->save_chart_image( $_POST['chart-img'], $chart_id, $_POST['save_chart_image'] );
628 534 if ( $attachment_id ) {
@@ -711,9 +617,9 @@
711 617 default:
712 618 // this should never happen.
713 619 break;
714 620 }
715 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
621 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
716 622 }
717 623
718 624 /**
719 625 * Load code editor assets.
@@ -725,9 +631,9 @@
725 631
726 632 // data tables assets.
727 633 wp_register_script( 'visualizer-datatables', VISUALIZER_ABSURL . 'js/lib/datatables.min.js', array( 'jquery-ui-core' ), Visualizer_Plugin::VERSION );
728 634 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 );
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 );
730 636 wp_enqueue_script( 'visualizer-datatables' );
731 637 wp_enqueue_style( 'visualizer-jquery-ui' );
732 638
733 639 if ( ! Visualizer_Module::is_pro() ) {
@@ -743,9 +649,9 @@
743 649 wp_register_script( 'visualizer-codemirror-matchbrackets', '//codemirror.net/addon/edit/matchbrackets.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
744 650 wp_register_script( 'visualizer-codemirror-closebrackets', '//codemirror.net/addon/edit/closebrackets.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
745 651 wp_register_script( 'visualizer-codemirror-sql', '//codemirror.net/mode/sql/sql.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
746 652 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 );
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 );
748 654 wp_register_style( 'visualizer-codemirror-core', '//codemirror.net/lib/codemirror.css', array(), Visualizer_Plugin::VERSION );
749 655 wp_register_style( 'visualizer-codemirror-hint', '//codemirror.net/addon/hint/show-hint.css', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
750 656
751 657 wp_enqueue_script( 'visualizer-codemirror-hint' );
@@ -759,9 +665,9 @@
759 665 'lineWrapping' => true,
760 666 'dragDrop' => false,
761 667 'matchBrackets' => true,
762 668 'autoCloseBrackets' => true,
763 - 'extraKeys' => array( 'Shift-Space' => 'autocomplete' ),
669 + 'extraKeys' => array( 'Ctrl-Space' => 'autocomplete' ),
764 670 'hintOptions' => array( 'tables' => $table_col_mapping ),
765 671 ),
766 672 )
767 673 );
@@ -795,12 +701,9 @@
795 701 update_option( 'visualizer-map-api-key', $_POST['map_api_key'] );
796 702 }
797 703
798 704 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 ) {
705 + if ( $this->_chart->post_status === 'auto-draft' ) {
803 706 $this->_chart->post_status = 'publish';
804 707
805 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.
806 709 // we do not want any difference in data so disable revisions temporarily.
@@ -808,15 +711,10 @@
808 711
809 712 wp_update_post( $this->_chart->to_array() );
810 713 }
811 714 // 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 );
715 + if ( ! ( isset( $_POST['cancel'] ) && 1 === intval( $_POST['cancel'] ) ) ) {
716 + update_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SETTINGS, $_POST );
819 717
820 718 // we will keep a parameter called 'internal_title' that will be set to the given title or, if empty, the chart ID
821 719 // this will help in searching with the chart id.
822 720 $settings = get_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SETTINGS, true );
@@ -830,14 +728,8 @@
830 728 if ( empty( $title ) ) {
831 729 $title = $this->_chart->ID;
832 730 }
833 731 $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 732 update_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SETTINGS, $settings );
841 733 }
842 734 $render = new Visualizer_Render_Page_Send();
843 735 $render->text = sprintf( '[visualizer id="%d"]', $this->_chart->ID );
@@ -863,9 +755,8 @@
863 755 wp_enqueue_style( 'visualizer-frame' );
864 756 wp_enqueue_script( 'visualizer-preview' );
865 757 wp_enqueue_script( 'visualizer-chosen' );
866 758 wp_enqueue_script( 'visualizer-render' );
867 - wp_enqueue_code_editor( array( 'type' => 'application/json' ) );
868 759
869 760 if ( Visualizer_Module::can_show_feature( 'simple-editor' ) ) {
870 761 wp_enqueue_script( 'visualizer-editor-simple' );
871 762 wp_localize_script(
@@ -873,10 +764,12 @@
873 764 'visualizer1',
874 765 array(
875 766 'ajax' => array(
876 767 'url' => admin_url( 'admin-ajax.php' ),
877 - 'nonces' => array(),
878 - 'actions' => array(),
768 + 'nonces' => array(
769 + ),
770 + 'actions' => array(
771 + ),
879 772 ),
880 773 )
881 774 );
882 775 }
@@ -887,15 +780,13 @@
887 780 'visualizer-render',
888 781 'visualizer',
889 782 array(
890 783 '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' ),
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' ),
898 789 ),
899 790 'charts' => array(
900 791 'canvas' => $data,
901 792 'id' => $this->_chart->ID,
@@ -926,9 +817,8 @@
926 817 'page_type' => 'chart',
927 818 'json_tag_separator' => Visualizer_Source_Json::TAG_SEPARATOR,
928 819 'json_tag_separator_view' => Visualizer_Source_Json::TAG_SEPARATOR_VIEW,
929 820 'is_front' => false,
930 - 'rest_base' => get_rest_url( null, 'wc/v3/reports/' ),
931 821 )
932 822 );
933 823
934 824 $render = new Visualizer_Render_Page_Data();
@@ -939,10 +829,11 @@
939 829 if ( filter_input( INPUT_GET, 'library', FILTER_VALIDATE_BOOLEAN ) ) {
940 830 $render->button = filter_input( INPUT_GET, 'action' ) === Visualizer_Plugin::ACTION_EDIT_CHART
941 831 ? esc_html__( 'Save Chart', 'visualizer' )
942 832 : esc_html__( 'Create Chart', 'visualizer' );
943 -
944 - $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 + }
945 836 } else {
946 837 $render->button = esc_attr__( 'Insert Chart', 'visualizer' );
947 838 }
948 839
@@ -965,12 +856,12 @@
965 856 * @access private
966 857 */
967 858 private function _handleTypesPage() {
968 859 // process post request
969 - 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' ) ) ) {
970 861 $type = filter_input( INPUT_POST, 'type' );
971 862 $library = filter_input( INPUT_POST, 'chart-library' );
972 - if ( Visualizer_Module_Admin::checkChartStatus( $type ) ) {
863 + if ( in_array( $type, Visualizer_Plugin::getChartTypes(), true ) ) {
973 864 if ( empty( $library ) ) {
974 865 // library cannot be empty.
975 866 do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, 'Chart library empty while creating the chart! Aborting...', 'error', __FILE__, __LINE__ );
976 867 return;
@@ -991,9 +882,9 @@
991 882 Visualizer_Module_Utility::set_defaults( $this->_chart );
992 883
993 884 // redirect to next tab
994 885 // changed by Ash/Upwork
995 - wp_redirect( esc_url_raw( add_query_arg( 'tab', 'settings' ) ) );
886 + wp_redirect( add_query_arg( 'tab', 'settings' ) );
996 887
997 888 return;
998 889 }
999 890 }
@@ -1022,80 +913,8 @@
1022 913 * Processes the CSV that is sent in the request as a string.
1023 914 *
1024 915 * @since 3.2.0
1025 916 */
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 917 private function handleCSVasString( $data, $editor_type ) {
1099 918 $source = null;
1100 919
1101 920 switch ( $editor_type ) {
@@ -1110,9 +929,9 @@
1110 929 continue;
1111 930 }
1112 931 $row = explode( ',', $row );
1113 932 $row = array_map(
1114 - function ( $r ) {
933 + function( $r ) {
1115 934 return '' === $r ? ' ' : $r;
1116 935 },
1117 936 $row
1118 937 );
@@ -1161,9 +980,9 @@
1161 980 foreach ( $types as $type ) {
1162 981 if ( empty( $type ) ) {
1163 982 $exclude[] = $index;
1164 983 }
1165 - ++$index;
984 + $index++;
1166 985 }
1167 986
1168 987 // when N headers are being renamed, the number of headers increases by N
1169 988 // because of the way datatable duplicates header information
@@ -1223,13 +1042,9 @@
1223 1042 // otherwise, assume this is a normal web request.
1224 1043 $can_die = ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE );
1225 1044
1226 1045 // validate nonce
1227 - if (
1228 - ! isset( $_GET['nonce'] ) ||
1229 - ! wp_verify_nonce( $_GET['nonce'], 'visualizer-upload-data' ) ||
1230 - ! current_user_can( 'edit_posts' )
1231 - ) {
1046 + if ( ! isset( $_GET['nonce'] ) || ! wp_verify_nonce( $_GET['nonce'] ) ) {
1232 1047 if ( ! $can_die ) {
1233 1048 return;
1234 1049 }
1235 1050 status_header( 403 );
@@ -1238,15 +1053,9 @@
1238 1053
1239 1054 // check chart, if chart exists
1240 1055 // do not use filter_input as it does not work for phpunit test cases, use filter_var instead
1241 1056 $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 - ) {
1057 + if ( ! $chart_id || ! ( $chart = get_post( $chart_id ) ) || $chart->post_type !== Visualizer_Plugin::CPT_VISUALIZER ) {
1249 1058 if ( ! $can_die ) {
1250 1059 return;
1251 1060 }
1252 1061 status_header( 400 );
@@ -1287,30 +1096,16 @@
1287 1096 delete_post_meta( $chart_id, Visualizer_Plugin::CF_EDITABLE_TABLE );
1288 1097
1289 1098 $source = null;
1290 1099 $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 - }
1100 + if ( isset( $_POST['remote_data'] ) && filter_var( $_POST['remote_data'], FILTER_VALIDATE_URL ) ) {
1101 + $source = new Visualizer_Source_Csv_Remote( $_POST['remote_data'] );
1303 1102 if ( isset( $_POST['vz-import-time'] ) ) {
1304 - 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'] );
1305 1104 }
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 - }
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'] );
1313 1108 } elseif ( isset( $_POST['chart_data'] ) && strlen( $_POST['chart_data'] ) > 0 ) {
1314 1109 $source = $this->handleCSVasString( $_POST['chart_data'], $_POST['editor-type'] );
1315 1110 update_post_meta( $chart_id, Visualizer_Plugin::CF_EDITOR, $_POST['editor-type'] );
1316 1111 } elseif ( isset( $_POST['table_data'] ) && 'yes' === $_POST['table_data'] ) {
@@ -1317,10 +1112,10 @@
1317 1112 $source = $this->handleTabularData();
1318 1113 update_post_meta( $chart_id, Visualizer_Plugin::CF_EDITOR, $_POST['editor-type'] );
1319 1114 } else {
1320 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__ );
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' ) );
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' ) );
1323 1118 }
1324 1119
1325 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__ );
1326 1121
@@ -1341,9 +1136,8 @@
1341 1136 if ( $populate ) {
1342 1137 $chart->post_content = $content;
1343 1138 }
1344 1139 wp_update_post( $chart->to_array() );
1345 -
1346 1140 update_post_meta( $chart->ID, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
1347 1141 update_post_meta( $chart->ID, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() );
1348 1142 update_post_meta( $chart->ID, Visualizer_Plugin::CF_DEFAULT_DATA, 0 );
1349 1143
@@ -1351,17 +1145,8 @@
1351 1145
1352 1146 Visualizer_Module_Utility::set_defaults( $chart, null );
1353 1147
1354 1148 $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 1149
1365 1150 $render->id = $chart->ID;
1366 1151 $render->data = json_encode( $source->getRawData( get_post_meta( $chart->ID, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) ) );
1367 1152 $render->series = json_encode( $source->getSeries() );
@@ -1368,9 +1153,9 @@
1368 1153 $render->settings = json_encode( $settings );
1369 1154 } else {
1370 1155 $error = $source->get_error();
1371 1156 if ( empty( $error ) ) {
1372 - $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' );
1373 1158 }
1374 1159 $render->message = $error;
1375 1160 do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( '%s for chart %d.', $error, $chart_id ), 'error', __FILE__, __LINE__ );
1376 1161 update_post_meta( $chart_id, Visualizer_Plugin::CF_ERROR, $error );
@@ -1381,9 +1166,9 @@
1381 1166 $render->render();
1382 1167 if ( ! $can_die ) {
1383 1168 return;
1384 1169 }
1385 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1170 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1386 1171 }
1387 1172
1388 1173 /**
1389 1174 * Clones the chart.
@@ -1422,26 +1207,23 @@
1422 1207 if ( strpos( $key, 'visualizer-' ) !== false ) {
1423 1208 add_post_meta( $new_chart_id, $key, maybe_unserialize( $value[0] ) );
1424 1209 }
1425 1210 }
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' )
1211 + $redirect = add_query_arg(
1212 + array(
1213 + 'page' => 'visualizer',
1214 + 'type' => filter_input( INPUT_GET, 'type' ),
1215 + 'vaction' => false,
1434 1216 ),
1435 - null,
1436 - 'db'
1217 + admin_url( 'admin.php' )
1437 1218 );
1438 1219 }
1439 1220 }
1440 1221
1441 - if ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) {
1222 + if ( defined( 'WP_TESTS_DOMAIN' ) ) {
1442 1223 wp_die();
1443 1224 }
1225 +
1444 1226 wp_redirect( $redirect );
1445 1227 exit;
1446 1228 }
1447 1229
@@ -1472,9 +1254,9 @@
1472 1254 }
1473 1255 }
1474 1256 }
1475 1257
1476 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1258 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1477 1259 }
1478 1260
1479 1261 /**
1480 1262 * Handles chart data page.
@@ -1498,11 +1280,10 @@
1498 1280 'visualizer-render',
1499 1281 'visualizer',
1500 1282 array(
1501 1283 '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' ),
1284 + 'invalid_source' => esc_html__( 'You have entered an invalid URL. Please provide a valid URL.', 'visualizer' ),
1285 + 'loading' => esc_html__( 'Loading...', 'visualizer' ),
1505 1286 ),
1506 1287 'charts' => array(
1507 1288 'canvas' => $data,
1508 1289 ),
@@ -1528,24 +1309,12 @@
1528 1309 */
1529 1310 public function getQueryData() {
1530 1311 check_ajax_referer( Visualizer_Plugin::ACTION_FETCH_DB_DATA . Visualizer_Plugin::VERSION, 'security' );
1531 1312
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 1313 $params = wp_parse_args( $_POST['params'] );
1544 1314 $chart_id = filter_var( $params['chart_id'], FILTER_VALIDATE_INT );
1545 - $query = trim( $params['query'], ';' );
1546 1315
1547 - $source = new Visualizer_Source_Query( stripslashes( $query ), $chart_id, $params );
1316 + $source = new Visualizer_Source_Query( stripslashes( $params['query'] ), $chart_id, $params );
1548 1317 $html = $source->fetch( true );
1549 1318 $error = $source->get_error();
1550 1319 if ( ! empty( $error ) ) {
1551 1320 wp_send_json_error( array( 'msg' => $error ) );
@@ -1560,19 +1329,8 @@
1560 1329 */
1561 1330 public function saveQuery() {
1562 1331 check_ajax_referer( Visualizer_Plugin::ACTION_SAVE_DB_QUERY . Visualizer_Plugin::VERSION, 'security' );
1563 1332
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 1333 $chart_id = filter_input(
1576 1334 INPUT_GET,
1577 1335 'chart',
1578 1336 FILTER_VALIDATE_INT,
@@ -1601,14 +1359,13 @@
1601 1359
1602 1360 $render = new Visualizer_Render_Page_Update();
1603 1361 if ( $chart_id ) {
1604 1362 $params = wp_parse_args( $_POST['params'] );
1605 - $query = trim( $params['query'], ';' );
1606 - $source = new Visualizer_Source_Query( stripslashes( $query ), $chart_id, $params );
1363 + $source = new Visualizer_Source_Query( stripslashes( $params['query'] ), $chart_id, $params );
1607 1364 $source->fetch( false );
1608 1365 $error = $source->get_error();
1609 1366 if ( empty( $error ) ) {
1610 - 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'] ) );
1611 1368 update_post_meta( $chart_id, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() );
1612 1369 update_post_meta( $chart_id, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
1613 1370 update_post_meta( $chart_id, Visualizer_Plugin::CF_DB_SCHEDULE, $hours );
1614 1371 update_post_meta( $chart_id, Visualizer_Plugin::CF_DEFAULT_DATA, 0 );
@@ -1637,9 +1394,9 @@
1637 1394 }
1638 1395 }
1639 1396 $render->render();
1640 1397 if ( ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE ) ) {
1641 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1398 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1642 1399 }
1643 1400 }
1644 1401
1645 1402
@@ -1664,9 +1421,9 @@
1664 1421
1665 1422 $hours = filter_input(
1666 1423 INPUT_POST,
1667 1424 'refresh',
1668 - FILTER_VALIDATE_FLOAT,
1425 + FILTER_VALIDATE_INT,
1669 1426 array(
1670 1427 'options' => array(
1671 1428 'min_range' => -1,
1672 1429 'max_range' => apply_filters( 'visualizer_is_business', false ) ? PHP_INT_MAX : -1,
@@ -1673,9 +1430,9 @@
1673 1430 ),
1674 1431 )
1675 1432 );
1676 1433
1677 - if ( ! is_numeric( $hours ) ) {
1434 + if ( 0 !== $hours && empty( $hours ) ) {
1678 1435 $hours = -1;
1679 1436 }
1680 1437
1681 1438 do_action( 'visualizer_save_filter', $chart_id, $hours );
@@ -1680,9 +1437,9 @@
1680 1437
1681 1438 do_action( 'visualizer_save_filter', $chart_id, $hours );
1682 1439
1683 1440 if ( ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE ) ) {
1684 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1441 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1685 1442 }
1686 1443 }
1687 1444
1688 1445 /**
@@ -1718,12 +1475,8 @@
1718 1475 // Save the image in the uploads directory.
1719 1476 require_once ABSPATH . '/wp-admin/includes/file.php';
1720 1477 \WP_Filesystem();
1721 1478 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 1479 $upload_file = $wp_filesystem->put_contents( $upload_path . $hashed_filename, $decoded );
1727 1480
1728 1481 // Insert new chart image.
1729 1482 $attachment = array(