PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.10.7
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.10.7
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 +75 -215 4.0.53.10.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' );
@@ -767,9 +751,9 @@
767 751 'lineWrapping' => true,
768 752 'dragDrop' => false,
769 753 'matchBrackets' => true,
770 754 'autoCloseBrackets' => true,
771 - 'extraKeys' => array( 'Shift-Space' => 'autocomplete' ),
755 + 'extraKeys' => array( 'Ctrl-Space' => 'autocomplete' ),
772 756 'hintOptions' => array( 'tables' => $table_col_mapping ),
773 757 ),
774 758 )
775 759 );
@@ -803,12 +787,9 @@
803 787 update_option( 'visualizer-map-api-key', $_POST['map_api_key'] );
804 788 }
805 789
806 790 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 ) {
791 + if ( $this->_chart->post_status === 'auto-draft' ) {
811 792 $this->_chart->post_status = 'publish';
812 793
813 794 // 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 795 // we do not want any difference in data so disable revisions temporarily.
@@ -816,15 +797,10 @@
816 797
817 798 wp_update_post( $this->_chart->to_array() );
818 799 }
819 800 // 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 );
801 + if ( ! ( isset( $_POST['cancel'] ) && 1 === intval( $_POST['cancel'] ) ) ) {
802 + update_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SETTINGS, $_POST );
827 803
828 804 // we will keep a parameter called 'internal_title' that will be set to the given title or, if empty, the chart ID
829 805 // this will help in searching with the chart id.
830 806 $settings = get_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SETTINGS, true );
@@ -871,9 +847,8 @@
871 847 wp_enqueue_style( 'visualizer-frame' );
872 848 wp_enqueue_script( 'visualizer-preview' );
873 849 wp_enqueue_script( 'visualizer-chosen' );
874 850 wp_enqueue_script( 'visualizer-render' );
875 - wp_enqueue_code_editor( array( 'type' => 'application/json' ) );
876 851
877 852 if ( Visualizer_Module::can_show_feature( 'simple-editor' ) ) {
878 853 wp_enqueue_script( 'visualizer-editor-simple' );
879 854 wp_localize_script(
@@ -881,10 +856,12 @@
881 856 'visualizer1',
882 857 array(
883 858 'ajax' => array(
884 859 'url' => admin_url( 'admin-ajax.php' ),
885 - 'nonces' => array(),
886 - 'actions' => array(),
860 + 'nonces' => array(
861 + ),
862 + 'actions' => array(
863 + ),
887 864 ),
888 865 )
889 866 );
890 867 }
@@ -895,15 +872,13 @@
895 872 'visualizer-render',
896 873 'visualizer',
897 874 array(
898 875 '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' ),
876 + 'invalid_source' => esc_html__( 'You have entered an invalid URL. Please provide a valid URL.', 'visualizer' ),
877 + 'loading' => esc_html__( 'Loading...', 'visualizer' ),
878 + 'json_error' => esc_html__( 'An error occured in fetching data.', 'visualizer' ),
879 + 'select_columns' => esc_html__( 'Please select a few columns to include in the chart.', 'visualizer' ),
880 + '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 881 ),
907 882 'charts' => array(
908 883 'canvas' => $data,
909 884 'id' => $this->_chart->ID,
@@ -947,10 +922,11 @@
947 922 if ( filter_input( INPUT_GET, 'library', FILTER_VALIDATE_BOOLEAN ) ) {
948 923 $render->button = filter_input( INPUT_GET, 'action' ) === Visualizer_Plugin::ACTION_EDIT_CHART
949 924 ? esc_html__( 'Save Chart', 'visualizer' )
950 925 : esc_html__( 'Create Chart', 'visualizer' );
951 -
952 - $render->cancel_button = esc_html__( 'Cancel', 'visualizer' );
926 + if ( filter_input( INPUT_GET, 'action' ) === Visualizer_Plugin::ACTION_EDIT_CHART ) {
927 + $render->cancel_button = esc_html__( 'Cancel', 'visualizer' );
928 + }
953 929 } else {
954 930 $render->button = esc_attr__( 'Insert Chart', 'visualizer' );
955 931 }
956 932
@@ -973,9 +949,9 @@
973 949 * @access private
974 950 */
975 951 private function _handleTypesPage() {
976 952 // process post request
977 - if ( $_SERVER['REQUEST_METHOD'] === 'POST' && wp_verify_nonce( filter_input( INPUT_POST, 'nonce' ), 'visualizer-upload-data' ) ) {
953 + if ( $_SERVER['REQUEST_METHOD'] === 'POST' && wp_verify_nonce( filter_input( INPUT_POST, 'nonce' ) ) ) {
978 954 $type = filter_input( INPUT_POST, 'type' );
979 955 $library = filter_input( INPUT_POST, 'chart-library' );
980 956 if ( Visualizer_Module_Admin::checkChartStatus( $type ) ) {
981 957 if ( empty( $library ) ) {
@@ -1030,80 +1006,8 @@
1030 1006 * Processes the CSV that is sent in the request as a string.
1031 1007 *
1032 1008 * @since 3.2.0
1033 1009 */
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 1010 private function handleCSVasString( $data, $editor_type ) {
1107 1011 $source = null;
1108 1012
1109 1013 switch ( $editor_type ) {
@@ -1118,9 +1022,9 @@
1118 1022 continue;
1119 1023 }
1120 1024 $row = explode( ',', $row );
1121 1025 $row = array_map(
1122 - function ( $r ) {
1026 + function( $r ) {
1123 1027 return '' === $r ? ' ' : $r;
1124 1028 },
1125 1029 $row
1126 1030 );
@@ -1169,9 +1073,9 @@
1169 1073 foreach ( $types as $type ) {
1170 1074 if ( empty( $type ) ) {
1171 1075 $exclude[] = $index;
1172 1076 }
1173 - ++$index;
1077 + $index++;
1174 1078 }
1175 1079
1176 1080 // when N headers are being renamed, the number of headers increases by N
1177 1081 // because of the way datatable duplicates header information
@@ -1231,13 +1135,9 @@
1231 1135 // otherwise, assume this is a normal web request.
1232 1136 $can_die = ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE );
1233 1137
1234 1138 // validate nonce
1235 - if (
1236 - ! isset( $_GET['nonce'] ) ||
1237 - ! wp_verify_nonce( $_GET['nonce'], 'visualizer-upload-data' ) ||
1238 - ! current_user_can( 'edit_posts' )
1239 - ) {
1139 + if ( ! isset( $_GET['nonce'] ) || ! wp_verify_nonce( $_GET['nonce'] ) ) {
1240 1140 if ( ! $can_die ) {
1241 1141 return;
1242 1142 }
1243 1143 status_header( 403 );
@@ -1246,15 +1146,9 @@
1246 1146
1247 1147 // check chart, if chart exists
1248 1148 // do not use filter_input as it does not work for phpunit test cases, use filter_var instead
1249 1149 $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 - ) {
1150 + if ( ! $chart_id || ! ( $chart = get_post( $chart_id ) ) || $chart->post_type !== Visualizer_Plugin::CPT_VISUALIZER ) {
1257 1151 if ( ! $can_die ) {
1258 1152 return;
1259 1153 }
1260 1154 status_header( 400 );
@@ -1301,24 +1195,15 @@
1301 1195 if ( isset( $_POST['remote_data'] ) && function_exists( 'wp_http_validate_url' ) ) {
1302 1196 $remote_data = wp_http_validate_url( $_POST['remote_data'] );
1303 1197 }
1304 1198 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 - }
1199 + $source = new Visualizer_Source_Csv_Remote( $remote_data );
1311 1200 if ( isset( $_POST['vz-import-time'] ) ) {
1312 1201 apply_filters( 'visualizer_pro_chart_schedule', $chart_id, $remote_data, $_POST['vz-import-time'] );
1313 1202 }
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 - }
1203 + // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
1204 + } elseif ( isset( $_FILES['local_data'] ) && $_FILES['local_data']['error'] == 0 ) {
1205 + $source = new Visualizer_Source_Csv( $_FILES['local_data']['tmp_name'] );
1321 1206 } elseif ( isset( $_POST['chart_data'] ) && strlen( $_POST['chart_data'] ) > 0 ) {
1322 1207 $source = $this->handleCSVasString( $_POST['chart_data'], $_POST['editor-type'] );
1323 1208 update_post_meta( $chart_id, Visualizer_Plugin::CF_EDITOR, $_POST['editor-type'] );
1324 1209 } elseif ( isset( $_POST['table_data'] ) && 'yes' === $_POST['table_data'] ) {
@@ -1325,10 +1210,10 @@
1325 1210 $source = $this->handleTabularData();
1326 1211 update_post_meta( $chart_id, Visualizer_Plugin::CF_EDITOR, $_POST['editor-type'] );
1327 1212 } else {
1328 1213 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' ) );
1214 + $render->message = esc_html__( 'CSV file with chart data was not uploaded. Please try again.', 'visualizer' );
1215 + update_post_meta( $chart_id, Visualizer_Plugin::CF_ERROR, esc_html__( 'CSV file with chart data was not uploaded. Please try again.', 'visualizer' ) );
1331 1216 }
1332 1217
1333 1218 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 1219
@@ -1376,9 +1261,9 @@
1376 1261 $render->settings = json_encode( $settings );
1377 1262 } else {
1378 1263 $error = $source->get_error();
1379 1264 if ( empty( $error ) ) {
1380 - $error = esc_html__( 'The CSV file couldn\'t be read. Check that it\'s properly formatted and try again.', 'visualizer' );
1265 + $error = esc_html__( 'CSV file is broken or invalid. Please try again.', 'visualizer' );
1381 1266 }
1382 1267 $render->message = $error;
1383 1268 do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( '%s for chart %d.', $error, $chart_id ), 'error', __FILE__, __LINE__ );
1384 1269 update_post_meta( $chart_id, Visualizer_Plugin::CF_ERROR, $error );
@@ -1389,9 +1274,9 @@
1389 1274 $render->render();
1390 1275 if ( ! $can_die ) {
1391 1276 return;
1392 1277 }
1393 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1278 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1394 1279 }
1395 1280
1396 1281 /**
1397 1282 * Clones the chart.
@@ -1445,9 +1330,9 @@
1445 1330 );
1446 1331 }
1447 1332 }
1448 1333
1449 - if ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) {
1334 + if ( defined( 'WP_TESTS_DOMAIN' ) ) {
1450 1335 wp_die();
1451 1336 }
1452 1337 wp_redirect( $redirect );
1453 1338 exit;
@@ -1480,9 +1365,9 @@
1480 1365 }
1481 1366 }
1482 1367 }
1483 1368
1484 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1369 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1485 1370 }
1486 1371
1487 1372 /**
1488 1373 * Handles chart data page.
@@ -1506,11 +1391,10 @@
1506 1391 'visualizer-render',
1507 1392 'visualizer',
1508 1393 array(
1509 1394 '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' ),
1395 + 'invalid_source' => esc_html__( 'You have entered an invalid URL. Please provide a valid URL.', 'visualizer' ),
1396 + 'loading' => esc_html__( 'Loading...', 'visualizer' ),
1513 1397 ),
1514 1398 'charts' => array(
1515 1399 'canvas' => $data,
1516 1400 ),
@@ -1536,24 +1420,12 @@
1536 1420 */
1537 1421 public function getQueryData() {
1538 1422 check_ajax_referer( Visualizer_Plugin::ACTION_FETCH_DB_DATA . Visualizer_Plugin::VERSION, 'security' );
1539 1423
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 1424 $params = wp_parse_args( $_POST['params'] );
1552 1425 $chart_id = filter_var( $params['chart_id'], FILTER_VALIDATE_INT );
1553 - $query = trim( $params['query'], ';' );
1554 1426
1555 - $source = new Visualizer_Source_Query( stripslashes( $query ), $chart_id, $params );
1427 + $source = new Visualizer_Source_Query( stripslashes( $params['query'] ), $chart_id, $params );
1556 1428 $html = $source->fetch( true );
1557 1429 $error = $source->get_error();
1558 1430 if ( ! empty( $error ) ) {
1559 1431 wp_send_json_error( array( 'msg' => $error ) );
@@ -1568,19 +1440,8 @@
1568 1440 */
1569 1441 public function saveQuery() {
1570 1442 check_ajax_referer( Visualizer_Plugin::ACTION_SAVE_DB_QUERY . Visualizer_Plugin::VERSION, 'security' );
1571 1443
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 1444 $chart_id = filter_input(
1584 1445 INPUT_GET,
1585 1446 'chart',
1586 1447 FILTER_VALIDATE_INT,
@@ -1609,14 +1470,13 @@
1609 1470
1610 1471 $render = new Visualizer_Render_Page_Update();
1611 1472 if ( $chart_id ) {
1612 1473 $params = wp_parse_args( $_POST['params'] );
1613 - $query = trim( $params['query'], ';' );
1614 - $source = new Visualizer_Source_Query( stripslashes( $query ), $chart_id, $params );
1474 + $source = new Visualizer_Source_Query( stripslashes( $params['query'] ), $chart_id, $params );
1615 1475 $source->fetch( false );
1616 1476 $error = $source->get_error();
1617 1477 if ( empty( $error ) ) {
1618 - update_post_meta( $chart_id, Visualizer_Plugin::CF_DB_QUERY, stripslashes( $query ) );
1478 + update_post_meta( $chart_id, Visualizer_Plugin::CF_DB_QUERY, stripslashes( $params['query'] ) );
1619 1479 update_post_meta( $chart_id, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() );
1620 1480 update_post_meta( $chart_id, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
1621 1481 update_post_meta( $chart_id, Visualizer_Plugin::CF_DB_SCHEDULE, $hours );
1622 1482 update_post_meta( $chart_id, Visualizer_Plugin::CF_DEFAULT_DATA, 0 );
@@ -1645,9 +1505,9 @@
1645 1505 }
1646 1506 }
1647 1507 $render->render();
1648 1508 if ( ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE ) ) {
1649 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1509 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1650 1510 }
1651 1511 }
1652 1512
1653 1513
@@ -1672,9 +1532,9 @@
1672 1532
1673 1533 $hours = filter_input(
1674 1534 INPUT_POST,
1675 1535 'refresh',
1676 - FILTER_VALIDATE_FLOAT,
1536 + FILTER_VALIDATE_INT,
1677 1537 array(
1678 1538 'options' => array(
1679 1539 'min_range' => -1,
1680 1540 'max_range' => apply_filters( 'visualizer_is_business', false ) ? PHP_INT_MAX : -1,
@@ -1681,9 +1541,9 @@
1681 1541 ),
1682 1542 )
1683 1543 );
1684 1544
1685 - if ( ! is_numeric( $hours ) ) {
1545 + if ( 0 !== $hours && empty( $hours ) ) {
1686 1546 $hours = -1;
1687 1547 }
1688 1548
1689 1549 do_action( 'visualizer_save_filter', $chart_id, $hours );
@@ -1688,9 +1548,9 @@
1688 1548
1689 1549 do_action( 'visualizer_save_filter', $chart_id, $hours );
1690 1550
1691 1551 if ( ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE ) ) {
1692 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1552 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1693 1553 }
1694 1554 }
1695 1555
1696 1556 /**