PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.10.8
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.10.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 3.10.4 All 148 releases
← All changes | classes/Visualizer/Module/Chart.php +75 -207 4.0.43.10.8 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.
@@ -295,9 +296,9 @@
295 296 $render->data = json_encode( $source->getRawData( get_post_meta( $chart_id, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) ) );
296 297 $render->series = json_encode( $source->getSeries() );
297 298 $render->render();
298 299
299 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
300 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
300 301 }
301 302
302 303
303 304 /**
@@ -373,13 +374,13 @@
373 374 * @since 1.0.0
374 375 *
375 376 * @access private
376 377 *
377 - * @param WP_Post|null $chart The chart object.
378 + * @param WP_Post $chart The chart object.
378 379 *
379 380 * @return array The array of chart data.
380 381 */
381 - private function _getChartArray( $chart = null ) {
382 + private function _getChartArray( WP_Post $chart = null ) {
382 383 if ( is_null( $chart ) ) {
383 384 $chart = $this->_chart;
384 385 }
385 386 $type = get_post_meta( $chart->ID, Visualizer_Plugin::CF_CHART_TYPE, true );
@@ -401,13 +402,8 @@
401 402 }
402 403
403 404 $date_formats = Visualizer_Source::get_date_formats_if_exists( $series, $data );
404 405
405 - $code = '';
406 - if ( 'd3' === $library ) {
407 - $code = get_post_meta( $chart->ID, Visualizer_Module_AIBuilder::CF_D3_CODE, true );
408 - }
409 -
410 406 return array(
411 407 'type' => $type,
412 408 'series' => $series,
413 409 'settings' => $settings,
@@ -412,9 +408,8 @@
412 408 'series' => $series,
413 409 'settings' => $settings,
414 410 'data' => $data,
415 411 'library' => $library,
416 - 'code' => $code,
417 412 'css' => $css,
418 413 'date_formats' => $date_formats,
419 414 );
420 415 }
@@ -431,9 +426,9 @@
431 426 public static function _sendResponse( $results ) {
432 427 header( 'Content-type: application/json' );
433 428 nocache_headers();
434 429 echo json_encode( $results );
435 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
430 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
436 431 }
437 432
438 433 /**
439 434 * Deletes a chart from database.
@@ -528,12 +523,8 @@
528 523 *
529 524 * @access public
530 525 */
531 526 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 527 defined( 'IFRAME_REQUEST' ) || define( 'IFRAME_REQUEST', 1 );
537 528 if ( ! defined( 'ET_BUILDER_PRODUCT_VERSION' ) && function_exists( 'et_get_theme_version' ) ) {
538 529 define( 'ET_BUILDER_PRODUCT_VERSION', et_get_theme_version() );
539 530 }
@@ -543,10 +534,9 @@
543 534 $chart_id = isset( $_GET['chart'] ) ? filter_var( $_GET['chart'], FILTER_VALIDATE_INT ) : '';
544 535 if ( ! empty( $_POST ) ) {
545 536 $_POST = map_deep( $_POST, 'wp_strip_all_tags' );
546 537 }
547 - $chart = $chart_id ? get_post( $chart_id ) : null;
548 - 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 ) {
549 539 if ( empty( $_GET['lang'] ) || empty( $_GET['parent_chart_id'] ) ) {
550 540 $this->deleteOldCharts();
551 541 $default_type = isset( $_GET['type'] ) && ! empty( $_GET['type'] ) ? $_GET['type'] : 'line';
552 542 $chart_status = Visualizer_Module_Admin::checkChartStatus( $default_type );
@@ -580,33 +570,35 @@
580 570
581 571 do_action( 'visualizer_pro_new_chart_defaults', $chart_id );
582 572 }
583 573 } 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 - );
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 + );
600 591
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] ) );
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 + }
609 601 }
610 602 }
611 603 }
612 604 }
@@ -613,9 +605,9 @@
613 605 do_action( 'visualizer_pro_new_chart_defaults', $chart_id );
614 606 }
615 607 wp_redirect( esc_url_raw( add_query_arg( 'chart', (int) $chart_id ) ) );
616 608
617 - if ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) {
609 + if ( defined( 'WP_TESTS_DOMAIN' ) ) {
618 610 wp_die();
619 611 }
620 612 exit();
621 613 }
@@ -711,9 +703,9 @@
711 703 default:
712 704 // this should never happen.
713 705 break;
714 706 }
715 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
707 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
716 708 }
717 709
718 710 /**
719 711 * Load code editor assets.
@@ -743,9 +735,9 @@
743 735 wp_register_script( 'visualizer-codemirror-matchbrackets', '//codemirror.net/addon/edit/matchbrackets.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
744 736 wp_register_script( 'visualizer-codemirror-closebrackets', '//codemirror.net/addon/edit/closebrackets.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
745 737 wp_register_script( 'visualizer-codemirror-sql', '//codemirror.net/mode/sql/sql.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
746 738 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 );
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 );
748 740 wp_register_style( 'visualizer-codemirror-core', '//codemirror.net/lib/codemirror.css', array(), Visualizer_Plugin::VERSION );
749 741 wp_register_style( 'visualizer-codemirror-hint', '//codemirror.net/addon/hint/show-hint.css', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
750 742
751 743 wp_enqueue_script( 'visualizer-codemirror-hint' );
@@ -759,9 +751,9 @@
759 751 'lineWrapping' => true,
760 752 'dragDrop' => false,
761 753 'matchBrackets' => true,
762 754 'autoCloseBrackets' => true,
763 - 'extraKeys' => array( 'Shift-Space' => 'autocomplete' ),
755 + 'extraKeys' => array( 'Ctrl-Space' => 'autocomplete' ),
764 756 'hintOptions' => array( 'tables' => $table_col_mapping ),
765 757 ),
766 758 )
767 759 );
@@ -795,12 +787,9 @@
795 787 update_option( 'visualizer-map-api-key', $_POST['map_api_key'] );
796 788 }
797 789
798 790 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 ) {
791 + if ( $this->_chart->post_status === 'auto-draft' ) {
803 792 $this->_chart->post_status = 'publish';
804 793
805 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.
806 795 // we do not want any difference in data so disable revisions temporarily.
@@ -808,15 +797,10 @@
808 797
809 798 wp_update_post( $this->_chart->to_array() );
810 799 }
811 800 // 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 );
801 + if ( ! ( isset( $_POST['cancel'] ) && 1 === intval( $_POST['cancel'] ) ) ) {
802 + update_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SETTINGS, $_POST );
819 803
820 804 // we will keep a parameter called 'internal_title' that will be set to the given title or, if empty, the chart ID
821 805 // this will help in searching with the chart id.
822 806 $settings = get_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SETTINGS, true );
@@ -863,9 +847,8 @@
863 847 wp_enqueue_style( 'visualizer-frame' );
864 848 wp_enqueue_script( 'visualizer-preview' );
865 849 wp_enqueue_script( 'visualizer-chosen' );
866 850 wp_enqueue_script( 'visualizer-render' );
867 - wp_enqueue_code_editor( array( 'type' => 'application/json' ) );
868 851
869 852 if ( Visualizer_Module::can_show_feature( 'simple-editor' ) ) {
870 853 wp_enqueue_script( 'visualizer-editor-simple' );
871 854 wp_localize_script(
@@ -873,10 +856,12 @@
873 856 'visualizer1',
874 857 array(
875 858 'ajax' => array(
876 859 'url' => admin_url( 'admin-ajax.php' ),
877 - 'nonces' => array(),
878 - 'actions' => array(),
860 + 'nonces' => array(
861 + ),
862 + 'actions' => array(
863 + ),
879 864 ),
880 865 )
881 866 );
882 867 }
@@ -887,15 +872,13 @@
887 872 'visualizer-render',
888 873 'visualizer',
889 874 array(
890 875 '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' ),
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' ),
898 881 ),
899 882 'charts' => array(
900 883 'canvas' => $data,
901 884 'id' => $this->_chart->ID,
@@ -939,10 +922,11 @@
939 922 if ( filter_input( INPUT_GET, 'library', FILTER_VALIDATE_BOOLEAN ) ) {
940 923 $render->button = filter_input( INPUT_GET, 'action' ) === Visualizer_Plugin::ACTION_EDIT_CHART
941 924 ? esc_html__( 'Save Chart', 'visualizer' )
942 925 : esc_html__( 'Create Chart', 'visualizer' );
943 -
944 - $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 + }
945 929 } else {
946 930 $render->button = esc_attr__( 'Insert Chart', 'visualizer' );
947 931 }
948 932
@@ -965,9 +949,9 @@
965 949 * @access private
966 950 */
967 951 private function _handleTypesPage() {
968 952 // process post request
969 - 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' ) ) ) {
970 954 $type = filter_input( INPUT_POST, 'type' );
971 955 $library = filter_input( INPUT_POST, 'chart-library' );
972 956 if ( Visualizer_Module_Admin::checkChartStatus( $type ) ) {
973 957 if ( empty( $library ) ) {
@@ -1022,80 +1006,8 @@
1022 1006 * Processes the CSV that is sent in the request as a string.
1023 1007 *
1024 1008 * @since 3.2.0
1025 1009 */
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 1010 private function handleCSVasString( $data, $editor_type ) {
1099 1011 $source = null;
1100 1012
1101 1013 switch ( $editor_type ) {
@@ -1110,9 +1022,9 @@
1110 1022 continue;
1111 1023 }
1112 1024 $row = explode( ',', $row );
1113 1025 $row = array_map(
1114 - function ( $r ) {
1026 + function( $r ) {
1115 1027 return '' === $r ? ' ' : $r;
1116 1028 },
1117 1029 $row
1118 1030 );
@@ -1161,9 +1073,9 @@
1161 1073 foreach ( $types as $type ) {
1162 1074 if ( empty( $type ) ) {
1163 1075 $exclude[] = $index;
1164 1076 }
1165 - ++$index;
1077 + $index++;
1166 1078 }
1167 1079
1168 1080 // when N headers are being renamed, the number of headers increases by N
1169 1081 // because of the way datatable duplicates header information
@@ -1223,13 +1135,9 @@
1223 1135 // otherwise, assume this is a normal web request.
1224 1136 $can_die = ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE );
1225 1137
1226 1138 // validate nonce
1227 - if (
1228 - ! isset( $_GET['nonce'] ) ||
1229 - ! wp_verify_nonce( $_GET['nonce'], 'visualizer-upload-data' ) ||
1230 - ! current_user_can( 'edit_posts' )
1231 - ) {
1139 + if ( ! isset( $_GET['nonce'] ) || ! wp_verify_nonce( $_GET['nonce'] ) ) {
1232 1140 if ( ! $can_die ) {
1233 1141 return;
1234 1142 }
1235 1143 status_header( 403 );
@@ -1238,15 +1146,9 @@
1238 1146
1239 1147 // check chart, if chart exists
1240 1148 // do not use filter_input as it does not work for phpunit test cases, use filter_var instead
1241 1149 $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 - ) {
1150 + if ( ! $chart_id || ! ( $chart = get_post( $chart_id ) ) || $chart->post_type !== Visualizer_Plugin::CPT_VISUALIZER ) {
1249 1151 if ( ! $can_die ) {
1250 1152 return;
1251 1153 }
1252 1154 status_header( 400 );
@@ -1293,24 +1195,15 @@
1293 1195 if ( isset( $_POST['remote_data'] ) && function_exists( 'wp_http_validate_url' ) ) {
1294 1196 $remote_data = wp_http_validate_url( $_POST['remote_data'] );
1295 1197 }
1296 1198 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 - }
1199 + $source = new Visualizer_Source_Csv_Remote( $remote_data );
1303 1200 if ( isset( $_POST['vz-import-time'] ) ) {
1304 1201 apply_filters( 'visualizer_pro_chart_schedule', $chart_id, $remote_data, $_POST['vz-import-time'] );
1305 1202 }
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 - }
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'] );
1313 1206 } elseif ( isset( $_POST['chart_data'] ) && strlen( $_POST['chart_data'] ) > 0 ) {
1314 1207 $source = $this->handleCSVasString( $_POST['chart_data'], $_POST['editor-type'] );
1315 1208 update_post_meta( $chart_id, Visualizer_Plugin::CF_EDITOR, $_POST['editor-type'] );
1316 1209 } elseif ( isset( $_POST['table_data'] ) && 'yes' === $_POST['table_data'] ) {
@@ -1317,10 +1210,10 @@
1317 1210 $source = $this->handleTabularData();
1318 1211 update_post_meta( $chart_id, Visualizer_Plugin::CF_EDITOR, $_POST['editor-type'] );
1319 1212 } else {
1320 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__ );
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' ) );
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' ) );
1323 1216 }
1324 1217
1325 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__ );
1326 1219
@@ -1368,9 +1261,9 @@
1368 1261 $render->settings = json_encode( $settings );
1369 1262 } else {
1370 1263 $error = $source->get_error();
1371 1264 if ( empty( $error ) ) {
1372 - $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' );
1373 1266 }
1374 1267 $render->message = $error;
1375 1268 do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( '%s for chart %d.', $error, $chart_id ), 'error', __FILE__, __LINE__ );
1376 1269 update_post_meta( $chart_id, Visualizer_Plugin::CF_ERROR, $error );
@@ -1381,9 +1274,9 @@
1381 1274 $render->render();
1382 1275 if ( ! $can_die ) {
1383 1276 return;
1384 1277 }
1385 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1278 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1386 1279 }
1387 1280
1388 1281 /**
1389 1282 * Clones the chart.
@@ -1437,9 +1330,9 @@
1437 1330 );
1438 1331 }
1439 1332 }
1440 1333
1441 - if ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) {
1334 + if ( defined( 'WP_TESTS_DOMAIN' ) ) {
1442 1335 wp_die();
1443 1336 }
1444 1337 wp_redirect( $redirect );
1445 1338 exit;
@@ -1472,9 +1365,9 @@
1472 1365 }
1473 1366 }
1474 1367 }
1475 1368
1476 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1369 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1477 1370 }
1478 1371
1479 1372 /**
1480 1373 * Handles chart data page.
@@ -1498,11 +1391,10 @@
1498 1391 'visualizer-render',
1499 1392 'visualizer',
1500 1393 array(
1501 1394 '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' ),
1395 + 'invalid_source' => esc_html__( 'You have entered an invalid URL. Please provide a valid URL.', 'visualizer' ),
1396 + 'loading' => esc_html__( 'Loading...', 'visualizer' ),
1505 1397 ),
1506 1398 'charts' => array(
1507 1399 'canvas' => $data,
1508 1400 ),
@@ -1528,24 +1420,12 @@
1528 1420 */
1529 1421 public function getQueryData() {
1530 1422 check_ajax_referer( Visualizer_Plugin::ACTION_FETCH_DB_DATA . Visualizer_Plugin::VERSION, 'security' );
1531 1423
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 1424 $params = wp_parse_args( $_POST['params'] );
1544 1425 $chart_id = filter_var( $params['chart_id'], FILTER_VALIDATE_INT );
1545 - $query = trim( $params['query'], ';' );
1546 1426
1547 - $source = new Visualizer_Source_Query( stripslashes( $query ), $chart_id, $params );
1427 + $source = new Visualizer_Source_Query( stripslashes( $params['query'] ), $chart_id, $params );
1548 1428 $html = $source->fetch( true );
1549 1429 $error = $source->get_error();
1550 1430 if ( ! empty( $error ) ) {
1551 1431 wp_send_json_error( array( 'msg' => $error ) );
@@ -1560,19 +1440,8 @@
1560 1440 */
1561 1441 public function saveQuery() {
1562 1442 check_ajax_referer( Visualizer_Plugin::ACTION_SAVE_DB_QUERY . Visualizer_Plugin::VERSION, 'security' );
1563 1443
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 1444 $chart_id = filter_input(
1576 1445 INPUT_GET,
1577 1446 'chart',
1578 1447 FILTER_VALIDATE_INT,
@@ -1601,14 +1470,13 @@
1601 1470
1602 1471 $render = new Visualizer_Render_Page_Update();
1603 1472 if ( $chart_id ) {
1604 1473 $params = wp_parse_args( $_POST['params'] );
1605 - $query = trim( $params['query'], ';' );
1606 - $source = new Visualizer_Source_Query( stripslashes( $query ), $chart_id, $params );
1474 + $source = new Visualizer_Source_Query( stripslashes( $params['query'] ), $chart_id, $params );
1607 1475 $source->fetch( false );
1608 1476 $error = $source->get_error();
1609 1477 if ( empty( $error ) ) {
1610 - 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'] ) );
1611 1479 update_post_meta( $chart_id, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() );
1612 1480 update_post_meta( $chart_id, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
1613 1481 update_post_meta( $chart_id, Visualizer_Plugin::CF_DB_SCHEDULE, $hours );
1614 1482 update_post_meta( $chart_id, Visualizer_Plugin::CF_DEFAULT_DATA, 0 );
@@ -1637,9 +1505,9 @@
1637 1505 }
1638 1506 }
1639 1507 $render->render();
1640 1508 if ( ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE ) ) {
1641 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1509 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1642 1510 }
1643 1511 }
1644 1512
1645 1513
@@ -1664,9 +1532,9 @@
1664 1532
1665 1533 $hours = filter_input(
1666 1534 INPUT_POST,
1667 1535 'refresh',
1668 - FILTER_VALIDATE_FLOAT,
1536 + FILTER_VALIDATE_INT,
1669 1537 array(
1670 1538 'options' => array(
1671 1539 'min_range' => -1,
1672 1540 'max_range' => apply_filters( 'visualizer_is_business', false ) ? PHP_INT_MAX : -1,
@@ -1673,9 +1541,9 @@
1673 1541 ),
1674 1542 )
1675 1543 );
1676 1544
1677 - if ( ! is_numeric( $hours ) ) {
1545 + if ( 0 !== $hours && empty( $hours ) ) {
1678 1546 $hours = -1;
1679 1547 }
1680 1548
1681 1549 do_action( 'visualizer_save_filter', $chart_id, $hours );
@@ -1680,9 +1548,9 @@
1680 1548
1681 1549 do_action( 'visualizer_save_filter', $chart_id, $hours );
1682 1550
1683 1551 if ( ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE ) ) {
1684 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1552 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1685 1553 }
1686 1554 }
1687 1555
1688 1556 /**