PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.11.7
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.11.7
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 3.10.4 All 148 releases
← All changes | classes/Visualizer/Module/Chart.php +67 -180 4.0.53.11.7 View file →
@@ -69,8 +69,9 @@
69 69
70 70 $this->_addAjaxAction( Visualizer_Plugin::ACTION_SAVE_FILTER_QUERY, 'saveFilter' );
71 71
72 72 $this->_addFilter( 'visualizer_get_sidebar', 'getSidebar', 10, 2 );
73 +
73 74 }
74 75
75 76 /**
76 77 * Generates the HTML of the sidebar for the chart.
@@ -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,10 +534,9 @@
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 542 $chart_status = Visualizer_Module_Admin::checkChartStatus( $default_type );
@@ -588,33 +570,35 @@
588 570
589 571 do_action( 'visualizer_pro_new_chart_defaults', $chart_id );
590 572 }
591 573 } 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 - );
574 + if ( current_user_can( 'edit_posts' ) ) {
575 + $parent_chart_id = isset( $_GET['parent_chart_id'] ) ? filter_var( $_GET['parent_chart_id'], FILTER_VALIDATE_INT ) : '';
576 + $success = false;
577 + if ( $parent_chart_id ) {
578 + $parent_chart = get_post( $parent_chart_id );
579 + $success = $parent_chart && $parent_chart->post_type === Visualizer_Plugin::CPT_VISUALIZER;
580 + }
581 + if ( $success ) {
582 + $new_chart_id = wp_insert_post(
583 + array(
584 + 'post_type' => Visualizer_Plugin::CPT_VISUALIZER,
585 + 'post_title' => 'Visualization',
586 + 'post_author' => get_current_user_id(),
587 + 'post_status' => $parent_chart->post_status,
588 + 'post_content' => $parent_chart->post_content,
589 + )
590 + );
608 591
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] ) );
592 + if ( is_wp_error( $new_chart_id ) ) {
593 + 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__ );
594 + } else {
595 + $post_meta = get_post_meta( $parent_chart_id );
596 + $chart_id = $new_chart_id;
597 + foreach ( $post_meta as $key => $value ) {
598 + if ( strpos( $key, 'visualizer-' ) !== false ) {
599 + add_post_meta( $new_chart_id, $key, maybe_unserialize( $value[0] ) );
600 + }
617 601 }
618 602 }
619 603 }
620 604 }
@@ -621,9 +605,9 @@
621 605 do_action( 'visualizer_pro_new_chart_defaults', $chart_id );
622 606 }
623 607 wp_redirect( esc_url_raw( add_query_arg( 'chart', (int) $chart_id ) ) );
624 608
625 - if ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) {
609 + if ( defined( 'WP_TESTS_DOMAIN' ) ) {
626 610 wp_die();
627 611 }
628 612 exit();
629 613 }
@@ -719,9 +703,9 @@
719 703 default:
720 704 // this should never happen.
721 705 break;
722 706 }
723 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
707 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
724 708 }
725 709
726 710 /**
727 711 * Load code editor assets.
@@ -751,9 +735,9 @@
751 735 wp_register_script( 'visualizer-codemirror-matchbrackets', '//codemirror.net/addon/edit/matchbrackets.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
752 736 wp_register_script( 'visualizer-codemirror-closebrackets', '//codemirror.net/addon/edit/closebrackets.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
753 737 wp_register_script( 'visualizer-codemirror-sql', '//codemirror.net/mode/sql/sql.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
754 738 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 );
739 + 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 740 wp_register_style( 'visualizer-codemirror-core', '//codemirror.net/lib/codemirror.css', array(), Visualizer_Plugin::VERSION );
757 741 wp_register_style( 'visualizer-codemirror-hint', '//codemirror.net/addon/hint/show-hint.css', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
758 742
759 743 wp_enqueue_script( 'visualizer-codemirror-hint' );
@@ -817,14 +801,9 @@
817 801 wp_update_post( $this->_chart->to_array() );
818 802 }
819 803 // save meta data only when it is NOT being canceled.
820 804 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 );
805 + update_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SETTINGS, $_POST );
827 806
828 807 // we will keep a parameter called 'internal_title' that will be set to the given title or, if empty, the chart ID
829 808 // this will help in searching with the chart id.
830 809 $settings = get_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SETTINGS, true );
@@ -871,9 +850,8 @@
871 850 wp_enqueue_style( 'visualizer-frame' );
872 851 wp_enqueue_script( 'visualizer-preview' );
873 852 wp_enqueue_script( 'visualizer-chosen' );
874 853 wp_enqueue_script( 'visualizer-render' );
875 - wp_enqueue_code_editor( array( 'type' => 'application/json' ) );
876 854
877 855 if ( Visualizer_Module::can_show_feature( 'simple-editor' ) ) {
878 856 wp_enqueue_script( 'visualizer-editor-simple' );
879 857 wp_localize_script(
@@ -881,10 +859,12 @@
881 859 'visualizer1',
882 860 array(
883 861 'ajax' => array(
884 862 'url' => admin_url( 'admin-ajax.php' ),
885 - 'nonces' => array(),
886 - 'actions' => array(),
863 + 'nonces' => array(
864 + ),
865 + 'actions' => array(
866 + ),
887 867 ),
888 868 )
889 869 );
890 870 }
@@ -895,15 +875,14 @@
895 875 'visualizer-render',
896 876 'visualizer',
897 877 array(
898 878 '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' ),
879 + 'invalid_source' => esc_html__( 'You have entered an invalid URL. Please provide a valid URL.', 'visualizer' ),
880 + 'loading' => esc_html__( 'Loading...', 'visualizer' ),
881 + 'json_error' => esc_html__( 'An error occured in fetching data.', 'visualizer' ),
882 + 'select_columns' => esc_html__( 'Please select a few columns to include in the chart.', 'visualizer' ),
883 + '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' ),
884 + 'copied' => __( 'The data has been copied to your clipboard. Hit Ctrl-V/Cmd-V in your spreadsheet editor to paste the data.', 'visualizer' ),
906 885 ),
907 886 'charts' => array(
908 887 'canvas' => $data,
909 888 'id' => $this->_chart->ID,
@@ -973,9 +952,9 @@
973 952 * @access private
974 953 */
975 954 private function _handleTypesPage() {
976 955 // process post request
977 - if ( $_SERVER['REQUEST_METHOD'] === 'POST' && wp_verify_nonce( filter_input( INPUT_POST, 'nonce' ), 'visualizer-upload-data' ) ) {
956 + if ( $_SERVER['REQUEST_METHOD'] === 'POST' && wp_verify_nonce( filter_input( INPUT_POST, 'nonce' ) ) ) {
978 957 $type = filter_input( INPUT_POST, 'type' );
979 958 $library = filter_input( INPUT_POST, 'chart-library' );
980 959 if ( Visualizer_Module_Admin::checkChartStatus( $type ) ) {
981 960 if ( empty( $library ) ) {
@@ -1030,80 +1009,8 @@
1030 1009 * Processes the CSV that is sent in the request as a string.
1031 1010 *
1032 1011 * @since 3.2.0
1033 1012 */
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 1013 private function handleCSVasString( $data, $editor_type ) {
1107 1014 $source = null;
1108 1015
1109 1016 switch ( $editor_type ) {
@@ -1118,9 +1025,9 @@
1118 1025 continue;
1119 1026 }
1120 1027 $row = explode( ',', $row );
1121 1028 $row = array_map(
1122 - function ( $r ) {
1029 + function( $r ) {
1123 1030 return '' === $r ? ' ' : $r;
1124 1031 },
1125 1032 $row
1126 1033 );
@@ -1169,9 +1076,9 @@
1169 1076 foreach ( $types as $type ) {
1170 1077 if ( empty( $type ) ) {
1171 1078 $exclude[] = $index;
1172 1079 }
1173 - ++$index;
1080 + $index++;
1174 1081 }
1175 1082
1176 1083 // when N headers are being renamed, the number of headers increases by N
1177 1084 // because of the way datatable duplicates header information
@@ -1231,13 +1138,9 @@
1231 1138 // otherwise, assume this is a normal web request.
1232 1139 $can_die = ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE );
1233 1140
1234 1141 // validate nonce
1235 - if (
1236 - ! isset( $_GET['nonce'] ) ||
1237 - ! wp_verify_nonce( $_GET['nonce'], 'visualizer-upload-data' ) ||
1238 - ! current_user_can( 'edit_posts' )
1239 - ) {
1142 + if ( ! isset( $_GET['nonce'] ) || ! wp_verify_nonce( $_GET['nonce'] ) ) {
1240 1143 if ( ! $can_die ) {
1241 1144 return;
1242 1145 }
1243 1146 status_header( 403 );
@@ -1246,15 +1149,9 @@
1246 1149
1247 1150 // check chart, if chart exists
1248 1151 // do not use filter_input as it does not work for phpunit test cases, use filter_var instead
1249 1152 $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 - ) {
1153 + if ( ! $chart_id || ! ( $chart = get_post( $chart_id ) ) || $chart->post_type !== Visualizer_Plugin::CPT_VISUALIZER ) {
1257 1154 if ( ! $can_die ) {
1258 1155 return;
1259 1156 }
1260 1157 status_header( 400 );
@@ -1301,24 +1198,15 @@
1301 1198 if ( isset( $_POST['remote_data'] ) && function_exists( 'wp_http_validate_url' ) ) {
1302 1199 $remote_data = wp_http_validate_url( $_POST['remote_data'] );
1303 1200 }
1304 1201 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 - }
1202 + $source = new Visualizer_Source_Csv_Remote( $remote_data );
1311 1203 if ( isset( $_POST['vz-import-time'] ) ) {
1312 1204 apply_filters( 'visualizer_pro_chart_schedule', $chart_id, $remote_data, $_POST['vz-import-time'] );
1313 1205 }
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 - }
1206 + // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
1207 + } elseif ( isset( $_FILES['local_data'] ) && $_FILES['local_data']['error'] == 0 ) {
1208 + $source = new Visualizer_Source_Csv( $_FILES['local_data']['tmp_name'] );
1321 1209 } elseif ( isset( $_POST['chart_data'] ) && strlen( $_POST['chart_data'] ) > 0 ) {
1322 1210 $source = $this->handleCSVasString( $_POST['chart_data'], $_POST['editor-type'] );
1323 1211 update_post_meta( $chart_id, Visualizer_Plugin::CF_EDITOR, $_POST['editor-type'] );
1324 1212 } elseif ( isset( $_POST['table_data'] ) && 'yes' === $_POST['table_data'] ) {
@@ -1325,10 +1213,10 @@
1325 1213 $source = $this->handleTabularData();
1326 1214 update_post_meta( $chart_id, Visualizer_Plugin::CF_EDITOR, $_POST['editor-type'] );
1327 1215 } else {
1328 1216 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' ) );
1217 + $render->message = esc_html__( 'CSV file with chart data was not uploaded. Please try again.', 'visualizer' );
1218 + update_post_meta( $chart_id, Visualizer_Plugin::CF_ERROR, esc_html__( 'CSV file with chart data was not uploaded. Please try again.', 'visualizer' ) );
1331 1219 }
1332 1220
1333 1221 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 1222
@@ -1376,9 +1264,9 @@
1376 1264 $render->settings = json_encode( $settings );
1377 1265 } else {
1378 1266 $error = $source->get_error();
1379 1267 if ( empty( $error ) ) {
1380 - $error = esc_html__( 'The CSV file couldn\'t be read. Check that it\'s properly formatted and try again.', 'visualizer' );
1268 + $error = esc_html__( 'CSV file is broken or invalid. Please try again.', 'visualizer' );
1381 1269 }
1382 1270 $render->message = $error;
1383 1271 do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( '%s for chart %d.', $error, $chart_id ), 'error', __FILE__, __LINE__ );
1384 1272 update_post_meta( $chart_id, Visualizer_Plugin::CF_ERROR, $error );
@@ -1389,9 +1277,9 @@
1389 1277 $render->render();
1390 1278 if ( ! $can_die ) {
1391 1279 return;
1392 1280 }
1393 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1281 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1394 1282 }
1395 1283
1396 1284 /**
1397 1285 * Clones the chart.
@@ -1445,9 +1333,9 @@
1445 1333 );
1446 1334 }
1447 1335 }
1448 1336
1449 - if ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) {
1337 + if ( defined( 'WP_TESTS_DOMAIN' ) ) {
1450 1338 wp_die();
1451 1339 }
1452 1340 wp_redirect( $redirect );
1453 1341 exit;
@@ -1480,9 +1368,9 @@
1480 1368 }
1481 1369 }
1482 1370 }
1483 1371
1484 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1372 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1485 1373 }
1486 1374
1487 1375 /**
1488 1376 * Handles chart data page.
@@ -1506,11 +1394,10 @@
1506 1394 'visualizer-render',
1507 1395 'visualizer',
1508 1396 array(
1509 1397 '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' ),
1398 + 'invalid_source' => esc_html__( 'You have entered an invalid URL. Please provide a valid URL.', 'visualizer' ),
1399 + 'loading' => esc_html__( 'Loading...', 'visualizer' ),
1513 1400 ),
1514 1401 'charts' => array(
1515 1402 'canvas' => $data,
1516 1403 ),
@@ -1645,9 +1532,9 @@
1645 1532 }
1646 1533 }
1647 1534 $render->render();
1648 1535 if ( ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE ) ) {
1649 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1536 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1650 1537 }
1651 1538 }
1652 1539
1653 1540
@@ -1672,9 +1559,9 @@
1672 1559
1673 1560 $hours = filter_input(
1674 1561 INPUT_POST,
1675 1562 'refresh',
1676 - FILTER_VALIDATE_FLOAT,
1563 + FILTER_VALIDATE_INT,
1677 1564 array(
1678 1565 'options' => array(
1679 1566 'min_range' => -1,
1680 1567 'max_range' => apply_filters( 'visualizer_is_business', false ) ? PHP_INT_MAX : -1,
@@ -1681,9 +1568,9 @@
1681 1568 ),
1682 1569 )
1683 1570 );
1684 1571
1685 - if ( ! is_numeric( $hours ) ) {
1572 + if ( 0 !== $hours && empty( $hours ) ) {
1686 1573 $hours = -1;
1687 1574 }
1688 1575
1689 1576 do_action( 'visualizer_save_filter', $chart_id, $hours );
@@ -1688,9 +1575,9 @@
1688 1575
1689 1576 do_action( 'visualizer_save_filter', $chart_id, $hours );
1690 1577
1691 1578 if ( ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE ) ) {
1692 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1579 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1693 1580 }
1694 1581 }
1695 1582
1696 1583 /**