PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.4.7
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.4.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 +87 -424 4.0.53.4.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.
@@ -133,30 +134,12 @@
133 134 ),
134 135 )
135 136 );
136 137
137 - if ( Visualizer_Module::is_pro() ) {
138 - $is_woocommerce_report = filter_input(
139 - INPUT_POST,
140 - 'is_woocommerce_report',
141 - FILTER_VALIDATE_BOOLEAN
142 - );
143 -
144 - if ( $is_woocommerce_report ) {
145 - update_post_meta( $chart_id, Visualizer_Plugin::CF_IS_WOOCOMMERCE_SOURCE, true );
146 - } else {
147 - delete_post_meta( $chart_id, Visualizer_Plugin::CF_IS_WOOCOMMERCE_SOURCE );
148 - }
149 - }
150 -
151 138 delete_post_meta( $chart_id, Visualizer_Plugin::CF_JSON_SCHEDULE );
152 139
153 140 if ( -1 < $time ) {
154 141 add_post_meta( $chart_id, Visualizer_Plugin::CF_JSON_SCHEDULE, $time );
155 - // Update schedules.
156 - $schedules = get_option( Visualizer_Plugin::CF_JSON_SCHEDULE, array() );
157 - $schedules[ $chart_id ] = time() + $time * HOUR_IN_SECONDS;
158 - update_option( Visualizer_Plugin::CF_JSON_SCHEDULE, $schedules );
159 142 }
160 143 wp_send_json_success();
161 144 }
162 145
@@ -169,12 +152,8 @@
169 152 */
170 153 public function getJsonRoots() {
171 154 check_ajax_referer( Visualizer_Plugin::ACTION_JSON_GET_ROOTS . Visualizer_Plugin::VERSION, 'security' );
172 155
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 156 $params = wp_parse_args( $_POST['params'] );
178 157
179 158 $source = new Visualizer_Source_Json( $params );
180 159
@@ -195,12 +174,8 @@
195 174 */
196 175 public function getJsonData() {
197 176 check_ajax_referer( Visualizer_Plugin::ACTION_JSON_GET_DATA . Visualizer_Plugin::VERSION, 'security' );
198 177
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 178 $params = wp_parse_args( $_POST['params'] );
204 179
205 180 $chart_id = $params['chart'];
206 181
@@ -266,16 +241,8 @@
266 241 if ( ! empty( $params['paging'] ) ) {
267 242 add_post_meta( $chart->ID, Visualizer_Plugin::CF_JSON_PAGING, $params['paging'] );
268 243 }
269 244
270 - if ( Visualizer_Module::is_pro() ) {
271 - if ( ! empty( $params['vz_woo_source'] ) ) {
272 - update_post_meta( $chart->ID, Visualizer_Plugin::CF_JSON_WOOCOMMERCE_SOURCE, $params['vz_woo_source'] );
273 - } else {
274 - delete_post_meta( $chart->ID, Visualizer_Plugin::CF_JSON_WOOCOMMERCE_SOURCE );
275 - }
276 - }
277 -
278 245 $time = filter_input(
279 246 INPUT_POST,
280 247 'time',
281 248 FILTER_VALIDATE_INT,
@@ -303,9 +270,9 @@
303 270 $render->data = json_encode( $source->getRawData( get_post_meta( $chart_id, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) ) );
304 271 $render->series = json_encode( $source->getSeries() );
305 272 $render->render();
306 273
307 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
274 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
308 275 }
309 276
310 277
311 278 /**
@@ -381,13 +348,13 @@
381 348 * @since 1.0.0
382 349 *
383 350 * @access private
384 351 *
385 - * @param WP_Post|null $chart The chart object.
352 + * @param WP_Post $chart The chart object.
386 353 *
387 354 * @return array The array of chart data.
388 355 */
389 - private function _getChartArray( $chart = null ) {
356 + private function _getChartArray( WP_Post $chart = null ) {
390 357 if ( is_null( $chart ) ) {
391 358 $chart = $this->_chart;
392 359 }
393 360 $type = get_post_meta( $chart->ID, Visualizer_Plugin::CF_CHART_TYPE, true );
@@ -409,13 +376,8 @@
409 376 }
410 377
411 378 $date_formats = Visualizer_Source::get_date_formats_if_exists( $series, $data );
412 379
413 - $code = '';
414 - if ( 'd3' === $library ) {
415 - $code = get_post_meta( $chart->ID, Visualizer_Module_AIBuilder::CF_D3_CODE, true );
416 - }
417 -
418 380 return array(
419 381 'type' => $type,
420 382 'series' => $series,
421 383 'settings' => $settings,
@@ -420,9 +382,8 @@
420 382 'series' => $series,
421 383 'settings' => $settings,
422 384 'data' => $data,
423 385 'library' => $library,
424 - 'code' => $code,
425 386 'css' => $css,
426 387 'date_formats' => $date_formats,
427 388 );
428 389 }
@@ -439,9 +400,9 @@
439 400 public static function _sendResponse( $results ) {
440 401 header( 'Content-type: application/json' );
441 402 nocache_headers();
442 403 echo json_encode( $results );
443 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
404 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
444 405 }
445 406
446 407 /**
447 408 * Deletes a chart from database.
@@ -473,22 +434,9 @@
473 434 $success = $chart && $chart->post_type === Visualizer_Plugin::CPT_VISUALIZER;
474 435 }
475 436 }
476 437 if ( $success ) {
477 - global $sitepress;
478 - if ( Visualizer_Module::is_pro() && ( function_exists( 'icl_get_languages' ) && $sitepress instanceof \SitePress ) ) {
479 - $trid = $sitepress->get_element_trid( $chart_id, 'post_' . Visualizer_Plugin::CPT_VISUALIZER );
480 - $translations = $sitepress->get_element_translations( $trid );
481 - if ( ! empty( $translations ) ) {
482 - foreach ( $translations as $translated_post ) {
483 - wp_delete_post( $translated_post->element_id, true );
484 - }
485 - } else {
486 - wp_delete_post( $chart_id, true );
487 - }
488 - } else {
489 - wp_delete_post( $chart_id, true );
490 - }
438 + wp_delete_post( $chart_id, true );
491 439 }
492 440 if ( $is_post ) {
493 441 self::_sendResponse(
494 442 array(
@@ -536,108 +484,44 @@
536 484 *
537 485 * @access public
538 486 */
539 487 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 488 defined( 'IFRAME_REQUEST' ) || define( 'IFRAME_REQUEST', 1 );
545 - if ( ! defined( 'ET_BUILDER_PRODUCT_VERSION' ) && function_exists( 'et_get_theme_version' ) ) {
546 - define( 'ET_BUILDER_PRODUCT_VERSION', et_get_theme_version() );
547 - }
548 - // Set current screen for the render chart.
549 - set_current_screen( 'visualizer_render_chart' );
550 489 // check chart, if chart not exists, will create new one and redirects to the same page with proper chart id
551 490 $chart_id = isset( $_GET['chart'] ) ? filter_var( $_GET['chart'], FILTER_VALIDATE_INT ) : '';
552 - if ( ! empty( $_POST ) ) {
553 - $_POST = map_deep( $_POST, 'wp_strip_all_tags' );
554 - }
555 - $chart = $chart_id ? get_post( $chart_id ) : null;
556 - if ( ! $chart_id || ! $chart || $chart->post_type !== Visualizer_Plugin::CPT_VISUALIZER ) {
557 - if ( empty( $_GET['lang'] ) || empty( $_GET['parent_chart_id'] ) ) {
558 - $this->deleteOldCharts();
559 - $default_type = isset( $_GET['type'] ) && ! empty( $_GET['type'] ) ? $_GET['type'] : 'line';
560 - $chart_status = Visualizer_Module_Admin::checkChartStatus( $default_type );
561 - if ( ! $chart_status ) {
562 - $default_type = 'line';
563 - }
564 - $source = new Visualizer_Source_Csv( VISUALIZER_ABSPATH . DIRECTORY_SEPARATOR . 'samples' . DIRECTORY_SEPARATOR . $default_type . '.csv' );
565 - $source->fetch();
566 - $chart_id = wp_insert_post(
491 + if ( ! $chart_id || ! ( $chart = get_post( $chart_id ) ) || $chart->post_type !== Visualizer_Plugin::CPT_VISUALIZER ) {
492 + $this->deleteOldCharts();
493 + $default_type = isset( $_GET['type'] ) && ! empty( $_GET['type'] ) ? $_GET['type'] : 'line';
494 + $source = new Visualizer_Source_Csv( VISUALIZER_ABSPATH . DIRECTORY_SEPARATOR . 'samples' . DIRECTORY_SEPARATOR . $default_type . '.csv' );
495 + $source->fetch();
496 + $chart_id = wp_insert_post(
497 + array(
498 + 'post_type' => Visualizer_Plugin::CPT_VISUALIZER,
499 + 'post_title' => 'Visualization',
500 + 'post_author' => get_current_user_id(),
501 + 'post_status' => 'auto-draft',
502 + 'post_content' => $source->getData( get_post_meta( $chart_id, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) ),
503 + )
504 + );
505 + if ( $chart_id && ! is_wp_error( $chart_id ) ) {
506 + add_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_TYPE, $default_type );
507 + add_post_meta( $chart_id, Visualizer_Plugin::CF_DEFAULT_DATA, 1 );
508 + add_post_meta( $chart_id, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() );
509 + add_post_meta( $chart_id, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
510 + add_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_LIBRARY, '' );
511 + add_post_meta(
512 + $chart_id,
513 + Visualizer_Plugin::CF_SETTINGS,
567 514 array(
568 - 'post_type' => Visualizer_Plugin::CPT_VISUALIZER,
569 - 'post_title' => 'Visualization',
570 - 'post_author' => get_current_user_id(),
571 - 'post_status' => 'auto-draft',
572 - 'post_content' => $source->getData( get_post_meta( $chart_id, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) ),
515 + 'focusTarget' => 'datum',
573 516 )
574 517 );
575 - if ( $chart_id && ! is_wp_error( $chart_id ) ) {
576 - add_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_TYPE, $default_type );
577 - add_post_meta( $chart_id, Visualizer_Plugin::CF_DEFAULT_DATA, 1 );
578 - add_post_meta( $chart_id, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() );
579 - add_post_meta( $chart_id, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
580 - add_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_LIBRARY, '' );
581 - add_post_meta(
582 - $chart_id,
583 - Visualizer_Plugin::CF_SETTINGS,
584 - array(
585 - 'focusTarget' => 'datum',
586 - )
587 - );
588 -
589 - do_action( 'visualizer_pro_new_chart_defaults', $chart_id );
590 - }
591 - } 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 - );
608 -
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] ) );
617 - }
618 - }
619 - }
620 - }
621 518 do_action( 'visualizer_pro_new_chart_defaults', $chart_id );
622 519 }
623 - wp_redirect( esc_url_raw( add_query_arg( 'chart', (int) $chart_id ) ) );
624 -
625 - if ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) {
626 - wp_die();
627 - }
628 - exit();
520 + wp_redirect( add_query_arg( 'chart', (int) $chart_id ) );
521 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
629 522 }
630 523
631 - $_POST['save_chart_image'] = isset( $_POST['save_chart_image'] ) && 'yes' === $_POST['save_chart_image'] ? true : false;
632 - $_POST['lazy_load_chart'] = isset( $_POST['lazy_load_chart'] ) && 'yes' === $_POST['lazy_load_chart'] ? true : false;
633 -
634 - if ( isset( $_POST['chart-img'] ) && ! empty( $_POST['chart-img'] ) ) {
635 - $attachment_id = $this->save_chart_image( $_POST['chart-img'], $chart_id, $_POST['save_chart_image'] );
636 - if ( $attachment_id ) {
637 - update_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_IMAGE, $attachment_id );
638 - }
639 - }
640 524 $lib = $this->load_chart_type( $chart_id );
641 525
642 526 // the alpha color picker (RGBA) is not supported by google.
643 527 $color_picker_dep = 'wp-color-picker';
@@ -699,16 +583,8 @@
699 583 // if the edit button is clicked.
700 584 $this->_chart = $this->handleExistingRevisions( $chart_id, $this->_chart );
701 585 }
702 586
703 - // Clear existing chart cache.
704 - if ( isset( $_POST['save'] ) && 1 === intval( $_POST['save'] ) ) {
705 - $cache_key = Visualizer_Plugin::CF_CHART_CACHE . '_' . $chart_id;
706 - if ( get_transient( $cache_key ) ) {
707 - delete_transient( $cache_key );
708 - }
709 - }
710 -
711 587 switch ( $tab ) {
712 588 case 'settings':
713 589 $this->_handleDataAndSettingsPage();
714 590 break;
@@ -719,9 +595,9 @@
719 595 default:
720 596 // this should never happen.
721 597 break;
722 598 }
723 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
599 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
724 600 }
725 601
726 602 /**
727 603 * Load code editor assets.
@@ -733,9 +609,9 @@
733 609
734 610 // data tables assets.
735 611 wp_register_script( 'visualizer-datatables', VISUALIZER_ABSURL . 'js/lib/datatables.min.js', array( 'jquery-ui-core' ), Visualizer_Plugin::VERSION );
736 612 wp_register_style( 'visualizer-datatables', VISUALIZER_ABSURL . 'css/lib/datatables.min.css', array(), Visualizer_Plugin::VERSION );
737 - wp_register_style( 'visualizer-jquery-ui', sprintf( '//code.jquery.com/ui/%s/themes/smoothness/jquery-ui.css', $wp_scripts->registered['jquery-ui-core']->ver ), array( 'visualizer-datatables' ), Visualizer_Plugin::VERSION );
613 + wp_register_style( 'visualizer-jquery-ui', sprintf( '//ajax.googleapis.com/ajax/libs/jqueryui/%s/themes/smoothness/jquery-ui.css', $wp_scripts->registered['jquery-ui-core']->ver ), array( 'visualizer-datatables' ), Visualizer_Plugin::VERSION );
738 614 wp_enqueue_script( 'visualizer-datatables' );
739 615 wp_enqueue_style( 'visualizer-jquery-ui' );
740 616
741 617 if ( ! Visualizer_Module::is_pro() ) {
@@ -751,9 +627,9 @@
751 627 wp_register_script( 'visualizer-codemirror-matchbrackets', '//codemirror.net/addon/edit/matchbrackets.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
752 628 wp_register_script( 'visualizer-codemirror-closebrackets', '//codemirror.net/addon/edit/closebrackets.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
753 629 wp_register_script( 'visualizer-codemirror-sql', '//codemirror.net/mode/sql/sql.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
754 630 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 );
631 + 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 632 wp_register_style( 'visualizer-codemirror-core', '//codemirror.net/lib/codemirror.css', array(), Visualizer_Plugin::VERSION );
757 633 wp_register_style( 'visualizer-codemirror-hint', '//codemirror.net/addon/hint/show-hint.css', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
758 634
759 635 wp_enqueue_script( 'visualizer-codemirror-hint' );
@@ -767,9 +643,9 @@
767 643 'lineWrapping' => true,
768 644 'dragDrop' => false,
769 645 'matchBrackets' => true,
770 646 'autoCloseBrackets' => true,
771 - 'extraKeys' => array( 'Shift-Space' => 'autocomplete' ),
647 + 'extraKeys' => array( 'Ctrl-Space' => 'autocomplete' ),
772 648 'hintOptions' => array( 'tables' => $table_col_mapping ),
773 649 ),
774 650 )
775 651 );
@@ -803,12 +679,9 @@
803 679 update_option( 'visualizer-map-api-key', $_POST['map_api_key'] );
804 680 }
805 681
806 682 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 ) {
683 + if ( $this->_chart->post_status === 'auto-draft' ) {
811 684 $this->_chart->post_status = 'publish';
812 685
813 686 // 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 687 // we do not want any difference in data so disable revisions temporarily.
@@ -816,15 +689,10 @@
816 689
817 690 wp_update_post( $this->_chart->to_array() );
818 691 }
819 692 // 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 );
693 + if ( ! ( isset( $_POST['cancel'] ) && 1 === intval( $_POST['cancel'] ) ) ) {
694 + update_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SETTINGS, $_POST );
827 695
828 696 // we will keep a parameter called 'internal_title' that will be set to the given title or, if empty, the chart ID
829 697 // this will help in searching with the chart id.
830 698 $settings = get_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SETTINGS, true );
@@ -838,14 +706,8 @@
838 706 if ( empty( $title ) ) {
839 707 $title = $this->_chart->ID;
840 708 }
841 709 $settings['internal_title'] = $title;
842 - $settings_label = isset( $settings['pieResidueSliceLabel'] ) ? $settings['pieResidueSliceLabel'] : '';
843 - if ( empty( $settings_label ) ) {
844 - $settings['pieResidueSliceLabel'] = esc_html__( 'Other', 'visualizer' );
845 - } else {
846 - $settings['pieResidueSliceLabel'] = $settings_label;
847 - }
848 710 update_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SETTINGS, $settings );
849 711 }
850 712 $render = new Visualizer_Render_Page_Send();
851 713 $render->text = sprintf( '[visualizer id="%d"]', $this->_chart->ID );
@@ -871,9 +733,8 @@
871 733 wp_enqueue_style( 'visualizer-frame' );
872 734 wp_enqueue_script( 'visualizer-preview' );
873 735 wp_enqueue_script( 'visualizer-chosen' );
874 736 wp_enqueue_script( 'visualizer-render' );
875 - wp_enqueue_code_editor( array( 'type' => 'application/json' ) );
876 737
877 738 if ( Visualizer_Module::can_show_feature( 'simple-editor' ) ) {
878 739 wp_enqueue_script( 'visualizer-editor-simple' );
879 740 wp_localize_script(
@@ -881,10 +742,12 @@
881 742 'visualizer1',
882 743 array(
883 744 'ajax' => array(
884 745 'url' => admin_url( 'admin-ajax.php' ),
885 - 'nonces' => array(),
886 - 'actions' => array(),
746 + 'nonces' => array(
747 + ),
748 + 'actions' => array(
749 + ),
887 750 ),
888 751 )
889 752 );
890 753 }
@@ -895,15 +758,13 @@
895 758 'visualizer-render',
896 759 'visualizer',
897 760 array(
898 761 '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' ),
762 + 'invalid_source' => esc_html__( 'You have entered an invalid URL. Please provide a valid URL.', 'visualizer' ),
763 + 'loading' => esc_html__( 'Loading...', 'visualizer' ),
764 + 'json_error' => esc_html__( 'An error occured in fetching data.', 'visualizer' ),
765 + 'select_columns' => esc_html__( 'Please select a few columns to include in the chart.', 'visualizer' ),
766 + '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 767 ),
907 768 'charts' => array(
908 769 'canvas' => $data,
909 770 'id' => $this->_chart->ID,
@@ -934,9 +795,8 @@
934 795 'page_type' => 'chart',
935 796 'json_tag_separator' => Visualizer_Source_Json::TAG_SEPARATOR,
936 797 'json_tag_separator_view' => Visualizer_Source_Json::TAG_SEPARATOR_VIEW,
937 798 'is_front' => false,
938 - 'rest_base' => get_rest_url( null, 'wc/v3/reports/' ),
939 799 )
940 800 );
941 801
942 802 $render = new Visualizer_Render_Page_Data();
@@ -947,10 +807,11 @@
947 807 if ( filter_input( INPUT_GET, 'library', FILTER_VALIDATE_BOOLEAN ) ) {
948 808 $render->button = filter_input( INPUT_GET, 'action' ) === Visualizer_Plugin::ACTION_EDIT_CHART
949 809 ? esc_html__( 'Save Chart', 'visualizer' )
950 810 : esc_html__( 'Create Chart', 'visualizer' );
951 -
952 - $render->cancel_button = esc_html__( 'Cancel', 'visualizer' );
811 + if ( filter_input( INPUT_GET, 'action' ) === Visualizer_Plugin::ACTION_EDIT_CHART ) {
812 + $render->cancel_button = esc_html__( 'Cancel', 'visualizer' );
813 + }
953 814 } else {
954 815 $render->button = esc_attr__( 'Insert Chart', 'visualizer' );
955 816 }
956 817
@@ -973,12 +834,12 @@
973 834 * @access private
974 835 */
975 836 private function _handleTypesPage() {
976 837 // process post request
977 - if ( $_SERVER['REQUEST_METHOD'] === 'POST' && wp_verify_nonce( filter_input( INPUT_POST, 'nonce' ), 'visualizer-upload-data' ) ) {
838 + if ( $_SERVER['REQUEST_METHOD'] === 'POST' && wp_verify_nonce( filter_input( INPUT_POST, 'nonce' ) ) ) {
978 839 $type = filter_input( INPUT_POST, 'type' );
979 840 $library = filter_input( INPUT_POST, 'chart-library' );
980 - if ( Visualizer_Module_Admin::checkChartStatus( $type ) ) {
841 + if ( in_array( $type, Visualizer_Plugin::getChartTypes(), true ) ) {
981 842 if ( empty( $library ) ) {
982 843 // library cannot be empty.
983 844 do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, 'Chart library empty while creating the chart! Aborting...', 'error', __FILE__, __LINE__ );
984 845 return;
@@ -999,9 +860,9 @@
999 860 Visualizer_Module_Utility::set_defaults( $this->_chart );
1000 861
1001 862 // redirect to next tab
1002 863 // changed by Ash/Upwork
1003 - wp_redirect( esc_url_raw( add_query_arg( 'tab', 'settings' ) ) );
864 + wp_redirect( add_query_arg( 'tab', 'settings' ) );
1004 865
1005 866 return;
1006 867 }
1007 868 }
@@ -1030,80 +891,8 @@
1030 891 * Processes the CSV that is sent in the request as a string.
1031 892 *
1032 893 * @since 3.2.0
1033 894 */
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 895 private function handleCSVasString( $data, $editor_type ) {
1107 896 $source = null;
1108 897
1109 898 switch ( $editor_type ) {
@@ -1116,16 +905,8 @@
1116 905 foreach ( $values as $row ) {
1117 906 if ( empty( $row ) ) {
1118 907 continue;
1119 908 }
1120 - $row = explode( ',', $row );
1121 - $row = array_map(
1122 - function ( $r ) {
1123 - return '' === $r ? ' ' : $r;
1124 - },
1125 - $row
1126 - );
1127 - $row = implode( ',', $row );
1128 909 // don't use fpucsv here because we need to just dump the data
1129 910 // minus the empty rows
1130 911 // because fputcsv needs to tokenize
1131 912 // we can standardize the CSV enclosure here and replace all ' with "
@@ -1169,9 +950,9 @@
1169 950 foreach ( $types as $type ) {
1170 951 if ( empty( $type ) ) {
1171 952 $exclude[] = $index;
1172 953 }
1173 - ++$index;
954 + $index++;
1174 955 }
1175 956
1176 957 // when N headers are being renamed, the number of headers increases by N
1177 958 // because of the way datatable duplicates header information
@@ -1231,13 +1012,9 @@
1231 1012 // otherwise, assume this is a normal web request.
1232 1013 $can_die = ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE );
1233 1014
1234 1015 // validate nonce
1235 - if (
1236 - ! isset( $_GET['nonce'] ) ||
1237 - ! wp_verify_nonce( $_GET['nonce'], 'visualizer-upload-data' ) ||
1238 - ! current_user_can( 'edit_posts' )
1239 - ) {
1016 + if ( ! isset( $_GET['nonce'] ) || ! wp_verify_nonce( $_GET['nonce'] ) ) {
1240 1017 if ( ! $can_die ) {
1241 1018 return;
1242 1019 }
1243 1020 status_header( 403 );
@@ -1246,15 +1023,9 @@
1246 1023
1247 1024 // check chart, if chart exists
1248 1025 // do not use filter_input as it does not work for phpunit test cases, use filter_var instead
1249 1026 $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 - ) {
1027 + if ( ! $chart_id || ! ( $chart = get_post( $chart_id ) ) || $chart->post_type !== Visualizer_Plugin::CPT_VISUALIZER ) {
1257 1028 if ( ! $can_die ) {
1258 1029 return;
1259 1030 }
1260 1031 status_header( 400 );
@@ -1290,35 +1061,18 @@
1290 1061
1291 1062 // delete editor related data.
1292 1063 delete_post_meta( $chart_id, Visualizer_Plugin::CF_EDITOR );
1293 1064
1294 - // delete this so that a JSON import can be later edited manually without a problem.
1295 - delete_post_meta( $chart_id, Visualizer_Plugin::CF_EDITABLE_TABLE );
1296 -
1297 1065 $source = null;
1298 1066 $render = new Visualizer_Render_Page_Update();
1299 -
1300 - $remote_data = false;
1301 - if ( isset( $_POST['remote_data'] ) && function_exists( 'wp_http_validate_url' ) ) {
1302 - $remote_data = wp_http_validate_url( $_POST['remote_data'] );
1303 - }
1304 - 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 - }
1067 + if ( isset( $_POST['remote_data'] ) && filter_var( $_POST['remote_data'], FILTER_VALIDATE_URL ) ) {
1068 + $source = new Visualizer_Source_Csv_Remote( $_POST['remote_data'] );
1311 1069 if ( isset( $_POST['vz-import-time'] ) ) {
1312 - apply_filters( 'visualizer_pro_chart_schedule', $chart_id, $remote_data, $_POST['vz-import-time'] );
1070 + apply_filters( 'visualizer_pro_chart_schedule', $chart_id, $_POST['remote_data'], $_POST['vz-import-time'] );
1313 1071 }
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 - }
1072 + // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
1073 + } elseif ( isset( $_FILES['local_data'] ) && $_FILES['local_data']['error'] == 0 ) {
1074 + $source = new Visualizer_Source_Csv( $_FILES['local_data']['tmp_name'] );
1321 1075 } elseif ( isset( $_POST['chart_data'] ) && strlen( $_POST['chart_data'] ) > 0 ) {
1322 1076 $source = $this->handleCSVasString( $_POST['chart_data'], $_POST['editor-type'] );
1323 1077 update_post_meta( $chart_id, Visualizer_Plugin::CF_EDITOR, $_POST['editor-type'] );
1324 1078 } elseif ( isset( $_POST['table_data'] ) && 'yes' === $_POST['table_data'] ) {
@@ -1325,10 +1079,10 @@
1325 1079 $source = $this->handleTabularData();
1326 1080 update_post_meta( $chart_id, Visualizer_Plugin::CF_EDITOR, $_POST['editor-type'] );
1327 1081 } else {
1328 1082 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' ) );
1083 + $render->message = esc_html__( 'CSV file with chart data was not uploaded. Please try again.', 'visualizer' );
1084 + update_post_meta( $chart_id, Visualizer_Plugin::CF_ERROR, esc_html__( 'CSV file with chart data was not uploaded. Please try again.', 'visualizer' ) );
1331 1085 }
1332 1086
1333 1087 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 1088
@@ -1349,9 +1103,8 @@
1349 1103 if ( $populate ) {
1350 1104 $chart->post_content = $content;
1351 1105 }
1352 1106 wp_update_post( $chart->to_array() );
1353 -
1354 1107 update_post_meta( $chart->ID, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
1355 1108 update_post_meta( $chart->ID, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() );
1356 1109 update_post_meta( $chart->ID, Visualizer_Plugin::CF_DEFAULT_DATA, 0 );
1357 1110
@@ -1359,17 +1112,8 @@
1359 1112
1360 1113 Visualizer_Module_Utility::set_defaults( $chart, null );
1361 1114
1362 1115 $settings = get_post_meta( $chart->ID, Visualizer_Plugin::CF_SETTINGS, true );
1363 - if ( isset( $settings['series'] ) && ! ( count( $settings['series'] ) - count( $source->getSeries() ) > 1 ) ) {
1364 - $diff_total_series = abs( count( $settings['series'] ) - count( $source->getSeries() ) );
1365 - if ( $diff_total_series ) {
1366 - foreach ( range( 1, $diff_total_series ) as $k => $diff_series ) {
1367 - $settings['series'][] = end( $settings['series'] );
1368 - }
1369 - update_post_meta( $chart->ID, Visualizer_Plugin::CF_SETTINGS, $settings );
1370 - }
1371 - }
1372 1116
1373 1117 $render->id = $chart->ID;
1374 1118 $render->data = json_encode( $source->getRawData( get_post_meta( $chart->ID, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) ) );
1375 1119 $render->series = json_encode( $source->getSeries() );
@@ -1376,9 +1120,9 @@
1376 1120 $render->settings = json_encode( $settings );
1377 1121 } else {
1378 1122 $error = $source->get_error();
1379 1123 if ( empty( $error ) ) {
1380 - $error = esc_html__( 'The CSV file couldn\'t be read. Check that it\'s properly formatted and try again.', 'visualizer' );
1124 + $error = esc_html__( 'CSV file is broken or invalid. Please try again.', 'visualizer' );
1381 1125 }
1382 1126 $render->message = $error;
1383 1127 do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( '%s for chart %d.', $error, $chart_id ), 'error', __FILE__, __LINE__ );
1384 1128 update_post_meta( $chart_id, Visualizer_Plugin::CF_ERROR, $error );
@@ -1389,9 +1133,9 @@
1389 1133 $render->render();
1390 1134 if ( ! $can_die ) {
1391 1135 return;
1392 1136 }
1393 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1137 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1394 1138 }
1395 1139
1396 1140 /**
1397 1141 * Clones the chart.
@@ -1430,26 +1174,23 @@
1430 1174 if ( strpos( $key, 'visualizer-' ) !== false ) {
1431 1175 add_post_meta( $new_chart_id, $key, maybe_unserialize( $value[0] ) );
1432 1176 }
1433 1177 }
1434 - $redirect = esc_url(
1435 - add_query_arg(
1436 - array(
1437 - 'page' => 'visualizer',
1438 - 'type' => filter_input( INPUT_GET, 'type' ),
1439 - 'vaction' => false,
1440 - ),
1441 - admin_url( 'admin.php' )
1178 + $redirect = add_query_arg(
1179 + array(
1180 + 'page' => 'visualizer',
1181 + 'type' => filter_input( INPUT_GET, 'type' ),
1182 + 'vaction' => false,
1442 1183 ),
1443 - null,
1444 - 'db'
1184 + admin_url( 'admin.php' )
1445 1185 );
1446 1186 }
1447 1187 }
1448 1188
1449 - if ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) {
1189 + if ( defined( 'WP_TESTS_DOMAIN' ) ) {
1450 1190 wp_die();
1451 1191 }
1192 +
1452 1193 wp_redirect( $redirect );
1453 1194 exit;
1454 1195 }
1455 1196
@@ -1480,9 +1221,9 @@
1480 1221 }
1481 1222 }
1482 1223 }
1483 1224
1484 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1225 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1485 1226 }
1486 1227
1487 1228 /**
1488 1229 * Handles chart data page.
@@ -1506,11 +1247,10 @@
1506 1247 'visualizer-render',
1507 1248 'visualizer',
1508 1249 array(
1509 1250 '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' ),
1251 + 'invalid_source' => esc_html__( 'You have entered an invalid URL. Please provide a valid URL.', 'visualizer' ),
1252 + 'loading' => esc_html__( 'Loading...', 'visualizer' ),
1513 1253 ),
1514 1254 'charts' => array(
1515 1255 'canvas' => $data,
1516 1256 ),
@@ -1536,24 +1276,12 @@
1536 1276 */
1537 1277 public function getQueryData() {
1538 1278 check_ajax_referer( Visualizer_Plugin::ACTION_FETCH_DB_DATA . Visualizer_Plugin::VERSION, 'security' );
1539 1279
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 1280 $params = wp_parse_args( $_POST['params'] );
1552 1281 $chart_id = filter_var( $params['chart_id'], FILTER_VALIDATE_INT );
1553 - $query = trim( $params['query'], ';' );
1554 1282
1555 - $source = new Visualizer_Source_Query( stripslashes( $query ), $chart_id, $params );
1283 + $source = new Visualizer_Source_Query( stripslashes( $params['query'] ), $chart_id, $params );
1556 1284 $html = $source->fetch( true );
1557 1285 $error = $source->get_error();
1558 1286 if ( ! empty( $error ) ) {
1559 1287 wp_send_json_error( array( 'msg' => $error ) );
@@ -1568,19 +1296,8 @@
1568 1296 */
1569 1297 public function saveQuery() {
1570 1298 check_ajax_referer( Visualizer_Plugin::ACTION_SAVE_DB_QUERY . Visualizer_Plugin::VERSION, 'security' );
1571 1299
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 1300 $chart_id = filter_input(
1584 1301 INPUT_GET,
1585 1302 'chart',
1586 1303 FILTER_VALIDATE_INT,
@@ -1593,9 +1310,9 @@
1593 1310
1594 1311 $hours = filter_input(
1595 1312 INPUT_POST,
1596 1313 'refresh',
1597 - FILTER_VALIDATE_FLOAT,
1314 + FILTER_VALIDATE_INT,
1598 1315 array(
1599 1316 'options' => array(
1600 1317 'min_range' => -1,
1601 1318 'max_range' => apply_filters( 'visualizer_is_business', false ) ? PHP_INT_MAX : -1,
@@ -1602,9 +1319,9 @@
1602 1319 ),
1603 1320 )
1604 1321 );
1605 1322
1606 - if ( ! is_numeric( $hours ) ) {
1323 + if ( ! is_int( $hours ) ) {
1607 1324 $hours = -1;
1608 1325 }
1609 1326
1610 1327 $render = new Visualizer_Render_Page_Update();
@@ -1609,14 +1326,13 @@
1609 1326
1610 1327 $render = new Visualizer_Render_Page_Update();
1611 1328 if ( $chart_id ) {
1612 1329 $params = wp_parse_args( $_POST['params'] );
1613 - $query = trim( $params['query'], ';' );
1614 - $source = new Visualizer_Source_Query( stripslashes( $query ), $chart_id, $params );
1330 + $source = new Visualizer_Source_Query( stripslashes( $params['query'] ), $chart_id, $params );
1615 1331 $source->fetch( false );
1616 1332 $error = $source->get_error();
1617 1333 if ( empty( $error ) ) {
1618 - update_post_meta( $chart_id, Visualizer_Plugin::CF_DB_QUERY, stripslashes( $query ) );
1334 + update_post_meta( $chart_id, Visualizer_Plugin::CF_DB_QUERY, stripslashes( $params['query'] ) );
1619 1335 update_post_meta( $chart_id, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() );
1620 1336 update_post_meta( $chart_id, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
1621 1337 update_post_meta( $chart_id, Visualizer_Plugin::CF_DB_SCHEDULE, $hours );
1622 1338 update_post_meta( $chart_id, Visualizer_Plugin::CF_DEFAULT_DATA, 0 );
@@ -1645,9 +1361,9 @@
1645 1361 }
1646 1362 }
1647 1363 $render->render();
1648 1364 if ( ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE ) ) {
1649 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1365 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1650 1366 }
1651 1367 }
1652 1368
1653 1369
@@ -1672,9 +1388,9 @@
1672 1388
1673 1389 $hours = filter_input(
1674 1390 INPUT_POST,
1675 1391 'refresh',
1676 - FILTER_VALIDATE_FLOAT,
1392 + FILTER_VALIDATE_INT,
1677 1393 array(
1678 1394 'options' => array(
1679 1395 'min_range' => -1,
1680 1396 'max_range' => apply_filters( 'visualizer_is_business', false ) ? PHP_INT_MAX : -1,
@@ -1681,9 +1397,9 @@
1681 1397 ),
1682 1398 )
1683 1399 );
1684 1400
1685 - if ( ! is_numeric( $hours ) ) {
1401 + if ( ! $hours ) {
1686 1402 $hours = -1;
1687 1403 }
1688 1404
1689 1405 do_action( 'visualizer_save_filter', $chart_id, $hours );
@@ -1688,61 +1404,8 @@
1688 1404
1689 1405 do_action( 'visualizer_save_filter', $chart_id, $hours );
1690 1406
1691 1407 if ( ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE ) ) {
1692 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1408 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1693 1409 }
1694 - }
1695 -
1696 - /**
1697 - * Save chart image.
1698 - *
1699 - * @param string $base64_img Chart image.
1700 - * @param int $chart_id Chart ID.
1701 - * @param bool $save_attachment Save attachment.
1702 - * @return attachment ID
1703 - */
1704 - public function save_chart_image( $base64_img, $chart_id, $save_attachment = true ) {
1705 - // Delete old chart image.
1706 - $old_attachment_id = get_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_IMAGE, true );
1707 - if ( $old_attachment_id ) {
1708 - wp_delete_attachment( $old_attachment_id, true );
1709 - }
1710 -
1711 - if ( ! $save_attachment ) {
1712 - return 0;
1713 - }
1714 -
1715 - // Upload dir.
1716 - $upload_dir = wp_upload_dir();
1717 - $upload_path = str_replace( '/', DIRECTORY_SEPARATOR, $upload_dir['path'] ) . DIRECTORY_SEPARATOR;
1718 -
1719 - $img = str_replace( 'data:image/png;base64,', '', $base64_img );
1720 - $img = str_replace( ' ', '+', $img );
1721 - $decoded = base64_decode( $img );
1722 - $filename = 'visualization-' . $chart_id . '.png';
1723 - $file_type = 'image/png';
1724 - $hashed_filename = $filename;
1725 -
1726 - // Save the image in the uploads directory.
1727 - require_once ABSPATH . '/wp-admin/includes/file.php';
1728 - \WP_Filesystem();
1729 - global $wp_filesystem;
1730 - if ( ! is_a( $wp_filesystem, 'WP_Filesystem_Base' ) ) {
1731 - $creds = request_filesystem_credentials( site_url() );
1732 - wp_filesystem( $creds );
1733 - }
1734 - $upload_file = $wp_filesystem->put_contents( $upload_path . $hashed_filename, $decoded );
1735 -
1736 - // Insert new chart image.
1737 - $attachment = array(
1738 - 'post_mime_type' => $file_type,
1739 - 'post_title' => preg_replace( '/\.[^.]+$/', '', basename( $hashed_filename ) ),
1740 - 'post_content' => '',
1741 - 'post_status' => 'inherit',
1742 - 'guid' => $upload_dir['url'] . '/' . basename( $hashed_filename ),
1743 - );
1744 -
1745 - $attach_id = wp_insert_attachment( $attachment, $upload_dir['path'] . '/' . $hashed_filename );
1746 - return $attach_id;
1747 1410 }
1748 1411 }