PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.9.2
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.9.2
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 +76 -224 4.0.53.9.2 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.
@@ -169,12 +170,8 @@
169 170 */
170 171 public function getJsonRoots() {
171 172 check_ajax_referer( Visualizer_Plugin::ACTION_JSON_GET_ROOTS . Visualizer_Plugin::VERSION, 'security' );
172 173
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 174 $params = wp_parse_args( $_POST['params'] );
178 175
179 176 $source = new Visualizer_Source_Json( $params );
180 177
@@ -195,12 +192,8 @@
195 192 */
196 193 public function getJsonData() {
197 194 check_ajax_referer( Visualizer_Plugin::ACTION_JSON_GET_DATA . Visualizer_Plugin::VERSION, 'security' );
198 195
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 196 $params = wp_parse_args( $_POST['params'] );
204 197
205 198 $chart_id = $params['chart'];
206 199
@@ -303,9 +296,9 @@
303 296 $render->data = json_encode( $source->getRawData( get_post_meta( $chart_id, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) ) );
304 297 $render->series = json_encode( $source->getSeries() );
305 298 $render->render();
306 299
307 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
300 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
308 301 }
309 302
310 303
311 304 /**
@@ -381,13 +374,13 @@
381 374 * @since 1.0.0
382 375 *
383 376 * @access private
384 377 *
385 - * @param WP_Post|null $chart The chart object.
378 + * @param WP_Post $chart The chart object.
386 379 *
387 380 * @return array The array of chart data.
388 381 */
389 - private function _getChartArray( $chart = null ) {
382 + private function _getChartArray( WP_Post $chart = null ) {
390 383 if ( is_null( $chart ) ) {
391 384 $chart = $this->_chart;
392 385 }
393 386 $type = get_post_meta( $chart->ID, Visualizer_Plugin::CF_CHART_TYPE, true );
@@ -409,13 +402,8 @@
409 402 }
410 403
411 404 $date_formats = Visualizer_Source::get_date_formats_if_exists( $series, $data );
412 405
413 - $code = '';
414 - if ( 'd3' === $library ) {
415 - $code = get_post_meta( $chart->ID, Visualizer_Module_AIBuilder::CF_D3_CODE, true );
416 - }
417 -
418 406 return array(
419 407 'type' => $type,
420 408 'series' => $series,
421 409 'settings' => $settings,
@@ -420,9 +408,8 @@
420 408 'series' => $series,
421 409 'settings' => $settings,
422 410 'data' => $data,
423 411 'library' => $library,
424 - 'code' => $code,
425 412 'css' => $css,
426 413 'date_formats' => $date_formats,
427 414 );
428 415 }
@@ -439,9 +426,9 @@
439 426 public static function _sendResponse( $results ) {
440 427 header( 'Content-type: application/json' );
441 428 nocache_headers();
442 429 echo json_encode( $results );
443 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
430 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
444 431 }
445 432
446 433 /**
447 434 * Deletes a chart from database.
@@ -536,12 +523,8 @@
536 523 *
537 524 * @access public
538 525 */
539 526 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 527 defined( 'IFRAME_REQUEST' ) || define( 'IFRAME_REQUEST', 1 );
545 528 if ( ! defined( 'ET_BUILDER_PRODUCT_VERSION' ) && function_exists( 'et_get_theme_version' ) ) {
546 529 define( 'ET_BUILDER_PRODUCT_VERSION', et_get_theme_version() );
547 530 }
@@ -551,17 +534,12 @@
551 534 $chart_id = isset( $_GET['chart'] ) ? filter_var( $_GET['chart'], FILTER_VALIDATE_INT ) : '';
552 535 if ( ! empty( $_POST ) ) {
553 536 $_POST = map_deep( $_POST, 'wp_strip_all_tags' );
554 537 }
555 - $chart = $chart_id ? get_post( $chart_id ) : null;
556 - if ( ! $chart_id || ! $chart || $chart->post_type !== Visualizer_Plugin::CPT_VISUALIZER ) {
538 + if ( ! $chart_id || ! ( $chart = get_post( $chart_id ) ) || $chart->post_type !== Visualizer_Plugin::CPT_VISUALIZER ) {
557 539 if ( empty( $_GET['lang'] ) || empty( $_GET['parent_chart_id'] ) ) {
558 540 $this->deleteOldCharts();
559 541 $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 542 $source = new Visualizer_Source_Csv( VISUALIZER_ABSPATH . DIRECTORY_SEPARATOR . 'samples' . DIRECTORY_SEPARATOR . $default_type . '.csv' );
565 543 $source->fetch();
566 544 $chart_id = wp_insert_post(
567 545 array(
@@ -588,33 +566,35 @@
588 566
589 567 do_action( 'visualizer_pro_new_chart_defaults', $chart_id );
590 568 }
591 569 } 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 - );
570 + if ( current_user_can( 'edit_posts' ) ) {
571 + $parent_chart_id = isset( $_GET['parent_chart_id'] ) ? filter_var( $_GET['parent_chart_id'], FILTER_VALIDATE_INT ) : '';
572 + $success = false;
573 + if ( $parent_chart_id ) {
574 + $parent_chart = get_post( $parent_chart_id );
575 + $success = $parent_chart && $parent_chart->post_type === Visualizer_Plugin::CPT_VISUALIZER;
576 + }
577 + if ( $success ) {
578 + $new_chart_id = wp_insert_post(
579 + array(
580 + 'post_type' => Visualizer_Plugin::CPT_VISUALIZER,
581 + 'post_title' => 'Visualization',
582 + 'post_author' => get_current_user_id(),
583 + 'post_status' => $parent_chart->post_status,
584 + 'post_content' => $parent_chart->post_content,
585 + )
586 + );
608 587
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] ) );
588 + if ( is_wp_error( $new_chart_id ) ) {
589 + 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__ );
590 + } else {
591 + $post_meta = get_post_meta( $parent_chart_id );
592 + $chart_id = $new_chart_id;
593 + foreach ( $post_meta as $key => $value ) {
594 + if ( strpos( $key, 'visualizer-' ) !== false ) {
595 + add_post_meta( $new_chart_id, $key, maybe_unserialize( $value[0] ) );
596 + }
617 597 }
618 598 }
619 599 }
620 600 }
@@ -621,9 +601,9 @@
621 601 do_action( 'visualizer_pro_new_chart_defaults', $chart_id );
622 602 }
623 603 wp_redirect( esc_url_raw( add_query_arg( 'chart', (int) $chart_id ) ) );
624 604
625 - if ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) {
605 + if ( defined( 'WP_TESTS_DOMAIN' ) ) {
626 606 wp_die();
627 607 }
628 608 exit();
629 609 }
@@ -719,9 +699,9 @@
719 699 default:
720 700 // this should never happen.
721 701 break;
722 702 }
723 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
703 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
724 704 }
725 705
726 706 /**
727 707 * Load code editor assets.
@@ -751,9 +731,9 @@
751 731 wp_register_script( 'visualizer-codemirror-matchbrackets', '//codemirror.net/addon/edit/matchbrackets.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
752 732 wp_register_script( 'visualizer-codemirror-closebrackets', '//codemirror.net/addon/edit/closebrackets.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
753 733 wp_register_script( 'visualizer-codemirror-sql', '//codemirror.net/mode/sql/sql.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
754 734 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 );
735 + 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 736 wp_register_style( 'visualizer-codemirror-core', '//codemirror.net/lib/codemirror.css', array(), Visualizer_Plugin::VERSION );
757 737 wp_register_style( 'visualizer-codemirror-hint', '//codemirror.net/addon/hint/show-hint.css', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
758 738
759 739 wp_enqueue_script( 'visualizer-codemirror-hint' );
@@ -767,9 +747,9 @@
767 747 'lineWrapping' => true,
768 748 'dragDrop' => false,
769 749 'matchBrackets' => true,
770 750 'autoCloseBrackets' => true,
771 - 'extraKeys' => array( 'Shift-Space' => 'autocomplete' ),
751 + 'extraKeys' => array( 'Ctrl-Space' => 'autocomplete' ),
772 752 'hintOptions' => array( 'tables' => $table_col_mapping ),
773 753 ),
774 754 )
775 755 );
@@ -803,12 +783,9 @@
803 783 update_option( 'visualizer-map-api-key', $_POST['map_api_key'] );
804 784 }
805 785
806 786 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 ) {
787 + if ( $this->_chart->post_status === 'auto-draft' ) {
811 788 $this->_chart->post_status = 'publish';
812 789
813 790 // 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 791 // we do not want any difference in data so disable revisions temporarily.
@@ -816,15 +793,10 @@
816 793
817 794 wp_update_post( $this->_chart->to_array() );
818 795 }
819 796 // 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 );
797 + if ( ! ( isset( $_POST['cancel'] ) && 1 === intval( $_POST['cancel'] ) ) ) {
798 + update_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SETTINGS, $_POST );
827 799
828 800 // we will keep a parameter called 'internal_title' that will be set to the given title or, if empty, the chart ID
829 801 // this will help in searching with the chart id.
830 802 $settings = get_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SETTINGS, true );
@@ -871,9 +843,8 @@
871 843 wp_enqueue_style( 'visualizer-frame' );
872 844 wp_enqueue_script( 'visualizer-preview' );
873 845 wp_enqueue_script( 'visualizer-chosen' );
874 846 wp_enqueue_script( 'visualizer-render' );
875 - wp_enqueue_code_editor( array( 'type' => 'application/json' ) );
876 847
877 848 if ( Visualizer_Module::can_show_feature( 'simple-editor' ) ) {
878 849 wp_enqueue_script( 'visualizer-editor-simple' );
879 850 wp_localize_script(
@@ -881,10 +852,12 @@
881 852 'visualizer1',
882 853 array(
883 854 'ajax' => array(
884 855 'url' => admin_url( 'admin-ajax.php' ),
885 - 'nonces' => array(),
886 - 'actions' => array(),
856 + 'nonces' => array(
857 + ),
858 + 'actions' => array(
859 + ),
887 860 ),
888 861 )
889 862 );
890 863 }
@@ -895,15 +868,13 @@
895 868 'visualizer-render',
896 869 'visualizer',
897 870 array(
898 871 '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' ),
872 + 'invalid_source' => esc_html__( 'You have entered an invalid URL. Please provide a valid URL.', 'visualizer' ),
873 + 'loading' => esc_html__( 'Loading...', 'visualizer' ),
874 + 'json_error' => esc_html__( 'An error occured in fetching data.', 'visualizer' ),
875 + 'select_columns' => esc_html__( 'Please select a few columns to include in the chart.', 'visualizer' ),
876 + '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 877 ),
907 878 'charts' => array(
908 879 'canvas' => $data,
909 880 'id' => $this->_chart->ID,
@@ -947,10 +918,11 @@
947 918 if ( filter_input( INPUT_GET, 'library', FILTER_VALIDATE_BOOLEAN ) ) {
948 919 $render->button = filter_input( INPUT_GET, 'action' ) === Visualizer_Plugin::ACTION_EDIT_CHART
949 920 ? esc_html__( 'Save Chart', 'visualizer' )
950 921 : esc_html__( 'Create Chart', 'visualizer' );
951 -
952 - $render->cancel_button = esc_html__( 'Cancel', 'visualizer' );
922 + if ( filter_input( INPUT_GET, 'action' ) === Visualizer_Plugin::ACTION_EDIT_CHART ) {
923 + $render->cancel_button = esc_html__( 'Cancel', 'visualizer' );
924 + }
953 925 } else {
954 926 $render->button = esc_attr__( 'Insert Chart', 'visualizer' );
955 927 }
956 928
@@ -973,12 +945,12 @@
973 945 * @access private
974 946 */
975 947 private function _handleTypesPage() {
976 948 // process post request
977 - if ( $_SERVER['REQUEST_METHOD'] === 'POST' && wp_verify_nonce( filter_input( INPUT_POST, 'nonce' ), 'visualizer-upload-data' ) ) {
949 + if ( $_SERVER['REQUEST_METHOD'] === 'POST' && wp_verify_nonce( filter_input( INPUT_POST, 'nonce' ) ) ) {
978 950 $type = filter_input( INPUT_POST, 'type' );
979 951 $library = filter_input( INPUT_POST, 'chart-library' );
980 - if ( Visualizer_Module_Admin::checkChartStatus( $type ) ) {
952 + if ( in_array( $type, Visualizer_Plugin::getChartTypes(), true ) ) {
981 953 if ( empty( $library ) ) {
982 954 // library cannot be empty.
983 955 do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, 'Chart library empty while creating the chart! Aborting...', 'error', __FILE__, __LINE__ );
984 956 return;
@@ -1030,80 +1002,8 @@
1030 1002 * Processes the CSV that is sent in the request as a string.
1031 1003 *
1032 1004 * @since 3.2.0
1033 1005 */
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 1006 private function handleCSVasString( $data, $editor_type ) {
1107 1007 $source = null;
1108 1008
1109 1009 switch ( $editor_type ) {
@@ -1118,9 +1018,9 @@
1118 1018 continue;
1119 1019 }
1120 1020 $row = explode( ',', $row );
1121 1021 $row = array_map(
1122 - function ( $r ) {
1022 + function( $r ) {
1123 1023 return '' === $r ? ' ' : $r;
1124 1024 },
1125 1025 $row
1126 1026 );
@@ -1169,9 +1069,9 @@
1169 1069 foreach ( $types as $type ) {
1170 1070 if ( empty( $type ) ) {
1171 1071 $exclude[] = $index;
1172 1072 }
1173 - ++$index;
1073 + $index++;
1174 1074 }
1175 1075
1176 1076 // when N headers are being renamed, the number of headers increases by N
1177 1077 // because of the way datatable duplicates header information
@@ -1231,13 +1131,9 @@
1231 1131 // otherwise, assume this is a normal web request.
1232 1132 $can_die = ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE );
1233 1133
1234 1134 // validate nonce
1235 - if (
1236 - ! isset( $_GET['nonce'] ) ||
1237 - ! wp_verify_nonce( $_GET['nonce'], 'visualizer-upload-data' ) ||
1238 - ! current_user_can( 'edit_posts' )
1239 - ) {
1135 + if ( ! isset( $_GET['nonce'] ) || ! wp_verify_nonce( $_GET['nonce'] ) ) {
1240 1136 if ( ! $can_die ) {
1241 1137 return;
1242 1138 }
1243 1139 status_header( 403 );
@@ -1246,15 +1142,9 @@
1246 1142
1247 1143 // check chart, if chart exists
1248 1144 // do not use filter_input as it does not work for phpunit test cases, use filter_var instead
1249 1145 $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 - ) {
1146 + if ( ! $chart_id || ! ( $chart = get_post( $chart_id ) ) || $chart->post_type !== Visualizer_Plugin::CPT_VISUALIZER ) {
1257 1147 if ( ! $can_die ) {
1258 1148 return;
1259 1149 }
1260 1150 status_header( 400 );
@@ -1301,24 +1191,15 @@
1301 1191 if ( isset( $_POST['remote_data'] ) && function_exists( 'wp_http_validate_url' ) ) {
1302 1192 $remote_data = wp_http_validate_url( $_POST['remote_data'] );
1303 1193 }
1304 1194 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 - }
1195 + $source = new Visualizer_Source_Csv_Remote( $remote_data );
1311 1196 if ( isset( $_POST['vz-import-time'] ) ) {
1312 1197 apply_filters( 'visualizer_pro_chart_schedule', $chart_id, $remote_data, $_POST['vz-import-time'] );
1313 1198 }
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 - }
1199 + // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
1200 + } elseif ( isset( $_FILES['local_data'] ) && $_FILES['local_data']['error'] == 0 ) {
1201 + $source = new Visualizer_Source_Csv( $_FILES['local_data']['tmp_name'] );
1321 1202 } elseif ( isset( $_POST['chart_data'] ) && strlen( $_POST['chart_data'] ) > 0 ) {
1322 1203 $source = $this->handleCSVasString( $_POST['chart_data'], $_POST['editor-type'] );
1323 1204 update_post_meta( $chart_id, Visualizer_Plugin::CF_EDITOR, $_POST['editor-type'] );
1324 1205 } elseif ( isset( $_POST['table_data'] ) && 'yes' === $_POST['table_data'] ) {
@@ -1325,10 +1206,10 @@
1325 1206 $source = $this->handleTabularData();
1326 1207 update_post_meta( $chart_id, Visualizer_Plugin::CF_EDITOR, $_POST['editor-type'] );
1327 1208 } else {
1328 1209 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' ) );
1210 + $render->message = esc_html__( 'CSV file with chart data was not uploaded. Please try again.', 'visualizer' );
1211 + update_post_meta( $chart_id, Visualizer_Plugin::CF_ERROR, esc_html__( 'CSV file with chart data was not uploaded. Please try again.', 'visualizer' ) );
1331 1212 }
1332 1213
1333 1214 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 1215
@@ -1376,9 +1257,9 @@
1376 1257 $render->settings = json_encode( $settings );
1377 1258 } else {
1378 1259 $error = $source->get_error();
1379 1260 if ( empty( $error ) ) {
1380 - $error = esc_html__( 'The CSV file couldn\'t be read. Check that it\'s properly formatted and try again.', 'visualizer' );
1261 + $error = esc_html__( 'CSV file is broken or invalid. Please try again.', 'visualizer' );
1381 1262 }
1382 1263 $render->message = $error;
1383 1264 do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( '%s for chart %d.', $error, $chart_id ), 'error', __FILE__, __LINE__ );
1384 1265 update_post_meta( $chart_id, Visualizer_Plugin::CF_ERROR, $error );
@@ -1389,9 +1270,9 @@
1389 1270 $render->render();
1390 1271 if ( ! $can_die ) {
1391 1272 return;
1392 1273 }
1393 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1274 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1394 1275 }
1395 1276
1396 1277 /**
1397 1278 * Clones the chart.
@@ -1445,9 +1326,9 @@
1445 1326 );
1446 1327 }
1447 1328 }
1448 1329
1449 - if ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) {
1330 + if ( defined( 'WP_TESTS_DOMAIN' ) ) {
1450 1331 wp_die();
1451 1332 }
1452 1333 wp_redirect( $redirect );
1453 1334 exit;
@@ -1480,9 +1361,9 @@
1480 1361 }
1481 1362 }
1482 1363 }
1483 1364
1484 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1365 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1485 1366 }
1486 1367
1487 1368 /**
1488 1369 * Handles chart data page.
@@ -1506,11 +1387,10 @@
1506 1387 'visualizer-render',
1507 1388 'visualizer',
1508 1389 array(
1509 1390 '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' ),
1391 + 'invalid_source' => esc_html__( 'You have entered an invalid URL. Please provide a valid URL.', 'visualizer' ),
1392 + 'loading' => esc_html__( 'Loading...', 'visualizer' ),
1513 1393 ),
1514 1394 'charts' => array(
1515 1395 'canvas' => $data,
1516 1396 ),
@@ -1536,24 +1416,12 @@
1536 1416 */
1537 1417 public function getQueryData() {
1538 1418 check_ajax_referer( Visualizer_Plugin::ACTION_FETCH_DB_DATA . Visualizer_Plugin::VERSION, 'security' );
1539 1419
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 1420 $params = wp_parse_args( $_POST['params'] );
1552 1421 $chart_id = filter_var( $params['chart_id'], FILTER_VALIDATE_INT );
1553 - $query = trim( $params['query'], ';' );
1554 1422
1555 - $source = new Visualizer_Source_Query( stripslashes( $query ), $chart_id, $params );
1423 + $source = new Visualizer_Source_Query( stripslashes( $params['query'] ), $chart_id, $params );
1556 1424 $html = $source->fetch( true );
1557 1425 $error = $source->get_error();
1558 1426 if ( ! empty( $error ) ) {
1559 1427 wp_send_json_error( array( 'msg' => $error ) );
@@ -1568,19 +1436,8 @@
1568 1436 */
1569 1437 public function saveQuery() {
1570 1438 check_ajax_referer( Visualizer_Plugin::ACTION_SAVE_DB_QUERY . Visualizer_Plugin::VERSION, 'security' );
1571 1439
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 1440 $chart_id = filter_input(
1584 1441 INPUT_GET,
1585 1442 'chart',
1586 1443 FILTER_VALIDATE_INT,
@@ -1609,14 +1466,13 @@
1609 1466
1610 1467 $render = new Visualizer_Render_Page_Update();
1611 1468 if ( $chart_id ) {
1612 1469 $params = wp_parse_args( $_POST['params'] );
1613 - $query = trim( $params['query'], ';' );
1614 - $source = new Visualizer_Source_Query( stripslashes( $query ), $chart_id, $params );
1470 + $source = new Visualizer_Source_Query( stripslashes( $params['query'] ), $chart_id, $params );
1615 1471 $source->fetch( false );
1616 1472 $error = $source->get_error();
1617 1473 if ( empty( $error ) ) {
1618 - update_post_meta( $chart_id, Visualizer_Plugin::CF_DB_QUERY, stripslashes( $query ) );
1474 + update_post_meta( $chart_id, Visualizer_Plugin::CF_DB_QUERY, stripslashes( $params['query'] ) );
1619 1475 update_post_meta( $chart_id, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() );
1620 1476 update_post_meta( $chart_id, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
1621 1477 update_post_meta( $chart_id, Visualizer_Plugin::CF_DB_SCHEDULE, $hours );
1622 1478 update_post_meta( $chart_id, Visualizer_Plugin::CF_DEFAULT_DATA, 0 );
@@ -1645,9 +1501,9 @@
1645 1501 }
1646 1502 }
1647 1503 $render->render();
1648 1504 if ( ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE ) ) {
1649 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1505 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1650 1506 }
1651 1507 }
1652 1508
1653 1509
@@ -1672,9 +1528,9 @@
1672 1528
1673 1529 $hours = filter_input(
1674 1530 INPUT_POST,
1675 1531 'refresh',
1676 - FILTER_VALIDATE_FLOAT,
1532 + FILTER_VALIDATE_INT,
1677 1533 array(
1678 1534 'options' => array(
1679 1535 'min_range' => -1,
1680 1536 'max_range' => apply_filters( 'visualizer_is_business', false ) ? PHP_INT_MAX : -1,
@@ -1681,9 +1537,9 @@
1681 1537 ),
1682 1538 )
1683 1539 );
1684 1540
1685 - if ( ! is_numeric( $hours ) ) {
1541 + if ( 0 !== $hours && empty( $hours ) ) {
1686 1542 $hours = -1;
1687 1543 }
1688 1544
1689 1545 do_action( 'visualizer_save_filter', $chart_id, $hours );
@@ -1688,9 +1544,9 @@
1688 1544
1689 1545 do_action( 'visualizer_save_filter', $chart_id, $hours );
1690 1546
1691 1547 if ( ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE ) ) {
1692 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1548 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1693 1549 }
1694 1550 }
1695 1551
1696 1552 /**
@@ -1726,12 +1582,8 @@
1726 1582 // Save the image in the uploads directory.
1727 1583 require_once ABSPATH . '/wp-admin/includes/file.php';
1728 1584 \WP_Filesystem();
1729 1585 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 1586 $upload_file = $wp_filesystem->put_contents( $upload_path . $hashed_filename, $decoded );
1735 1587
1736 1588 // Insert new chart image.
1737 1589 $attachment = array(