PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.4.2
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.4.2
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 +101 -452 4.0.33.4.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.
@@ -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
@@ -231,12 +214,11 @@
231 214
232 215 $chart = get_post( $chart_id );
233 216
234 217 $source = new Visualizer_Source_Json( $params );
235 - update_post_meta( $chart->ID, Visualizer_Plugin::CF_EDITABLE_TABLE, true );
236 218 $source->fetchFromEditableTable();
237 219
238 - $content = $source->getData( get_post_meta( $chart->ID, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) );
220 + $content = $source->getData();
239 221 $chart->post_content = $content;
240 222 wp_update_post( $chart->to_array() );
241 223 update_post_meta( $chart->ID, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
242 224 update_post_meta( $chart->ID, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() );
@@ -258,16 +240,8 @@
258 240 if ( ! empty( $params['paging'] ) ) {
259 241 add_post_meta( $chart->ID, Visualizer_Plugin::CF_JSON_PAGING, $params['paging'] );
260 242 }
261 243
262 - if ( Visualizer_Module::is_pro() ) {
263 - if ( ! empty( $params['vz_woo_source'] ) ) {
264 - update_post_meta( $chart->ID, Visualizer_Plugin::CF_JSON_WOOCOMMERCE_SOURCE, $params['vz_woo_source'] );
265 - } else {
266 - delete_post_meta( $chart->ID, Visualizer_Plugin::CF_JSON_WOOCOMMERCE_SOURCE );
267 - }
268 - }
269 -
270 244 $time = filter_input(
271 245 INPUT_POST,
272 246 'time',
273 247 FILTER_VALIDATE_INT,
@@ -291,13 +265,13 @@
291 265 delete_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_SCHEDULE );
292 266
293 267 $render = new Visualizer_Render_Page_Update();
294 268 $render->id = $chart->ID;
295 - $render->data = json_encode( $source->getRawData( get_post_meta( $chart_id, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) ) );
269 + $render->data = json_encode( $source->getRawData() );
296 270 $render->series = json_encode( $source->getSeries() );
297 271 $render->render();
298 272
299 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
273 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
300 274 }
301 275
302 276
303 277 /**
@@ -373,19 +347,19 @@
373 347 * @since 1.0.0
374 348 *
375 349 * @access private
376 350 *
377 - * @param WP_Post|null $chart The chart object.
351 + * @param WP_Post $chart The chart object.
378 352 *
379 353 * @return array The array of chart data.
380 354 */
381 - private function _getChartArray( $chart = null ) {
355 + private function _getChartArray( WP_Post $chart = null ) {
382 356 if ( is_null( $chart ) ) {
383 357 $chart = $this->_chart;
384 358 }
385 359 $type = get_post_meta( $chart->ID, Visualizer_Plugin::CF_CHART_TYPE, true );
386 360 $series = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_SERIES, get_post_meta( $chart->ID, Visualizer_Plugin::CF_SERIES, true ), $chart->ID, $type );
387 - $data = self::get_chart_data( $chart, $type );
361 + $data = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_DATA, unserialize( $chart->post_content ), $chart->ID, $type );
388 362 $library = $this->load_chart_type( $chart->ID );
389 363
390 364 $settings = get_post_meta( $chart->ID, Visualizer_Plugin::CF_SETTINGS, true );
391 365 $settings = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_SETTINGS, $settings, $chart->ID, $type );
@@ -401,13 +375,8 @@
401 375 }
402 376
403 377 $date_formats = Visualizer_Source::get_date_formats_if_exists( $series, $data );
404 378
405 - $code = '';
406 - if ( 'd3' === $library ) {
407 - $code = get_post_meta( $chart->ID, Visualizer_Module_AIBuilder::CF_D3_CODE, true );
408 - }
409 -
410 379 return array(
411 380 'type' => $type,
412 381 'series' => $series,
413 382 'settings' => $settings,
@@ -412,9 +381,8 @@
412 381 'series' => $series,
413 382 'settings' => $settings,
414 383 'data' => $data,
415 384 'library' => $library,
416 - 'code' => $code,
417 385 'css' => $css,
418 386 'date_formats' => $date_formats,
419 387 );
420 388 }
@@ -431,9 +399,9 @@
431 399 public static function _sendResponse( $results ) {
432 400 header( 'Content-type: application/json' );
433 401 nocache_headers();
434 402 echo json_encode( $results );
435 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
403 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
436 404 }
437 405
438 406 /**
439 407 * Deletes a chart from database.
@@ -465,22 +433,9 @@
465 433 $success = $chart && $chart->post_type === Visualizer_Plugin::CPT_VISUALIZER;
466 434 }
467 435 }
468 436 if ( $success ) {
469 - global $sitepress;
470 - if ( Visualizer_Module::is_pro() && ( function_exists( 'icl_get_languages' ) && $sitepress instanceof \SitePress ) ) {
471 - $trid = $sitepress->get_element_trid( $chart_id, 'post_' . Visualizer_Plugin::CPT_VISUALIZER );
472 - $translations = $sitepress->get_element_translations( $trid );
473 - if ( ! empty( $translations ) ) {
474 - foreach ( $translations as $translated_post ) {
475 - wp_delete_post( $translated_post->element_id, true );
476 - }
477 - } else {
478 - wp_delete_post( $chart_id, true );
479 - }
480 - } else {
481 - wp_delete_post( $chart_id, true );
482 - }
437 + wp_delete_post( $chart_id, true );
483 438 }
484 439 if ( $is_post ) {
485 440 self::_sendResponse(
486 441 array(
@@ -528,108 +483,44 @@
528 483 *
529 484 * @access public
530 485 */
531 486 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 487 defined( 'IFRAME_REQUEST' ) || define( 'IFRAME_REQUEST', 1 );
537 - if ( ! defined( 'ET_BUILDER_PRODUCT_VERSION' ) && function_exists( 'et_get_theme_version' ) ) {
538 - define( 'ET_BUILDER_PRODUCT_VERSION', et_get_theme_version() );
539 - }
540 - // Set current screen for the render chart.
541 - set_current_screen( 'visualizer_render_chart' );
542 488 // check chart, if chart not exists, will create new one and redirects to the same page with proper chart id
543 489 $chart_id = isset( $_GET['chart'] ) ? filter_var( $_GET['chart'], FILTER_VALIDATE_INT ) : '';
544 - if ( ! empty( $_POST ) ) {
545 - $_POST = map_deep( $_POST, 'wp_strip_all_tags' );
546 - }
547 - $chart = $chart_id ? get_post( $chart_id ) : null;
548 - if ( ! $chart_id || ! $chart || $chart->post_type !== Visualizer_Plugin::CPT_VISUALIZER ) {
549 - if ( empty( $_GET['lang'] ) || empty( $_GET['parent_chart_id'] ) ) {
550 - $this->deleteOldCharts();
551 - $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 - $source = new Visualizer_Source_Csv( VISUALIZER_ABSPATH . DIRECTORY_SEPARATOR . 'samples' . DIRECTORY_SEPARATOR . $default_type . '.csv' );
557 - $source->fetch();
558 - $chart_id = wp_insert_post(
490 + if ( ! $chart_id || ! ( $chart = get_post( $chart_id ) ) || $chart->post_type !== Visualizer_Plugin::CPT_VISUALIZER ) {
491 + $this->deleteOldCharts();
492 + $default_type = isset( $_GET['type'] ) && ! empty( $_GET['type'] ) ? $_GET['type'] : 'line';
493 + $source = new Visualizer_Source_Csv( VISUALIZER_ABSPATH . DIRECTORY_SEPARATOR . 'samples' . DIRECTORY_SEPARATOR . $default_type . '.csv' );
494 + $source->fetch();
495 + $chart_id = wp_insert_post(
496 + array(
497 + 'post_type' => Visualizer_Plugin::CPT_VISUALIZER,
498 + 'post_title' => 'Visualization',
499 + 'post_author' => get_current_user_id(),
500 + 'post_status' => 'auto-draft',
501 + 'post_content' => $source->getData(),
502 + )
503 + );
504 + if ( $chart_id && ! is_wp_error( $chart_id ) ) {
505 + add_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_TYPE, $default_type );
506 + add_post_meta( $chart_id, Visualizer_Plugin::CF_DEFAULT_DATA, 1 );
507 + add_post_meta( $chart_id, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() );
508 + add_post_meta( $chart_id, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
509 + add_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_LIBRARY, '' );
510 + add_post_meta(
511 + $chart_id,
512 + Visualizer_Plugin::CF_SETTINGS,
559 513 array(
560 - 'post_type' => Visualizer_Plugin::CPT_VISUALIZER,
561 - 'post_title' => 'Visualization',
562 - 'post_author' => get_current_user_id(),
563 - 'post_status' => 'auto-draft',
564 - 'post_content' => $source->getData( get_post_meta( $chart_id, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) ),
514 + 'focusTarget' => 'datum',
565 515 )
566 516 );
567 - if ( $chart_id && ! is_wp_error( $chart_id ) ) {
568 - add_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_TYPE, $default_type );
569 - add_post_meta( $chart_id, Visualizer_Plugin::CF_DEFAULT_DATA, 1 );
570 - add_post_meta( $chart_id, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() );
571 - add_post_meta( $chart_id, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
572 - add_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_LIBRARY, '' );
573 - add_post_meta(
574 - $chart_id,
575 - Visualizer_Plugin::CF_SETTINGS,
576 - array(
577 - 'focusTarget' => 'datum',
578 - )
579 - );
580 -
581 - do_action( 'visualizer_pro_new_chart_defaults', $chart_id );
582 - }
583 - } 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 - );
600 -
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] ) );
609 - }
610 - }
611 - }
612 - }
613 517 do_action( 'visualizer_pro_new_chart_defaults', $chart_id );
614 518 }
615 - wp_redirect( esc_url_raw( add_query_arg( 'chart', (int) $chart_id ) ) );
616 -
617 - if ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) {
618 - wp_die();
619 - }
620 - exit();
519 + wp_redirect( add_query_arg( 'chart', (int) $chart_id ) );
520 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
621 521 }
622 522
623 - $_POST['save_chart_image'] = isset( $_POST['save_chart_image'] ) && 'yes' === $_POST['save_chart_image'] ? true : false;
624 - $_POST['lazy_load_chart'] = isset( $_POST['lazy_load_chart'] ) && 'yes' === $_POST['lazy_load_chart'] ? true : false;
625 -
626 - if ( isset( $_POST['chart-img'] ) && ! empty( $_POST['chart-img'] ) ) {
627 - $attachment_id = $this->save_chart_image( $_POST['chart-img'], $chart_id, $_POST['save_chart_image'] );
628 - if ( $attachment_id ) {
629 - update_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_IMAGE, $attachment_id );
630 - }
631 - }
632 523 $lib = $this->load_chart_type( $chart_id );
633 524
634 525 // the alpha color picker (RGBA) is not supported by google.
635 526 $color_picker_dep = 'wp-color-picker';
@@ -642,9 +533,9 @@
642 533 wp_register_script( 'visualizer-chosen', VISUALIZER_ABSURL . 'js/lib/chosen.jquery.min.js', array( 'jquery' ), Visualizer_Plugin::VERSION );
643 534 wp_register_style( 'visualizer-chosen', VISUALIZER_ABSURL . 'css/lib/chosen.min.css', array(), Visualizer_Plugin::VERSION );
644 535
645 536 wp_register_style( 'visualizer-frame', VISUALIZER_ABSURL . 'css/frame.css', array( 'visualizer-chosen' ), Visualizer_Plugin::VERSION );
646 - wp_register_script( 'visualizer-frame', VISUALIZER_ABSURL . 'js/frame.js', array( 'visualizer-chosen', 'jquery-ui-accordion', 'jquery-ui-tabs' ), Visualizer_Plugin::VERSION, true );
537 + wp_register_script( 'visualizer-frame', VISUALIZER_ABSURL . 'js/frame.js', array( 'visualizer-chosen', 'jquery-ui-accordion' ), Visualizer_Plugin::VERSION, true );
647 538 wp_register_script( 'visualizer-customization', $this->get_user_customization_js(), array(), null, true );
648 539 wp_register_script(
649 540 'visualizer-render',
650 541 VISUALIZER_ABSURL . 'js/render-facade.js',
@@ -683,9 +574,8 @@
683 574 if ( isset( $_POST['cancel'] ) && 1 === intval( $_POST['cancel'] ) ) {
684 575 // if the cancel button is clicked.
685 576 $this->undoRevisions( $chart_id, true );
686 577 } elseif ( isset( $_POST['save'] ) && 1 === intval( $_POST['save'] ) ) {
687 - $this->handlePermissions();
688 578 // if the save button is clicked.
689 579 $this->undoRevisions( $chart_id, false );
690 580 } else {
691 581 // if the edit button is clicked.
@@ -691,16 +581,8 @@
691 581 // if the edit button is clicked.
692 582 $this->_chart = $this->handleExistingRevisions( $chart_id, $this->_chart );
693 583 }
694 584
695 - // Clear existing chart cache.
696 - if ( isset( $_POST['save'] ) && 1 === intval( $_POST['save'] ) ) {
697 - $cache_key = Visualizer_Plugin::CF_CHART_CACHE . '_' . $chart_id;
698 - if ( get_transient( $cache_key ) ) {
699 - delete_transient( $cache_key );
700 - }
701 - }
702 -
703 585 switch ( $tab ) {
704 586 case 'settings':
705 587 $this->_handleDataAndSettingsPage();
706 588 break;
@@ -708,12 +590,12 @@
708 590 case 'visualizer': // fall through.
709 591 $this->_handleTypesPage();
710 592 break;
711 593 default:
712 - // this should never happen.
594 + do_action( 'visualizer_pro_handle_tab', $tab, $this->_chart );
713 595 break;
714 596 }
715 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
597 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
716 598 }
717 599
718 600 /**
719 601 * Load code editor assets.
@@ -725,9 +607,9 @@
725 607
726 608 // data tables assets.
727 609 wp_register_script( 'visualizer-datatables', VISUALIZER_ABSURL . 'js/lib/datatables.min.js', array( 'jquery-ui-core' ), Visualizer_Plugin::VERSION );
728 610 wp_register_style( 'visualizer-datatables', VISUALIZER_ABSURL . 'css/lib/datatables.min.css', array(), Visualizer_Plugin::VERSION );
729 - 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 );
611 + 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 );
730 612 wp_enqueue_script( 'visualizer-datatables' );
731 613 wp_enqueue_style( 'visualizer-jquery-ui' );
732 614
733 615 if ( ! Visualizer_Module::is_pro() ) {
@@ -743,9 +625,9 @@
743 625 wp_register_script( 'visualizer-codemirror-matchbrackets', '//codemirror.net/addon/edit/matchbrackets.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
744 626 wp_register_script( 'visualizer-codemirror-closebrackets', '//codemirror.net/addon/edit/closebrackets.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
745 627 wp_register_script( 'visualizer-codemirror-sql', '//codemirror.net/mode/sql/sql.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
746 628 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 );
629 + 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 630 wp_register_style( 'visualizer-codemirror-core', '//codemirror.net/lib/codemirror.css', array(), Visualizer_Plugin::VERSION );
749 631 wp_register_style( 'visualizer-codemirror-hint', '//codemirror.net/addon/hint/show-hint.css', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
750 632
751 633 wp_enqueue_script( 'visualizer-codemirror-hint' );
@@ -759,9 +641,9 @@
759 641 'lineWrapping' => true,
760 642 'dragDrop' => false,
761 643 'matchBrackets' => true,
762 644 'autoCloseBrackets' => true,
763 - 'extraKeys' => array( 'Shift-Space' => 'autocomplete' ),
645 + 'extraKeys' => array( 'Ctrl-Space' => 'autocomplete' ),
764 646 'hintOptions' => array( 'tables' => $table_col_mapping ),
765 647 ),
766 648 )
767 649 );
@@ -770,25 +652,8 @@
770 652 return $table_col_mapping;
771 653 }
772 654
773 655 /**
774 - * Handle permissions from the new conslidated settings sidebar.
775 - */
776 - private function handlePermissions() {
777 - if ( ! Visualizer_Module::is_pro() ) {
778 - return;
779 - }
780 -
781 - // we will not support old free and new pro.
782 - // handling new free and old pro.
783 - if ( has_action( 'visualizer_pro_handle_tab' ) ) {
784 - do_action( 'visualizer_pro_handle_tab', 'permissions', $this->_chart );
785 - } else {
786 - do_action( 'visualizer_handle_permissions', $this->_chart );
787 - }
788 - }
789 -
790 - /**
791 656 * Handle data and settings page
792 657 */
793 658 private function _handleDataAndSettingsPage() {
794 659 if ( isset( $_POST['map_api_key'] ) ) {
@@ -793,30 +658,20 @@
793 658 private function _handleDataAndSettingsPage() {
794 659 if ( isset( $_POST['map_api_key'] ) ) {
795 660 update_option( 'visualizer-map-api-key', $_POST['map_api_key'] );
796 661 }
797 -
798 662 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 ) {
663 + if ( $this->_chart->post_status === 'auto-draft' ) {
803 664 $this->_chart->post_status = 'publish';
804 665
805 666 // 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 667 // we do not want any difference in data so disable revisions temporarily.
807 - $this->disableRevisionsTemporarily();
808 -
668 + add_filter( 'wp_revisions_to_keep', '__return_false' );
809 669 wp_update_post( $this->_chart->to_array() );
810 670 }
811 671 // 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 );
672 + if ( ! ( isset( $_POST['cancel'] ) && 1 === intval( $_POST['cancel'] ) ) ) {
673 + update_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SETTINGS, $_POST );
819 674
820 675 // we will keep a parameter called 'internal_title' that will be set to the given title or, if empty, the chart ID
821 676 // this will help in searching with the chart id.
822 677 $settings = get_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SETTINGS, true );
@@ -830,19 +685,14 @@
830 685 if ( empty( $title ) ) {
831 686 $title = $this->_chart->ID;
832 687 }
833 688 $settings['internal_title'] = $title;
834 - $settings_label = isset( $settings['pieResidueSliceLabel'] ) ? $settings['pieResidueSliceLabel'] : '';
835 - if ( empty( $settings_label ) ) {
836 - $settings['pieResidueSliceLabel'] = esc_html__( 'Other', 'visualizer' );
837 - } else {
838 - $settings['pieResidueSliceLabel'] = $settings_label;
839 - }
840 689 update_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SETTINGS, $settings );
841 690 }
842 691 $render = new Visualizer_Render_Page_Send();
843 692 $render->text = sprintf( '[visualizer id="%d"]', $this->_chart->ID );
844 693 wp_iframe( array( $render, 'render' ) );
694 +
845 695 return;
846 696 }
847 697 $data = $this->_getChartArray();
848 698 $sidebar = '';
@@ -863,9 +713,8 @@
863 713 wp_enqueue_style( 'visualizer-frame' );
864 714 wp_enqueue_script( 'visualizer-preview' );
865 715 wp_enqueue_script( 'visualizer-chosen' );
866 716 wp_enqueue_script( 'visualizer-render' );
867 - wp_enqueue_code_editor( array( 'type' => 'application/json' ) );
868 717
869 718 if ( Visualizer_Module::can_show_feature( 'simple-editor' ) ) {
870 719 wp_enqueue_script( 'visualizer-editor-simple' );
871 720 wp_localize_script(
@@ -873,10 +722,12 @@
873 722 'visualizer1',
874 723 array(
875 724 'ajax' => array(
876 725 'url' => admin_url( 'admin-ajax.php' ),
877 - 'nonces' => array(),
878 - 'actions' => array(),
726 + 'nonces' => array(
727 + ),
728 + 'actions' => array(
729 + ),
879 730 ),
880 731 )
881 732 );
882 733 }
@@ -887,15 +738,12 @@
887 738 'visualizer-render',
888 739 'visualizer',
889 740 array(
890 741 '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' ),
742 + 'invalid_source' => esc_html__( 'You have entered an invalid URL. Please provide a valid URL.', 'visualizer' ),
743 + 'loading' => esc_html__( 'Loading...', 'visualizer' ),
744 + 'json_error' => esc_html__( 'An error occured in fetching data.', 'visualizer' ),
745 + 'select_columns' => esc_html__( 'Please select a few columns to include in the chart.', 'visualizer' ),
898 746 ),
899 747 'charts' => array(
900 748 'canvas' => $data,
901 749 'id' => $this->_chart->ID,
@@ -926,9 +774,8 @@
926 774 'page_type' => 'chart',
927 775 'json_tag_separator' => Visualizer_Source_Json::TAG_SEPARATOR,
928 776 'json_tag_separator_view' => Visualizer_Source_Json::TAG_SEPARATOR_VIEW,
929 777 'is_front' => false,
930 - 'rest_base' => get_rest_url( null, 'wc/v3/reports/' ),
931 778 )
932 779 );
933 780
934 781 $render = new Visualizer_Render_Page_Data();
@@ -939,10 +786,11 @@
939 786 if ( filter_input( INPUT_GET, 'library', FILTER_VALIDATE_BOOLEAN ) ) {
940 787 $render->button = filter_input( INPUT_GET, 'action' ) === Visualizer_Plugin::ACTION_EDIT_CHART
941 788 ? esc_html__( 'Save Chart', 'visualizer' )
942 789 : esc_html__( 'Create Chart', 'visualizer' );
943 -
944 - $render->cancel_button = esc_html__( 'Cancel', 'visualizer' );
790 + if ( filter_input( INPUT_GET, 'action' ) === Visualizer_Plugin::ACTION_EDIT_CHART ) {
791 + $render->cancel_button = esc_html__( 'Cancel', 'visualizer' );
792 + }
945 793 } else {
946 794 $render->button = esc_attr__( 'Insert Chart', 'visualizer' );
947 795 }
948 796
@@ -965,12 +813,12 @@
965 813 * @access private
966 814 */
967 815 private function _handleTypesPage() {
968 816 // process post request
969 - if ( $_SERVER['REQUEST_METHOD'] === 'POST' && wp_verify_nonce( filter_input( INPUT_POST, 'nonce' ), 'visualizer-upload-data' ) ) {
817 + if ( $_SERVER['REQUEST_METHOD'] === 'POST' && wp_verify_nonce( filter_input( INPUT_POST, 'nonce' ) ) ) {
970 818 $type = filter_input( INPUT_POST, 'type' );
971 819 $library = filter_input( INPUT_POST, 'chart-library' );
972 - if ( Visualizer_Module_Admin::checkChartStatus( $type ) ) {
820 + if ( in_array( $type, Visualizer_Plugin::getChartTypes(), true ) ) {
973 821 if ( empty( $library ) ) {
974 822 // library cannot be empty.
975 823 do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, 'Chart library empty while creating the chart! Aborting...', 'error', __FILE__, __LINE__ );
976 824 return;
@@ -982,9 +830,9 @@
982 830 // if the chart has default data, update it with appropriate default data for new type
983 831 if ( filter_var( get_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_DEFAULT_DATA, true ), FILTER_VALIDATE_BOOLEAN ) ) {
984 832 $source = new Visualizer_Source_Csv( VISUALIZER_ABSPATH . DIRECTORY_SEPARATOR . 'samples' . DIRECTORY_SEPARATOR . $type . '.csv' );
985 833 $source->fetch();
986 - $this->_chart->post_content = $source->getData( get_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) );
834 + $this->_chart->post_content = $source->getData();
987 835 wp_update_post( $this->_chart->to_array() );
988 836 update_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
989 837 }
990 838
@@ -991,9 +839,9 @@
991 839 Visualizer_Module_Utility::set_defaults( $this->_chart );
992 840
993 841 // redirect to next tab
994 842 // changed by Ash/Upwork
995 - wp_redirect( esc_url_raw( add_query_arg( 'tab', 'settings' ) ) );
843 + wp_redirect( add_query_arg( 'tab', 'settings' ) );
996 844
997 845 return;
998 846 }
999 847 }
@@ -1022,80 +870,8 @@
1022 870 * Processes the CSV that is sent in the request as a string.
1023 871 *
1024 872 * @since 3.2.0
1025 873 */
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 874 private function handleCSVasString( $data, $editor_type ) {
1099 875 $source = null;
1100 876
1101 877 switch ( $editor_type ) {
@@ -1108,23 +884,14 @@
1108 884 foreach ( $values as $row ) {
1109 885 if ( empty( $row ) ) {
1110 886 continue;
1111 887 }
1112 - $row = explode( ',', $row );
1113 - $row = array_map(
1114 - function ( $r ) {
1115 - return '' === $r ? ' ' : $r;
1116 - },
1117 - $row
1118 - );
1119 - $row = implode( ',', $row );
1120 888 // don't use fpucsv here because we need to just dump the data
1121 889 // minus the empty rows
890 + // and if any row contains ' or ", fputcsv will mess it up
1122 891 // because fputcsv needs to tokenize
1123 - // we can standardize the CSV enclosure here and replace all ' with "
1124 - // we can assume that if there are an even number of ' they should be changed to "
1125 - // but that will screw up words like fo'c'sle
1126 - // so here let's just assume ' will NOT be used for enclosures
892 + // and let's standardize the CSV enclosure
893 + $row = str_replace( "'", VISUALIZER_CSV_ENCLOSURE, $row );
1127 894 fwrite( $handle, $row );
1128 895 fwrite( $handle, PHP_EOL );
1129 896 }
1130 897 }
@@ -1161,9 +928,9 @@
1161 928 foreach ( $types as $type ) {
1162 929 if ( empty( $type ) ) {
1163 930 $exclude[] = $index;
1164 931 }
1165 - ++$index;
932 + $index++;
1166 933 }
1167 934
1168 935 // when N headers are being renamed, the number of headers increases by N
1169 936 // because of the way datatable duplicates header information
@@ -1223,13 +990,9 @@
1223 990 // otherwise, assume this is a normal web request.
1224 991 $can_die = ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE );
1225 992
1226 993 // validate nonce
1227 - if (
1228 - ! isset( $_GET['nonce'] ) ||
1229 - ! wp_verify_nonce( $_GET['nonce'], 'visualizer-upload-data' ) ||
1230 - ! current_user_can( 'edit_posts' )
1231 - ) {
994 + if ( ! isset( $_GET['nonce'] ) || ! wp_verify_nonce( $_GET['nonce'] ) ) {
1232 995 if ( ! $can_die ) {
1233 996 return;
1234 997 }
1235 998 status_header( 403 );
@@ -1238,15 +1001,9 @@
1238 1001
1239 1002 // check chart, if chart exists
1240 1003 // do not use filter_input as it does not work for phpunit test cases, use filter_var instead
1241 1004 $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 - ) {
1005 + if ( ! $chart_id || ! ( $chart = get_post( $chart_id ) ) || $chart->post_type !== Visualizer_Plugin::CPT_VISUALIZER ) {
1249 1006 if ( ! $can_die ) {
1250 1007 return;
1251 1008 }
1252 1009 status_header( 400 );
@@ -1282,35 +1039,18 @@
1282 1039
1283 1040 // delete editor related data.
1284 1041 delete_post_meta( $chart_id, Visualizer_Plugin::CF_EDITOR );
1285 1042
1286 - // delete this so that a JSON import can be later edited manually without a problem.
1287 - delete_post_meta( $chart_id, Visualizer_Plugin::CF_EDITABLE_TABLE );
1288 -
1289 1043 $source = null;
1290 1044 $render = new Visualizer_Render_Page_Update();
1291 -
1292 - $remote_data = false;
1293 - if ( isset( $_POST['remote_data'] ) && function_exists( 'wp_http_validate_url' ) ) {
1294 - $remote_data = wp_http_validate_url( $_POST['remote_data'] );
1295 - }
1296 - 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 - }
1045 + if ( isset( $_POST['remote_data'] ) && filter_var( $_POST['remote_data'], FILTER_VALIDATE_URL ) ) {
1046 + $source = new Visualizer_Source_Csv_Remote( $_POST['remote_data'] );
1303 1047 if ( isset( $_POST['vz-import-time'] ) ) {
1304 - apply_filters( 'visualizer_pro_chart_schedule', $chart_id, $remote_data, $_POST['vz-import-time'] );
1048 + apply_filters( 'visualizer_pro_chart_schedule', $chart_id, $_POST['remote_data'], $_POST['vz-import-time'] );
1305 1049 }
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 - }
1050 + // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
1051 + } elseif ( isset( $_FILES['local_data'] ) && $_FILES['local_data']['error'] == 0 ) {
1052 + $source = new Visualizer_Source_Csv( $_FILES['local_data']['tmp_name'] );
1313 1053 } elseif ( isset( $_POST['chart_data'] ) && strlen( $_POST['chart_data'] ) > 0 ) {
1314 1054 $source = $this->handleCSVasString( $_POST['chart_data'], $_POST['editor-type'] );
1315 1055 update_post_meta( $chart_id, Visualizer_Plugin::CF_EDITOR, $_POST['editor-type'] );
1316 1056 } elseif ( isset( $_POST['table_data'] ) && 'yes' === $_POST['table_data'] ) {
@@ -1317,10 +1057,10 @@
1317 1057 $source = $this->handleTabularData();
1318 1058 update_post_meta( $chart_id, Visualizer_Plugin::CF_EDITOR, $_POST['editor-type'] );
1319 1059 } else {
1320 1060 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' ) );
1061 + $render->message = esc_html__( 'CSV file with chart data was not uploaded. Please try again.', 'visualizer' );
1062 + update_post_meta( $chart_id, Visualizer_Plugin::CF_ERROR, esc_html__( 'CSV file with chart data was not uploaded. Please try again.', 'visualizer' ) );
1323 1063 }
1324 1064
1325 1065 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 1066
@@ -1325,9 +1065,9 @@
1325 1065 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 1066
1327 1067 if ( $source ) {
1328 1068 if ( $source->fetch() ) {
1329 - $content = $source->getData( get_post_meta( $chart_id, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) );
1069 + $content = $source->getData();
1330 1070 $populate = true;
1331 1071 if ( is_string( $content ) && is_array( unserialize( $content ) ) ) {
1332 1072 $json = unserialize( $content );
1333 1073 // if source exists, so should data. if source exists but data is blank, do not populate the chart.
@@ -1341,9 +1081,8 @@
1341 1081 if ( $populate ) {
1342 1082 $chart->post_content = $content;
1343 1083 }
1344 1084 wp_update_post( $chart->to_array() );
1345 -
1346 1085 update_post_meta( $chart->ID, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
1347 1086 update_post_meta( $chart->ID, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() );
1348 1087 update_post_meta( $chart->ID, Visualizer_Plugin::CF_DEFAULT_DATA, 0 );
1349 1088
@@ -1351,26 +1090,17 @@
1351 1090
1352 1091 Visualizer_Module_Utility::set_defaults( $chart, null );
1353 1092
1354 1093 $settings = get_post_meta( $chart->ID, Visualizer_Plugin::CF_SETTINGS, true );
1355 - if ( isset( $settings['series'] ) && ! ( count( $settings['series'] ) - count( $source->getSeries() ) > 1 ) ) {
1356 - $diff_total_series = abs( count( $settings['series'] ) - count( $source->getSeries() ) );
1357 - if ( $diff_total_series ) {
1358 - foreach ( range( 1, $diff_total_series ) as $k => $diff_series ) {
1359 - $settings['series'][] = end( $settings['series'] );
1360 - }
1361 - update_post_meta( $chart->ID, Visualizer_Plugin::CF_SETTINGS, $settings );
1362 - }
1363 - }
1364 1094
1365 1095 $render->id = $chart->ID;
1366 - $render->data = json_encode( $source->getRawData( get_post_meta( $chart->ID, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) ) );
1096 + $render->data = json_encode( $source->getRawData() );
1367 1097 $render->series = json_encode( $source->getSeries() );
1368 1098 $render->settings = json_encode( $settings );
1369 1099 } else {
1370 1100 $error = $source->get_error();
1371 1101 if ( empty( $error ) ) {
1372 - $error = esc_html__( 'The CSV file couldn\'t be read. Check that it\'s properly formatted and try again.', 'visualizer' );
1102 + $error = esc_html__( 'CSV file is broken or invalid. Please try again.', 'visualizer' );
1373 1103 }
1374 1104 $render->message = $error;
1375 1105 do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( '%s for chart %d.', $error, $chart_id ), 'error', __FILE__, __LINE__ );
1376 1106 update_post_meta( $chart_id, Visualizer_Plugin::CF_ERROR, $error );
@@ -1381,9 +1111,9 @@
1381 1111 $render->render();
1382 1112 if ( ! $can_die ) {
1383 1113 return;
1384 1114 }
1385 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1115 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1386 1116 }
1387 1117
1388 1118 /**
1389 1119 * Clones the chart.
@@ -1422,26 +1152,23 @@
1422 1152 if ( strpos( $key, 'visualizer-' ) !== false ) {
1423 1153 add_post_meta( $new_chart_id, $key, maybe_unserialize( $value[0] ) );
1424 1154 }
1425 1155 }
1426 - $redirect = esc_url(
1427 - add_query_arg(
1428 - array(
1429 - 'page' => 'visualizer',
1430 - 'type' => filter_input( INPUT_GET, 'type' ),
1431 - 'vaction' => false,
1432 - ),
1433 - admin_url( 'admin.php' )
1156 + $redirect = add_query_arg(
1157 + array(
1158 + 'page' => 'visualizer',
1159 + 'type' => filter_input( INPUT_GET, 'type' ),
1160 + 'vaction' => false,
1434 1161 ),
1435 - null,
1436 - 'db'
1162 + admin_url( 'admin.php' )
1437 1163 );
1438 1164 }
1439 1165 }
1440 1166
1441 - if ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) {
1167 + if ( defined( 'WP_TESTS_DOMAIN' ) ) {
1442 1168 wp_die();
1443 1169 }
1170 +
1444 1171 wp_redirect( $redirect );
1445 1172 exit;
1446 1173 }
1447 1174
@@ -1472,9 +1199,9 @@
1472 1199 }
1473 1200 }
1474 1201 }
1475 1202
1476 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1203 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1477 1204 }
1478 1205
1479 1206 /**
1480 1207 * Handles chart data page.
@@ -1498,11 +1225,10 @@
1498 1225 'visualizer-render',
1499 1226 'visualizer',
1500 1227 array(
1501 1228 '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' ),
1229 + 'invalid_source' => esc_html__( 'You have entered an invalid URL. Please provide a valid URL.', 'visualizer' ),
1230 + 'loading' => esc_html__( 'Loading...', 'visualizer' ),
1505 1231 ),
1506 1232 'charts' => array(
1507 1233 'canvas' => $data,
1508 1234 ),
@@ -1528,24 +1254,12 @@
1528 1254 */
1529 1255 public function getQueryData() {
1530 1256 check_ajax_referer( Visualizer_Plugin::ACTION_FETCH_DB_DATA . Visualizer_Plugin::VERSION, 'security' );
1531 1257
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 1258 $params = wp_parse_args( $_POST['params'] );
1544 1259 $chart_id = filter_var( $params['chart_id'], FILTER_VALIDATE_INT );
1545 - $query = trim( $params['query'], ';' );
1546 1260
1547 - $source = new Visualizer_Source_Query( stripslashes( $query ), $chart_id, $params );
1261 + $source = new Visualizer_Source_Query( stripslashes( $params['query'] ), $chart_id, $params );
1548 1262 $html = $source->fetch( true );
1549 1263 $error = $source->get_error();
1550 1264 if ( ! empty( $error ) ) {
1551 1265 wp_send_json_error( array( 'msg' => $error ) );
@@ -1560,19 +1274,8 @@
1560 1274 */
1561 1275 public function saveQuery() {
1562 1276 check_ajax_referer( Visualizer_Plugin::ACTION_SAVE_DB_QUERY . Visualizer_Plugin::VERSION, 'security' );
1563 1277
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 1278 $chart_id = filter_input(
1576 1279 INPUT_GET,
1577 1280 'chart',
1578 1281 FILTER_VALIDATE_INT,
@@ -1585,9 +1288,9 @@
1585 1288
1586 1289 $hours = filter_input(
1587 1290 INPUT_POST,
1588 1291 'refresh',
1589 - FILTER_VALIDATE_FLOAT,
1292 + FILTER_VALIDATE_INT,
1590 1293 array(
1591 1294 'options' => array(
1592 1295 'min_range' => -1,
1593 1296 'max_range' => apply_filters( 'visualizer_is_business', false ) ? PHP_INT_MAX : -1,
@@ -1594,9 +1297,9 @@
1594 1297 ),
1595 1298 )
1596 1299 );
1597 1300
1598 - if ( ! is_numeric( $hours ) ) {
1301 + if ( ! is_int( $hours ) ) {
1599 1302 $hours = -1;
1600 1303 }
1601 1304
1602 1305 $render = new Visualizer_Render_Page_Update();
@@ -1601,14 +1304,13 @@
1601 1304
1602 1305 $render = new Visualizer_Render_Page_Update();
1603 1306 if ( $chart_id ) {
1604 1307 $params = wp_parse_args( $_POST['params'] );
1605 - $query = trim( $params['query'], ';' );
1606 - $source = new Visualizer_Source_Query( stripslashes( $query ), $chart_id, $params );
1308 + $source = new Visualizer_Source_Query( stripslashes( $params['query'] ), $chart_id, $params );
1607 1309 $source->fetch( false );
1608 1310 $error = $source->get_error();
1609 1311 if ( empty( $error ) ) {
1610 - update_post_meta( $chart_id, Visualizer_Plugin::CF_DB_QUERY, stripslashes( $query ) );
1312 + update_post_meta( $chart_id, Visualizer_Plugin::CF_DB_QUERY, stripslashes( $params['query'] ) );
1611 1313 update_post_meta( $chart_id, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() );
1612 1314 update_post_meta( $chart_id, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
1613 1315 update_post_meta( $chart_id, Visualizer_Plugin::CF_DB_SCHEDULE, $hours );
1614 1316 update_post_meta( $chart_id, Visualizer_Plugin::CF_DEFAULT_DATA, 0 );
@@ -1625,12 +1327,12 @@
1625 1327
1626 1328 wp_update_post(
1627 1329 array(
1628 1330 'ID' => $chart_id,
1629 - 'post_content' => $source->getData( get_post_meta( $chart_id, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) ),
1331 + 'post_content' => $source->getData(),
1630 1332 )
1631 1333 );
1632 - $render->data = json_encode( $source->getRawData( get_post_meta( $chart_id, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) ) );
1334 + $render->data = json_encode( $source->getRawData() );
1633 1335 $render->series = json_encode( $source->getSeries() );
1634 1336 $render->id = $chart_id;
1635 1337 } else {
1636 1338 $render->message = $error;
@@ -1637,9 +1339,9 @@
1637 1339 }
1638 1340 }
1639 1341 $render->render();
1640 1342 if ( ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE ) ) {
1641 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1343 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1642 1344 }
1643 1345 }
1644 1346
1645 1347
@@ -1664,9 +1366,9 @@
1664 1366
1665 1367 $hours = filter_input(
1666 1368 INPUT_POST,
1667 1369 'refresh',
1668 - FILTER_VALIDATE_FLOAT,
1370 + FILTER_VALIDATE_INT,
1669 1371 array(
1670 1372 'options' => array(
1671 1373 'min_range' => -1,
1672 1374 'max_range' => apply_filters( 'visualizer_is_business', false ) ? PHP_INT_MAX : -1,
@@ -1673,9 +1375,9 @@
1673 1375 ),
1674 1376 )
1675 1377 );
1676 1378
1677 - if ( ! is_numeric( $hours ) ) {
1379 + if ( ! $hours ) {
1678 1380 $hours = -1;
1679 1381 }
1680 1382
1681 1383 do_action( 'visualizer_save_filter', $chart_id, $hours );
@@ -1680,61 +1382,8 @@
1680 1382
1681 1383 do_action( 'visualizer_save_filter', $chart_id, $hours );
1682 1384
1683 1385 if ( ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE ) ) {
1684 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1386 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1685 1387 }
1686 - }
1687 -
1688 - /**
1689 - * Save chart image.
1690 - *
1691 - * @param string $base64_img Chart image.
1692 - * @param int $chart_id Chart ID.
1693 - * @param bool $save_attachment Save attachment.
1694 - * @return attachment ID
1695 - */
1696 - public function save_chart_image( $base64_img, $chart_id, $save_attachment = true ) {
1697 - // Delete old chart image.
1698 - $old_attachment_id = get_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_IMAGE, true );
1699 - if ( $old_attachment_id ) {
1700 - wp_delete_attachment( $old_attachment_id, true );
1701 - }
1702 -
1703 - if ( ! $save_attachment ) {
1704 - return 0;
1705 - }
1706 -
1707 - // Upload dir.
1708 - $upload_dir = wp_upload_dir();
1709 - $upload_path = str_replace( '/', DIRECTORY_SEPARATOR, $upload_dir['path'] ) . DIRECTORY_SEPARATOR;
1710 -
1711 - $img = str_replace( 'data:image/png;base64,', '', $base64_img );
1712 - $img = str_replace( ' ', '+', $img );
1713 - $decoded = base64_decode( $img );
1714 - $filename = 'visualization-' . $chart_id . '.png';
1715 - $file_type = 'image/png';
1716 - $hashed_filename = $filename;
1717 -
1718 - // Save the image in the uploads directory.
1719 - require_once ABSPATH . '/wp-admin/includes/file.php';
1720 - \WP_Filesystem();
1721 - 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 - $upload_file = $wp_filesystem->put_contents( $upload_path . $hashed_filename, $decoded );
1727 -
1728 - // Insert new chart image.
1729 - $attachment = array(
1730 - 'post_mime_type' => $file_type,
1731 - 'post_title' => preg_replace( '/\.[^.]+$/', '', basename( $hashed_filename ) ),
1732 - 'post_content' => '',
1733 - 'post_status' => 'inherit',
1734 - 'guid' => $upload_dir['url'] . '/' . basename( $hashed_filename ),
1735 - );
1736 -
1737 - $attach_id = wp_insert_attachment( $attachment, $upload_dir['path'] . '/' . $hashed_filename );
1738 - return $attach_id;
1739 1388 }
1740 1389 }