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.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 +76 -216 4.0.43.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.
@@ -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,17 +534,12 @@
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 - $chart_status = Visualizer_Module_Admin::checkChartStatus( $default_type );
553 - if ( ! $chart_status ) {
554 - $default_type = 'line';
555 - }
556 542 $source = new Visualizer_Source_Csv( VISUALIZER_ABSPATH . DIRECTORY_SEPARATOR . 'samples' . DIRECTORY_SEPARATOR . $default_type . '.csv' );
557 543 $source->fetch();
558 544 $chart_id = wp_insert_post(
559 545 array(
@@ -580,33 +566,35 @@
580 566
581 567 do_action( 'visualizer_pro_new_chart_defaults', $chart_id );
582 568 }
583 569 } 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 - );
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 + );
600 587
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] ) );
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 + }
609 597 }
610 598 }
611 599 }
612 600 }
@@ -613,9 +601,9 @@
613 601 do_action( 'visualizer_pro_new_chart_defaults', $chart_id );
614 602 }
615 603 wp_redirect( esc_url_raw( add_query_arg( 'chart', (int) $chart_id ) ) );
616 604
617 - if ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) {
605 + if ( defined( 'WP_TESTS_DOMAIN' ) ) {
618 606 wp_die();
619 607 }
620 608 exit();
621 609 }
@@ -711,9 +699,9 @@
711 699 default:
712 700 // this should never happen.
713 701 break;
714 702 }
715 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
703 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
716 704 }
717 705
718 706 /**
719 707 * Load code editor assets.
@@ -743,9 +731,9 @@
743 731 wp_register_script( 'visualizer-codemirror-matchbrackets', '//codemirror.net/addon/edit/matchbrackets.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
744 732 wp_register_script( 'visualizer-codemirror-closebrackets', '//codemirror.net/addon/edit/closebrackets.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
745 733 wp_register_script( 'visualizer-codemirror-sql', '//codemirror.net/mode/sql/sql.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
746 734 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 );
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 );
748 736 wp_register_style( 'visualizer-codemirror-core', '//codemirror.net/lib/codemirror.css', array(), Visualizer_Plugin::VERSION );
749 737 wp_register_style( 'visualizer-codemirror-hint', '//codemirror.net/addon/hint/show-hint.css', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
750 738
751 739 wp_enqueue_script( 'visualizer-codemirror-hint' );
@@ -759,9 +747,9 @@
759 747 'lineWrapping' => true,
760 748 'dragDrop' => false,
761 749 'matchBrackets' => true,
762 750 'autoCloseBrackets' => true,
763 - 'extraKeys' => array( 'Shift-Space' => 'autocomplete' ),
751 + 'extraKeys' => array( 'Ctrl-Space' => 'autocomplete' ),
764 752 'hintOptions' => array( 'tables' => $table_col_mapping ),
765 753 ),
766 754 )
767 755 );
@@ -795,12 +783,9 @@
795 783 update_option( 'visualizer-map-api-key', $_POST['map_api_key'] );
796 784 }
797 785
798 786 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 ) {
787 + if ( $this->_chart->post_status === 'auto-draft' ) {
803 788 $this->_chart->post_status = 'publish';
804 789
805 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.
806 791 // we do not want any difference in data so disable revisions temporarily.
@@ -808,15 +793,10 @@
808 793
809 794 wp_update_post( $this->_chart->to_array() );
810 795 }
811 796 // 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 );
797 + if ( ! ( isset( $_POST['cancel'] ) && 1 === intval( $_POST['cancel'] ) ) ) {
798 + update_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SETTINGS, $_POST );
819 799
820 800 // we will keep a parameter called 'internal_title' that will be set to the given title or, if empty, the chart ID
821 801 // this will help in searching with the chart id.
822 802 $settings = get_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SETTINGS, true );
@@ -863,9 +843,8 @@
863 843 wp_enqueue_style( 'visualizer-frame' );
864 844 wp_enqueue_script( 'visualizer-preview' );
865 845 wp_enqueue_script( 'visualizer-chosen' );
866 846 wp_enqueue_script( 'visualizer-render' );
867 - wp_enqueue_code_editor( array( 'type' => 'application/json' ) );
868 847
869 848 if ( Visualizer_Module::can_show_feature( 'simple-editor' ) ) {
870 849 wp_enqueue_script( 'visualizer-editor-simple' );
871 850 wp_localize_script(
@@ -873,10 +852,12 @@
873 852 'visualizer1',
874 853 array(
875 854 'ajax' => array(
876 855 'url' => admin_url( 'admin-ajax.php' ),
877 - 'nonces' => array(),
878 - 'actions' => array(),
856 + 'nonces' => array(
857 + ),
858 + 'actions' => array(
859 + ),
879 860 ),
880 861 )
881 862 );
882 863 }
@@ -887,15 +868,13 @@
887 868 'visualizer-render',
888 869 'visualizer',
889 870 array(
890 871 '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' ),
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' ),
898 877 ),
899 878 'charts' => array(
900 879 'canvas' => $data,
901 880 'id' => $this->_chart->ID,
@@ -939,10 +918,11 @@
939 918 if ( filter_input( INPUT_GET, 'library', FILTER_VALIDATE_BOOLEAN ) ) {
940 919 $render->button = filter_input( INPUT_GET, 'action' ) === Visualizer_Plugin::ACTION_EDIT_CHART
941 920 ? esc_html__( 'Save Chart', 'visualizer' )
942 921 : esc_html__( 'Create Chart', 'visualizer' );
943 -
944 - $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 + }
945 925 } else {
946 926 $render->button = esc_attr__( 'Insert Chart', 'visualizer' );
947 927 }
948 928
@@ -965,12 +945,12 @@
965 945 * @access private
966 946 */
967 947 private function _handleTypesPage() {
968 948 // process post request
969 - 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' ) ) ) {
970 950 $type = filter_input( INPUT_POST, 'type' );
971 951 $library = filter_input( INPUT_POST, 'chart-library' );
972 - if ( Visualizer_Module_Admin::checkChartStatus( $type ) ) {
952 + if ( in_array( $type, Visualizer_Plugin::getChartTypes(), true ) ) {
973 953 if ( empty( $library ) ) {
974 954 // library cannot be empty.
975 955 do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, 'Chart library empty while creating the chart! Aborting...', 'error', __FILE__, __LINE__ );
976 956 return;
@@ -1022,80 +1002,8 @@
1022 1002 * Processes the CSV that is sent in the request as a string.
1023 1003 *
1024 1004 * @since 3.2.0
1025 1005 */
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 1006 private function handleCSVasString( $data, $editor_type ) {
1099 1007 $source = null;
1100 1008
1101 1009 switch ( $editor_type ) {
@@ -1110,9 +1018,9 @@
1110 1018 continue;
1111 1019 }
1112 1020 $row = explode( ',', $row );
1113 1021 $row = array_map(
1114 - function ( $r ) {
1022 + function( $r ) {
1115 1023 return '' === $r ? ' ' : $r;
1116 1024 },
1117 1025 $row
1118 1026 );
@@ -1161,9 +1069,9 @@
1161 1069 foreach ( $types as $type ) {
1162 1070 if ( empty( $type ) ) {
1163 1071 $exclude[] = $index;
1164 1072 }
1165 - ++$index;
1073 + $index++;
1166 1074 }
1167 1075
1168 1076 // when N headers are being renamed, the number of headers increases by N
1169 1077 // because of the way datatable duplicates header information
@@ -1223,13 +1131,9 @@
1223 1131 // otherwise, assume this is a normal web request.
1224 1132 $can_die = ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE );
1225 1133
1226 1134 // validate nonce
1227 - if (
1228 - ! isset( $_GET['nonce'] ) ||
1229 - ! wp_verify_nonce( $_GET['nonce'], 'visualizer-upload-data' ) ||
1230 - ! current_user_can( 'edit_posts' )
1231 - ) {
1135 + if ( ! isset( $_GET['nonce'] ) || ! wp_verify_nonce( $_GET['nonce'] ) ) {
1232 1136 if ( ! $can_die ) {
1233 1137 return;
1234 1138 }
1235 1139 status_header( 403 );
@@ -1238,15 +1142,9 @@
1238 1142
1239 1143 // check chart, if chart exists
1240 1144 // do not use filter_input as it does not work for phpunit test cases, use filter_var instead
1241 1145 $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 - ) {
1146 + if ( ! $chart_id || ! ( $chart = get_post( $chart_id ) ) || $chart->post_type !== Visualizer_Plugin::CPT_VISUALIZER ) {
1249 1147 if ( ! $can_die ) {
1250 1148 return;
1251 1149 }
1252 1150 status_header( 400 );
@@ -1293,24 +1191,15 @@
1293 1191 if ( isset( $_POST['remote_data'] ) && function_exists( 'wp_http_validate_url' ) ) {
1294 1192 $remote_data = wp_http_validate_url( $_POST['remote_data'] );
1295 1193 }
1296 1194 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 - }
1195 + $source = new Visualizer_Source_Csv_Remote( $remote_data );
1303 1196 if ( isset( $_POST['vz-import-time'] ) ) {
1304 1197 apply_filters( 'visualizer_pro_chart_schedule', $chart_id, $remote_data, $_POST['vz-import-time'] );
1305 1198 }
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 - }
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'] );
1313 1202 } elseif ( isset( $_POST['chart_data'] ) && strlen( $_POST['chart_data'] ) > 0 ) {
1314 1203 $source = $this->handleCSVasString( $_POST['chart_data'], $_POST['editor-type'] );
1315 1204 update_post_meta( $chart_id, Visualizer_Plugin::CF_EDITOR, $_POST['editor-type'] );
1316 1205 } elseif ( isset( $_POST['table_data'] ) && 'yes' === $_POST['table_data'] ) {
@@ -1317,10 +1206,10 @@
1317 1206 $source = $this->handleTabularData();
1318 1207 update_post_meta( $chart_id, Visualizer_Plugin::CF_EDITOR, $_POST['editor-type'] );
1319 1208 } else {
1320 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__ );
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' ) );
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' ) );
1323 1212 }
1324 1213
1325 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__ );
1326 1215
@@ -1368,9 +1257,9 @@
1368 1257 $render->settings = json_encode( $settings );
1369 1258 } else {
1370 1259 $error = $source->get_error();
1371 1260 if ( empty( $error ) ) {
1372 - $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' );
1373 1262 }
1374 1263 $render->message = $error;
1375 1264 do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( '%s for chart %d.', $error, $chart_id ), 'error', __FILE__, __LINE__ );
1376 1265 update_post_meta( $chart_id, Visualizer_Plugin::CF_ERROR, $error );
@@ -1381,9 +1270,9 @@
1381 1270 $render->render();
1382 1271 if ( ! $can_die ) {
1383 1272 return;
1384 1273 }
1385 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1274 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1386 1275 }
1387 1276
1388 1277 /**
1389 1278 * Clones the chart.
@@ -1437,9 +1326,9 @@
1437 1326 );
1438 1327 }
1439 1328 }
1440 1329
1441 - if ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) {
1330 + if ( defined( 'WP_TESTS_DOMAIN' ) ) {
1442 1331 wp_die();
1443 1332 }
1444 1333 wp_redirect( $redirect );
1445 1334 exit;
@@ -1472,9 +1361,9 @@
1472 1361 }
1473 1362 }
1474 1363 }
1475 1364
1476 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1365 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1477 1366 }
1478 1367
1479 1368 /**
1480 1369 * Handles chart data page.
@@ -1498,11 +1387,10 @@
1498 1387 'visualizer-render',
1499 1388 'visualizer',
1500 1389 array(
1501 1390 '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' ),
1391 + 'invalid_source' => esc_html__( 'You have entered an invalid URL. Please provide a valid URL.', 'visualizer' ),
1392 + 'loading' => esc_html__( 'Loading...', 'visualizer' ),
1505 1393 ),
1506 1394 'charts' => array(
1507 1395 'canvas' => $data,
1508 1396 ),
@@ -1528,24 +1416,12 @@
1528 1416 */
1529 1417 public function getQueryData() {
1530 1418 check_ajax_referer( Visualizer_Plugin::ACTION_FETCH_DB_DATA . Visualizer_Plugin::VERSION, 'security' );
1531 1419
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 1420 $params = wp_parse_args( $_POST['params'] );
1544 1421 $chart_id = filter_var( $params['chart_id'], FILTER_VALIDATE_INT );
1545 - $query = trim( $params['query'], ';' );
1546 1422
1547 - $source = new Visualizer_Source_Query( stripslashes( $query ), $chart_id, $params );
1423 + $source = new Visualizer_Source_Query( stripslashes( $params['query'] ), $chart_id, $params );
1548 1424 $html = $source->fetch( true );
1549 1425 $error = $source->get_error();
1550 1426 if ( ! empty( $error ) ) {
1551 1427 wp_send_json_error( array( 'msg' => $error ) );
@@ -1560,19 +1436,8 @@
1560 1436 */
1561 1437 public function saveQuery() {
1562 1438 check_ajax_referer( Visualizer_Plugin::ACTION_SAVE_DB_QUERY . Visualizer_Plugin::VERSION, 'security' );
1563 1439
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 1440 $chart_id = filter_input(
1576 1441 INPUT_GET,
1577 1442 'chart',
1578 1443 FILTER_VALIDATE_INT,
@@ -1601,14 +1466,13 @@
1601 1466
1602 1467 $render = new Visualizer_Render_Page_Update();
1603 1468 if ( $chart_id ) {
1604 1469 $params = wp_parse_args( $_POST['params'] );
1605 - $query = trim( $params['query'], ';' );
1606 - $source = new Visualizer_Source_Query( stripslashes( $query ), $chart_id, $params );
1470 + $source = new Visualizer_Source_Query( stripslashes( $params['query'] ), $chart_id, $params );
1607 1471 $source->fetch( false );
1608 1472 $error = $source->get_error();
1609 1473 if ( empty( $error ) ) {
1610 - 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'] ) );
1611 1475 update_post_meta( $chart_id, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() );
1612 1476 update_post_meta( $chart_id, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
1613 1477 update_post_meta( $chart_id, Visualizer_Plugin::CF_DB_SCHEDULE, $hours );
1614 1478 update_post_meta( $chart_id, Visualizer_Plugin::CF_DEFAULT_DATA, 0 );
@@ -1637,9 +1501,9 @@
1637 1501 }
1638 1502 }
1639 1503 $render->render();
1640 1504 if ( ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE ) ) {
1641 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1505 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1642 1506 }
1643 1507 }
1644 1508
1645 1509
@@ -1664,9 +1528,9 @@
1664 1528
1665 1529 $hours = filter_input(
1666 1530 INPUT_POST,
1667 1531 'refresh',
1668 - FILTER_VALIDATE_FLOAT,
1532 + FILTER_VALIDATE_INT,
1669 1533 array(
1670 1534 'options' => array(
1671 1535 'min_range' => -1,
1672 1536 'max_range' => apply_filters( 'visualizer_is_business', false ) ? PHP_INT_MAX : -1,
@@ -1673,9 +1537,9 @@
1673 1537 ),
1674 1538 )
1675 1539 );
1676 1540
1677 - if ( ! is_numeric( $hours ) ) {
1541 + if ( 0 !== $hours && empty( $hours ) ) {
1678 1542 $hours = -1;
1679 1543 }
1680 1544
1681 1545 do_action( 'visualizer_save_filter', $chart_id, $hours );
@@ -1680,9 +1544,9 @@
1680 1544
1681 1545 do_action( 'visualizer_save_filter', $chart_id, $hours );
1682 1546
1683 1547 if ( ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE ) ) {
1684 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1548 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1685 1549 }
1686 1550 }
1687 1551
1688 1552 /**
@@ -1718,12 +1582,8 @@
1718 1582 // Save the image in the uploads directory.
1719 1583 require_once ABSPATH . '/wp-admin/includes/file.php';
1720 1584 \WP_Filesystem();
1721 1585 global $wp_filesystem;
1722 - if ( ! is_a( $wp_filesystem, 'WP_Filesystem_Base' ) ) {
1723 - $creds = request_filesystem_credentials( site_url() );
1724 - wp_filesystem( $creds );
1725 - }
1726 1586 $upload_file = $wp_filesystem->put_contents( $upload_path . $hashed_filename, $decoded );
1727 1587
1728 1588 // Insert new chart image.
1729 1589 $attachment = array(