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 +148 -559 4.0.83.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.
@@ -107,10 +108,11 @@
107 108 */
108 109 public function setJsonSchedule() {
109 110 check_ajax_referer( Visualizer_Plugin::ACTION_JSON_SET_SCHEDULE . Visualizer_Plugin::VERSION, 'security' );
110 111
111 - $chart_id = isset( $_POST['chart'] ) ? filter_var(
112 - $_POST['chart'],
112 + $chart_id = filter_input(
113 + INPUT_POST,
114 + 'chart',
113 115 FILTER_VALIDATE_INT,
114 116 array(
115 117 'options' => array(
116 118 'min_range' => 1,
@@ -115,18 +117,14 @@
115 117 'options' => array(
116 118 'min_range' => 1,
117 119 ),
118 120 )
119 - ) : false;
121 + );
120 122
121 123 if ( ! $chart_id ) {
122 124 wp_send_json_error();
123 125 }
124 126
125 - if ( ! self::can_edit_chart( $chart_id ) ) {
126 - wp_send_json_error( array( 'msg' => esc_html__( 'You do not have permission to perform this action.', 'visualizer' ) ), 403 );
127 - }
128 -
129 127 $time = filter_input(
130 128 INPUT_POST,
131 129 'time',
132 130 FILTER_VALIDATE_INT,
@@ -136,30 +134,12 @@
136 134 ),
137 135 )
138 136 );
139 137
140 - if ( Visualizer_Module::is_pro() ) {
141 - $is_woocommerce_report = filter_input(
142 - INPUT_POST,
143 - 'is_woocommerce_report',
144 - FILTER_VALIDATE_BOOLEAN
145 - );
146 -
147 - if ( $is_woocommerce_report ) {
148 - update_post_meta( $chart_id, Visualizer_Plugin::CF_IS_WOOCOMMERCE_SOURCE, true );
149 - } else {
150 - delete_post_meta( $chart_id, Visualizer_Plugin::CF_IS_WOOCOMMERCE_SOURCE );
151 - }
152 - }
153 -
154 138 delete_post_meta( $chart_id, Visualizer_Plugin::CF_JSON_SCHEDULE );
155 139
156 140 if ( -1 < $time ) {
157 141 add_post_meta( $chart_id, Visualizer_Plugin::CF_JSON_SCHEDULE, $time );
158 - // Update schedules.
159 - $schedules = get_option( Visualizer_Plugin::CF_JSON_SCHEDULE, array() );
160 - $schedules[ $chart_id ] = time() + $time * HOUR_IN_SECONDS;
161 - update_option( Visualizer_Plugin::CF_JSON_SCHEDULE, $schedules );
162 142 }
163 143 wp_send_json_success();
164 144 }
165 145
@@ -172,12 +152,8 @@
172 152 */
173 153 public function getJsonRoots() {
174 154 check_ajax_referer( Visualizer_Plugin::ACTION_JSON_GET_ROOTS . Visualizer_Plugin::VERSION, 'security' );
175 155
176 - if ( ! current_user_can( 'edit_posts' ) ) {
177 - wp_send_json_error( array( 'msg' => esc_html__( 'You do not have permission to perform this action.', 'visualizer' ) ) );
178 - }
179 -
180 156 $params = wp_parse_args( $_POST['params'] );
181 157
182 158 $source = new Visualizer_Source_Json( $params );
183 159
@@ -198,18 +174,13 @@
198 174 */
199 175 public function getJsonData() {
200 176 check_ajax_referer( Visualizer_Plugin::ACTION_JSON_GET_DATA . Visualizer_Plugin::VERSION, 'security' );
201 177
202 - if ( ! current_user_can( 'edit_posts' ) ) {
203 - wp_send_json_error( array( 'msg' => esc_html__( 'You do not have permission to perform this action.', 'visualizer' ) ) );
204 - }
205 -
206 178 $params = wp_parse_args( $_POST['params'] );
207 179
208 180 $chart_id = $params['chart'];
209 181
210 - $chart = $chart_id ? get_post( $chart_id ) : null;
211 - if ( ! $chart || Visualizer_Plugin::CPT_VISUALIZER !== $chart->post_type || ! current_user_can( 'edit_post', $chart_id ) ) {
182 + if ( empty( $chart_id ) ) {
212 183 wp_die();
213 184 }
214 185
215 186 $source = new Visualizer_Source_Json( $params );
@@ -234,21 +205,20 @@
234 205 public function setJsonData() {
235 206 check_ajax_referer( Visualizer_Plugin::ACTION_JSON_SET_DATA . Visualizer_Plugin::VERSION, 'security' );
236 207
237 208 $params = $_POST;
238 - $chart_id = isset( $_GET['chart'] ) ? absint( $_GET['chart'] ) : 0;
209 + $chart_id = $_GET['chart'];
239 210
240 - if ( ! self::can_edit_chart( $chart_id ) ) {
241 - wp_die( esc_html__( 'You do not have permission to perform this action.', 'visualizer' ), '', array( 'response' => 403 ) );
211 + if ( empty( $chart_id ) ) {
212 + wp_die();
242 213 }
243 214
244 215 $chart = get_post( $chart_id );
245 216
246 217 $source = new Visualizer_Source_Json( $params );
247 - update_post_meta( $chart->ID, Visualizer_Plugin::CF_EDITABLE_TABLE, true );
248 218 $source->fetchFromEditableTable();
249 219
250 - $content = $source->getData( get_post_meta( $chart->ID, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) );
220 + $content = $source->getData();
251 221 $chart->post_content = $content;
252 222 wp_update_post( $chart->to_array() );
253 223 update_post_meta( $chart->ID, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
254 224 update_post_meta( $chart->ID, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() );
@@ -270,16 +240,8 @@
270 240 if ( ! empty( $params['paging'] ) ) {
271 241 add_post_meta( $chart->ID, Visualizer_Plugin::CF_JSON_PAGING, $params['paging'] );
272 242 }
273 243
274 - if ( Visualizer_Module::is_pro() ) {
275 - if ( ! empty( $params['vz_woo_source'] ) ) {
276 - update_post_meta( $chart->ID, Visualizer_Plugin::CF_JSON_WOOCOMMERCE_SOURCE, $params['vz_woo_source'] );
277 - } else {
278 - delete_post_meta( $chart->ID, Visualizer_Plugin::CF_JSON_WOOCOMMERCE_SOURCE );
279 - }
280 - }
281 -
282 244 $time = filter_input(
283 245 INPUT_POST,
284 246 'time',
285 247 FILTER_VALIDATE_INT,
@@ -303,13 +265,13 @@
303 265 delete_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_SCHEDULE );
304 266
305 267 $render = new Visualizer_Render_Page_Update();
306 268 $render->id = $chart->ID;
307 - $render->data = json_encode( $source->getRawData( get_post_meta( $chart_id, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) ) );
269 + $render->data = json_encode( $source->getRawData() );
308 270 $render->series = json_encode( $source->getSeries() );
309 271 $render->render();
310 272
311 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
273 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
312 274 }
313 275
314 276
315 277 /**
@@ -321,14 +283,8 @@
321 283 *
322 284 * @access public
323 285 */
324 286 public function getCharts() {
325 - check_ajax_referer( Visualizer_Plugin::ACTION_GET_CHARTS, 'nonce' );
326 -
327 - if ( ! current_user_can( 'edit_posts' ) ) {
328 - wp_send_json_error( array( 'msg' => esc_html__( 'You do not have permission to perform this action.', 'visualizer' ) ), 403 );
329 - }
330 -
331 287 $query_args = array(
332 288 'post_type' => Visualizer_Plugin::CPT_VISUALIZER,
333 289 'posts_per_page' => 9,
334 290 'paged' => filter_input(
@@ -342,11 +298,8 @@
342 298 ),
343 299 )
344 300 ),
345 301 );
346 - if ( ! current_user_can( 'edit_others_posts' ) ) {
347 - $query_args['author'] = get_current_user_id();
348 - }
349 302 $filter = filter_input( INPUT_GET, 's', FILTER_SANITIZE_STRING );
350 303 if ( empty( $filter ) ) {
351 304 // 'filter' is from the modal from the add media button.
352 305 $filter = filter_input( INPUT_GET, 'filter', FILTER_SANITIZE_STRING );
@@ -394,19 +347,19 @@
394 347 * @since 1.0.0
395 348 *
396 349 * @access private
397 350 *
398 - * @param WP_Post|null $chart The chart object.
351 + * @param WP_Post $chart The chart object.
399 352 *
400 353 * @return array The array of chart data.
401 354 */
402 - private function _getChartArray( $chart = null ) {
355 + private function _getChartArray( WP_Post $chart = null ) {
403 356 if ( is_null( $chart ) ) {
404 357 $chart = $this->_chart;
405 358 }
406 359 $type = get_post_meta( $chart->ID, Visualizer_Plugin::CF_CHART_TYPE, true );
407 360 $series = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_SERIES, get_post_meta( $chart->ID, Visualizer_Plugin::CF_SERIES, true ), $chart->ID, $type );
408 - $data = self::get_chart_data( $chart, $type );
361 + $data = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_DATA, unserialize( $chart->post_content ), $chart->ID, $type );
409 362 $library = $this->load_chart_type( $chart->ID );
410 363
411 364 $settings = get_post_meta( $chart->ID, Visualizer_Plugin::CF_SETTINGS, true );
412 365 $settings = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_SETTINGS, $settings, $chart->ID, $type );
@@ -422,13 +375,8 @@
422 375 }
423 376
424 377 $date_formats = Visualizer_Source::get_date_formats_if_exists( $series, $data );
425 378
426 - $code = '';
427 - if ( 'd3' === $library ) {
428 - $code = get_post_meta( $chart->ID, Visualizer_Module_AIBuilder::CF_D3_CODE, true );
429 - }
430 -
431 379 return array(
432 380 'type' => $type,
433 381 'series' => $series,
434 382 'settings' => $settings,
@@ -433,9 +381,8 @@
433 381 'series' => $series,
434 382 'settings' => $settings,
435 383 'data' => $data,
436 384 'library' => $library,
437 - 'code' => $code,
438 385 'css' => $css,
439 386 'date_formats' => $date_formats,
440 387 );
441 388 }
@@ -452,9 +399,9 @@
452 399 public static function _sendResponse( $results ) {
453 400 header( 'Content-type: application/json' );
454 401 nocache_headers();
455 402 echo json_encode( $results );
456 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
403 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
457 404 }
458 405
459 406 /**
460 407 * Deletes a chart from database.
@@ -465,14 +412,16 @@
465 412 * @access public
466 413 */
467 414 public function deleteChart() {
468 415 $is_post = $_SERVER['REQUEST_METHOD'] === 'POST';
469 - $input = $is_post ? $_POST : $_GET;
416 + $input_method = $is_post ? INPUT_POST : INPUT_GET;
470 417 $chart_id = $success = false;
471 - $nonce = isset( $input['nonce'] ) && wp_verify_nonce( $input['nonce'] );
472 - if ( $nonce ) {
473 - $chart_id = isset( $input['chart'] ) ? filter_var(
474 - $input['chart'],
418 + $nonce = wp_verify_nonce( filter_input( $input_method, 'nonce' ) );
419 + $capable = current_user_can( 'delete_posts' );
420 + if ( $nonce && $capable ) {
421 + $chart_id = filter_input(
422 + $input_method,
423 + 'chart',
475 424 FILTER_VALIDATE_INT,
476 425 array(
477 426 'options' => array(
478 427 'min_range' => 1,
@@ -477,34 +426,16 @@
477 426 'options' => array(
478 427 'min_range' => 1,
479 428 ),
480 429 )
481 - ) : false;
430 + );
482 431 if ( $chart_id ) {
483 432 $chart = get_post( $chart_id );
484 - $success = $chart
485 - && $chart->post_type === Visualizer_Plugin::CPT_VISUALIZER
486 - && (
487 - current_user_can( 'delete_post', $chart_id )
488 - || ( (int) $chart->post_author === get_current_user_id() && current_user_can( 'delete_posts' ) )
489 - );
433 + $success = $chart && $chart->post_type === Visualizer_Plugin::CPT_VISUALIZER;
490 434 }
491 435 }
492 436 if ( $success ) {
493 - global $sitepress;
494 - if ( Visualizer_Module::is_pro() && ( function_exists( 'icl_get_languages' ) && $sitepress instanceof \SitePress ) ) {
495 - $trid = $sitepress->get_element_trid( $chart_id, 'post_' . Visualizer_Plugin::CPT_VISUALIZER );
496 - $translations = $sitepress->get_element_translations( $trid );
497 - if ( ! empty( $translations ) ) {
498 - foreach ( $translations as $translated_post ) {
499 - wp_delete_post( $translated_post->element_id, true );
500 - }
501 - } else {
502 - wp_delete_post( $chart_id, true );
503 - }
504 - } else {
505 - wp_delete_post( $chart_id, true );
506 - }
437 + wp_delete_post( $chart_id, true );
507 438 }
508 439 if ( $is_post ) {
509 440 self::_sendResponse(
510 441 array(
@@ -552,111 +483,44 @@
552 483 *
553 484 * @access public
554 485 */
555 486 public function renderChartPages() {
556 - if ( ! current_user_can( 'edit_posts' ) ) {
557 - wp_die( __( 'You do not have permission to access this page.', 'visualizer' ) );
558 - }
559 -
560 487 defined( 'IFRAME_REQUEST' ) || define( 'IFRAME_REQUEST', 1 );
561 - if ( ! defined( 'ET_BUILDER_PRODUCT_VERSION' ) && function_exists( 'et_get_theme_version' ) ) {
562 - define( 'ET_BUILDER_PRODUCT_VERSION', et_get_theme_version() );
563 - }
564 - // Set current screen for the render chart.
565 - set_current_screen( 'visualizer_render_chart' );
566 488 // check chart, if chart not exists, will create new one and redirects to the same page with proper chart id
567 489 $chart_id = isset( $_GET['chart'] ) ? filter_var( $_GET['chart'], FILTER_VALIDATE_INT ) : '';
568 - if ( ! empty( $_POST ) ) {
569 - $_POST = map_deep( $_POST, 'wp_strip_all_tags' );
570 - }
571 - $chart = $chart_id ? get_post( $chart_id ) : null;
572 - if ( $chart && ! self::can_edit_chart( $chart_id ) ) {
573 - wp_die( esc_html__( 'You do not have permission to access this page.', 'visualizer' ), '', array( 'response' => 403 ) );
574 - }
575 - if ( ! $chart_id || ! $chart || $chart->post_type !== Visualizer_Plugin::CPT_VISUALIZER ) {
576 - if ( empty( $_GET['lang'] ) || empty( $_GET['parent_chart_id'] ) ) {
577 - $this->deleteOldCharts();
578 - $default_type = isset( $_GET['type'] ) && ! empty( $_GET['type'] ) ? $_GET['type'] : 'line';
579 - $chart_status = Visualizer_Module_Admin::checkChartStatus( $default_type );
580 - if ( ! $chart_status ) {
581 - $default_type = 'line';
582 - }
583 - $source = new Visualizer_Source_Csv( VISUALIZER_ABSPATH . DIRECTORY_SEPARATOR . 'samples' . DIRECTORY_SEPARATOR . $default_type . '.csv' );
584 - $source->fetch();
585 - $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,
586 513 array(
587 - 'post_type' => Visualizer_Plugin::CPT_VISUALIZER,
588 - 'post_title' => 'Visualization',
589 - 'post_author' => get_current_user_id(),
590 - 'post_status' => 'auto-draft',
591 - 'post_content' => $source->getData( get_post_meta( $chart_id, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) ),
514 + 'focusTarget' => 'datum',
592 515 )
593 516 );
594 - if ( $chart_id && ! is_wp_error( $chart_id ) ) {
595 - add_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_TYPE, $default_type );
596 - add_post_meta( $chart_id, Visualizer_Plugin::CF_DEFAULT_DATA, 1 );
597 - add_post_meta( $chart_id, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() );
598 - add_post_meta( $chart_id, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
599 - add_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_LIBRARY, '' );
600 - add_post_meta(
601 - $chart_id,
602 - Visualizer_Plugin::CF_SETTINGS,
603 - array(
604 - 'focusTarget' => 'datum',
605 - )
606 - );
607 -
608 - do_action( 'visualizer_pro_new_chart_defaults', $chart_id );
609 - }
610 - } else {
611 - $parent_chart_id = filter_var( $_GET['parent_chart_id'], FILTER_VALIDATE_INT );
612 - $success = false;
613 - if ( $parent_chart_id && self::can_edit_chart( $parent_chart_id ) ) {
614 - $parent_chart = get_post( $parent_chart_id );
615 - $success = $parent_chart && $parent_chart->post_type === Visualizer_Plugin::CPT_VISUALIZER;
616 - }
617 - if ( $success ) {
618 - $new_chart_id = wp_insert_post(
619 - array(
620 - 'post_type' => Visualizer_Plugin::CPT_VISUALIZER,
621 - 'post_title' => 'Visualization',
622 - 'post_author' => get_current_user_id(),
623 - 'post_status' => $parent_chart->post_status,
624 - 'post_content' => $parent_chart->post_content,
625 - )
626 - );
627 -
628 - if ( is_wp_error( $new_chart_id ) ) {
629 - 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__ );
630 - } else {
631 - $post_meta = get_post_meta( $parent_chart_id );
632 - $chart_id = $new_chart_id;
633 - foreach ( $post_meta as $key => $value ) {
634 - if ( strpos( $key, 'visualizer-' ) !== false ) {
635 - add_post_meta( $new_chart_id, $key, self::maybe_decode_content( $value[0] ) );
636 - }
637 - }
638 - }
639 - }
640 517 do_action( 'visualizer_pro_new_chart_defaults', $chart_id );
641 518 }
642 - wp_redirect( esc_url_raw( add_query_arg( 'chart', (int) $chart_id ) ) );
643 -
644 - if ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) {
645 - wp_die();
646 - }
647 - exit();
519 + wp_redirect( add_query_arg( 'chart', (int) $chart_id ) );
520 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
648 521 }
649 522
650 - $_POST['save_chart_image'] = isset( $_POST['save_chart_image'] ) && 'yes' === $_POST['save_chart_image'] ? true : false;
651 - $_POST['lazy_load_chart'] = isset( $_POST['lazy_load_chart'] ) && 'yes' === $_POST['lazy_load_chart'] ? true : false;
652 -
653 - if ( isset( $_POST['chart-img'] ) && ! empty( $_POST['chart-img'] ) ) {
654 - $attachment_id = $this->save_chart_image( $_POST['chart-img'], $chart_id, $_POST['save_chart_image'] );
655 - if ( $attachment_id ) {
656 - update_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_IMAGE, $attachment_id );
657 - }
658 - }
659 523 $lib = $this->load_chart_type( $chart_id );
660 524
661 525 // the alpha color picker (RGBA) is not supported by google.
662 526 $color_picker_dep = 'wp-color-picker';
@@ -669,9 +533,9 @@
669 533 wp_register_script( 'visualizer-chosen', VISUALIZER_ABSURL . 'js/lib/chosen.jquery.min.js', array( 'jquery' ), Visualizer_Plugin::VERSION );
670 534 wp_register_style( 'visualizer-chosen', VISUALIZER_ABSURL . 'css/lib/chosen.min.css', array(), Visualizer_Plugin::VERSION );
671 535
672 536 wp_register_style( 'visualizer-frame', VISUALIZER_ABSURL . 'css/frame.css', array( 'visualizer-chosen' ), Visualizer_Plugin::VERSION );
673 - 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 );
674 538 wp_register_script( 'visualizer-customization', $this->get_user_customization_js(), array(), null, true );
675 539 wp_register_script(
676 540 'visualizer-render',
677 541 VISUALIZER_ABSURL . 'js/render-facade.js',
@@ -710,9 +574,8 @@
710 574 if ( isset( $_POST['cancel'] ) && 1 === intval( $_POST['cancel'] ) ) {
711 575 // if the cancel button is clicked.
712 576 $this->undoRevisions( $chart_id, true );
713 577 } elseif ( isset( $_POST['save'] ) && 1 === intval( $_POST['save'] ) ) {
714 - $this->handlePermissions();
715 578 // if the save button is clicked.
716 579 $this->undoRevisions( $chart_id, false );
717 580 } else {
718 581 // if the edit button is clicked.
@@ -718,16 +581,8 @@
718 581 // if the edit button is clicked.
719 582 $this->_chart = $this->handleExistingRevisions( $chart_id, $this->_chart );
720 583 }
721 584
722 - // Clear existing chart cache.
723 - if ( isset( $_POST['save'] ) && 1 === intval( $_POST['save'] ) ) {
724 - $cache_key = Visualizer_Plugin::CF_CHART_CACHE . '_' . $chart_id;
725 - if ( get_transient( $cache_key ) ) {
726 - delete_transient( $cache_key );
727 - }
728 - }
729 -
730 585 switch ( $tab ) {
731 586 case 'settings':
732 587 $this->_handleDataAndSettingsPage();
733 588 break;
@@ -735,12 +590,12 @@
735 590 case 'visualizer': // fall through.
736 591 $this->_handleTypesPage();
737 592 break;
738 593 default:
739 - // this should never happen.
594 + do_action( 'visualizer_pro_handle_tab', $tab, $this->_chart );
740 595 break;
741 596 }
742 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
597 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
743 598 }
744 599
745 600 /**
746 601 * Load code editor assets.
@@ -752,9 +607,9 @@
752 607
753 608 // data tables assets.
754 609 wp_register_script( 'visualizer-datatables', VISUALIZER_ABSURL . 'js/lib/datatables.min.js', array( 'jquery-ui-core' ), Visualizer_Plugin::VERSION );
755 610 wp_register_style( 'visualizer-datatables', VISUALIZER_ABSURL . 'css/lib/datatables.min.css', array(), Visualizer_Plugin::VERSION );
756 - 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 );
757 612 wp_enqueue_script( 'visualizer-datatables' );
758 613 wp_enqueue_style( 'visualizer-jquery-ui' );
759 614
760 615 if ( ! Visualizer_Module::is_pro() ) {
@@ -770,9 +625,9 @@
770 625 wp_register_script( 'visualizer-codemirror-matchbrackets', '//codemirror.net/addon/edit/matchbrackets.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
771 626 wp_register_script( 'visualizer-codemirror-closebrackets', '//codemirror.net/addon/edit/closebrackets.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
772 627 wp_register_script( 'visualizer-codemirror-sql', '//codemirror.net/mode/sql/sql.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
773 628 wp_register_script( 'visualizer-codemirror-sql-hint', '//codemirror.net/addon/hint/sql-hint.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
774 - 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 );
775 630 wp_register_style( 'visualizer-codemirror-core', '//codemirror.net/lib/codemirror.css', array(), Visualizer_Plugin::VERSION );
776 631 wp_register_style( 'visualizer-codemirror-hint', '//codemirror.net/addon/hint/show-hint.css', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
777 632
778 633 wp_enqueue_script( 'visualizer-codemirror-hint' );
@@ -786,9 +641,9 @@
786 641 'lineWrapping' => true,
787 642 'dragDrop' => false,
788 643 'matchBrackets' => true,
789 644 'autoCloseBrackets' => true,
790 - 'extraKeys' => array( 'Shift-Space' => 'autocomplete' ),
645 + 'extraKeys' => array( 'Ctrl-Space' => 'autocomplete' ),
791 646 'hintOptions' => array( 'tables' => $table_col_mapping ),
792 647 ),
793 648 )
794 649 );
@@ -797,54 +652,26 @@
797 652 return $table_col_mapping;
798 653 }
799 654
800 655 /**
801 - * Handle permissions from the new conslidated settings sidebar.
802 - */
803 - private function handlePermissions() {
804 - if ( ! Visualizer_Module::is_pro() ) {
805 - return;
806 - }
807 -
808 - // we will not support old free and new pro.
809 - // handling new free and old pro.
810 - if ( has_action( 'visualizer_pro_handle_tab' ) ) {
811 - do_action( 'visualizer_pro_handle_tab', 'permissions', $this->_chart );
812 - } else {
813 - do_action( 'visualizer_handle_permissions', $this->_chart );
814 - }
815 - }
816 -
817 - /**
818 656 * Handle data and settings page
819 657 */
820 658 private function _handleDataAndSettingsPage() {
659 + if ( isset( $_POST['map_api_key'] ) ) {
660 + update_option( 'visualizer-map-api-key', $_POST['map_api_key'] );
661 + }
821 662 if ( $_SERVER['REQUEST_METHOD'] === 'POST' && isset( $_GET['nonce'] ) && wp_verify_nonce( $_GET['nonce'] ) ) {
822 - $is_canceled = isset( $_POST['cancel'] ) && 1 === intval( $_POST['cancel'] );
823 - $is_newly_created = $this->_chart->post_status === 'auto-draft';
824 -
825 - if ( isset( $_POST['map_api_key'] ) && current_user_can( 'manage_options' ) ) {
826 - update_option( 'visualizer-map-api-key', sanitize_text_field( wp_unslash( $_POST['map_api_key'] ) ) );
827 - }
828 -
829 - if ( $is_newly_created && ! $is_canceled ) {
663 + if ( $this->_chart->post_status === 'auto-draft' ) {
830 664 $this->_chart->post_status = 'publish';
831 665
832 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.
833 667 // we do not want any difference in data so disable revisions temporarily.
834 - $this->disableRevisionsTemporarily();
835 -
668 + add_filter( 'wp_revisions_to_keep', '__return_false' );
836 669 wp_update_post( $this->_chart->to_array() );
837 670 }
838 671 // save meta data only when it is NOT being canceled.
839 - if ( ! $is_canceled ) {
840 - $post_settings = $_POST;
841 - $existing = get_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SETTINGS, true );
842 - if ( isset( $existing['colors'] ) && is_array( $existing['colors'] ) && ! isset( $post_settings['colors'] ) ) {
843 - $post_settings['colors'] = $existing['colors'];
844 - }
845 - $post_settings = $this->sanitizeSettings( $post_settings );
846 - 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 );
847 674
848 675 // we will keep a parameter called 'internal_title' that will be set to the given title or, if empty, the chart ID
849 676 // this will help in searching with the chart id.
850 677 $settings = get_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SETTINGS, true );
@@ -858,19 +685,14 @@
858 685 if ( empty( $title ) ) {
859 686 $title = $this->_chart->ID;
860 687 }
861 688 $settings['internal_title'] = $title;
862 - $settings_label = isset( $settings['pieResidueSliceLabel'] ) ? $settings['pieResidueSliceLabel'] : '';
863 - if ( empty( $settings_label ) ) {
864 - $settings['pieResidueSliceLabel'] = esc_html__( 'Other', 'visualizer' );
865 - } else {
866 - $settings['pieResidueSliceLabel'] = $settings_label;
867 - }
868 689 update_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SETTINGS, $settings );
869 690 }
870 691 $render = new Visualizer_Render_Page_Send();
871 692 $render->text = sprintf( '[visualizer id="%d"]', $this->_chart->ID );
872 693 wp_iframe( array( $render, 'render' ) );
694 +
873 695 return;
874 696 }
875 697 $data = $this->_getChartArray();
876 698 $sidebar = '';
@@ -891,9 +713,8 @@
891 713 wp_enqueue_style( 'visualizer-frame' );
892 714 wp_enqueue_script( 'visualizer-preview' );
893 715 wp_enqueue_script( 'visualizer-chosen' );
894 716 wp_enqueue_script( 'visualizer-render' );
895 - wp_enqueue_code_editor( array( 'type' => 'application/json' ) );
896 717
897 718 if ( Visualizer_Module::can_show_feature( 'simple-editor' ) ) {
898 719 wp_enqueue_script( 'visualizer-editor-simple' );
899 720 wp_localize_script(
@@ -901,10 +722,12 @@
901 722 'visualizer1',
902 723 array(
903 724 'ajax' => array(
904 725 'url' => admin_url( 'admin-ajax.php' ),
905 - 'nonces' => array(),
906 - 'actions' => array(),
726 + 'nonces' => array(
727 + ),
728 + 'actions' => array(
729 + ),
907 730 ),
908 731 )
909 732 );
910 733 }
@@ -915,15 +738,12 @@
915 738 'visualizer-render',
916 739 'visualizer',
917 740 array(
918 741 'l10n' => array(
919 - 'invalid_source' => esc_html__( 'The URL you entered is invalid. Please enter a valid URL.', 'visualizer' ),
920 - 'loading' => esc_html__( 'Loading...', 'visualizer' ),
921 - 'json_error' => esc_html__( 'An error occured in fetching data.', 'visualizer' ),
922 - 'select_columns' => esc_html__( 'Please select a few columns to include in the chart.', 'visualizer' ),
923 - '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' ),
924 - 'copied' => __( 'The data has been copied to your clipboard. Hit Ctrl-V/Cmd-V in your spreadsheet editor to paste the data.', 'visualizer' ),
925 - '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' ),
926 746 ),
927 747 'charts' => array(
928 748 'canvas' => $data,
929 749 'id' => $this->_chart->ID,
@@ -954,9 +774,8 @@
954 774 'page_type' => 'chart',
955 775 'json_tag_separator' => Visualizer_Source_Json::TAG_SEPARATOR,
956 776 'json_tag_separator_view' => Visualizer_Source_Json::TAG_SEPARATOR_VIEW,
957 777 'is_front' => false,
958 - 'rest_base' => get_rest_url( null, 'wc/v3/reports/' ),
959 778 )
960 779 );
961 780
962 781 $render = new Visualizer_Render_Page_Data();
@@ -967,10 +786,11 @@
967 786 if ( filter_input( INPUT_GET, 'library', FILTER_VALIDATE_BOOLEAN ) ) {
968 787 $render->button = filter_input( INPUT_GET, 'action' ) === Visualizer_Plugin::ACTION_EDIT_CHART
969 788 ? esc_html__( 'Save Chart', 'visualizer' )
970 789 : esc_html__( 'Create Chart', 'visualizer' );
971 -
972 - $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 + }
973 793 } else {
974 794 $render->button = esc_attr__( 'Insert Chart', 'visualizer' );
975 795 }
976 796
@@ -993,12 +813,12 @@
993 813 * @access private
994 814 */
995 815 private function _handleTypesPage() {
996 816 // process post request
997 - 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' ) ) ) {
998 818 $type = filter_input( INPUT_POST, 'type' );
999 819 $library = filter_input( INPUT_POST, 'chart-library' );
1000 - if ( Visualizer_Module_Admin::checkChartStatus( $type ) ) {
820 + if ( in_array( $type, Visualizer_Plugin::getChartTypes(), true ) ) {
1001 821 if ( empty( $library ) ) {
1002 822 // library cannot be empty.
1003 823 do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, 'Chart library empty while creating the chart! Aborting...', 'error', __FILE__, __LINE__ );
1004 824 return;
@@ -1010,9 +830,9 @@
1010 830 // if the chart has default data, update it with appropriate default data for new type
1011 831 if ( filter_var( get_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_DEFAULT_DATA, true ), FILTER_VALIDATE_BOOLEAN ) ) {
1012 832 $source = new Visualizer_Source_Csv( VISUALIZER_ABSPATH . DIRECTORY_SEPARATOR . 'samples' . DIRECTORY_SEPARATOR . $type . '.csv' );
1013 833 $source->fetch();
1014 - $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();
1015 835 wp_update_post( $this->_chart->to_array() );
1016 836 update_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
1017 837 }
1018 838
@@ -1019,9 +839,9 @@
1019 839 Visualizer_Module_Utility::set_defaults( $this->_chart );
1020 840
1021 841 // redirect to next tab
1022 842 // changed by Ash/Upwork
1023 - wp_redirect( esc_url_raw( add_query_arg( 'tab', 'settings' ) ) );
843 + wp_redirect( add_query_arg( 'tab', 'settings' ) );
1024 844
1025 845 return;
1026 846 }
1027 847 }
@@ -1034,35 +854,8 @@
1034 854 wp_iframe( array( $render, 'render' ) );
1035 855 }
1036 856
1037 857 /**
1038 - * Sanitize settings data from the request.
1039 - *
1040 - * @param array<string, mixed> $post_data The POST data to sanitize.
1041 - * @return array<string, mixed> The sanitized settings data.
1042 - */
1043 - private function sanitizeSettings( $post_data ): array {
1044 - $chart_img = '';
1045 - if ( isset( $post_data['chart-img'] ) ) {
1046 - $chart_img = wp_unslash( $post_data['chart-img'] );
1047 - unset( $post_data['chart-img'] );
1048 - }
1049 -
1050 - $post_data = map_deep(
1051 - $post_data,
1052 - 'sanitize_textarea_field'
1053 - );
1054 -
1055 - // The value is a client-side canvas export; keep it only when it is a
1056 - // base64 image data URI so nothing else is ever stored unsanitized.
1057 - if ( is_string( $chart_img ) && preg_match( '#^data:image/(png|jpeg|webp);base64,[A-Za-z0-9+/ ]+=*$#', $chart_img ) ) {
1058 - $post_data['chart-img'] = $chart_img;
1059 - }
1060 -
1061 - return $post_data;
1062 - }
1063 -
1064 - /**
1065 858 * Renders flattr script in the iframe <head>
1066 859 *
1067 860 * @since 1.4.2
1068 861 * @action admin_head
@@ -1077,81 +870,8 @@
1077 870 * Processes the CSV that is sent in the request as a string.
1078 871 *
1079 872 * @since 3.2.0
1080 873 */
1081 - /**
1082 - * Determines whether a remote URL serves an XLSX file.
1083 - *
1084 - * Used as a fallback when the URL path has no recognisable file extension
1085 - * (e.g. SharePoint, signed S3 URLs, or "download?id=…" endpoints).
1086 - *
1087 - * Uses the shared remote-fetch policy to block non-public destinations,
1088 - * and streams the response to a temp file so no body data is held in memory
1089 - * regardless of whether the server honours the Range header.
1090 - *
1091 - * The check relies on the ZIP magic number (PK\x03\x04) that every XLSX
1092 - * file begins with, making it immune to misleading Content-Type headers
1093 - * such as application/octet-stream. Content-Type is used as a last-resort
1094 - * fallback only when the temp file is empty (e.g. a HEAD-only server).
1095 - *
1096 - * @access private
1097 - * @param string $url The remote URL to probe.
1098 - * @return bool TRUE if the file appears to be XLSX, FALSE otherwise.
1099 - */
1100 - private static function _url_is_xlsx( $url ) {
1101 - $tmpfile = wp_tempnam( 'visualizer_xlsx_probe' );
1102 - if ( ! $tmpfile ) {
1103 - return false;
1104 - }
1105 -
1106 - $response = Visualizer_Remote_Fetch::request(
1107 - $url,
1108 - array(
1109 - 'timeout' => 10,
1110 - 'user-agent' => 'WordPress/' . get_bloginfo( 'version' ),
1111 - 'headers' => array( 'Range' => 'bytes=0-3' ),
1112 - 'stream' => true,
1113 - 'filename' => $tmpfile,
1114 - 'limit_response_size' => 4,
1115 - )
1116 - );
1117 -
1118 - if ( is_wp_error( $response ) ) {
1119 - @unlink( $tmpfile ); // phpcs:ignore WordPress.PHP.NoSilencedErrors
1120 - return false;
1121 - }
1122 -
1123 - $magic = '';
1124 - // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fopen
1125 - $fh = @fopen( $tmpfile, 'rb' ); // phpcs:ignore WordPress.PHP.NoSilencedErrors
1126 - if ( $fh ) {
1127 - $magic = fread( $fh, 4 ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fread
1128 - fclose( $fh ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose
1129 - }
1130 - @unlink( $tmpfile ); // phpcs:ignore WordPress.PHP.NoSilencedErrors
1131 -
1132 - if ( strlen( $magic ) >= 4 ) {
1133 - // XLSX (and all ZIP-based Office formats) start with PK\x03\x04.
1134 - return $magic === "PK\x03\x04";
1135 - }
1136 -
1137 - // Last resort: server returned an empty body (e.g. ignored Range and
1138 - // returned only headers). Check Content-Type from the same response.
1139 - // application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
1140 - return false !== strpos(
1141 - wp_remote_retrieve_header( $response, 'content-type' ),
1142 - 'spreadsheetml'
1143 - );
1144 - }
1145 -
1146 - /**
1147 - * Parses a raw CSV string or editor payload and returns a source object.
1148 - *
1149 - * @access private
1150 - * @param string $data The raw CSV data string.
1151 - * @param string $editor_type The editor type ('text' or 'tabular').
1152 - * @return Visualizer_Source|null The populated source object, or null on failure.
1153 - */
1154 874 private function handleCSVasString( $data, $editor_type ) {
1155 875 $source = null;
1156 876
1157 877 switch ( $editor_type ) {
@@ -1164,23 +884,14 @@
1164 884 foreach ( $values as $row ) {
1165 885 if ( empty( $row ) ) {
1166 886 continue;
1167 887 }
1168 - $row = explode( ',', $row );
1169 - $row = array_map(
1170 - function ( $r ) {
1171 - return '' === $r ? ' ' : $r;
1172 - },
1173 - $row
1174 - );
1175 - $row = implode( ',', $row );
1176 888 // don't use fpucsv here because we need to just dump the data
1177 889 // minus the empty rows
890 + // and if any row contains ' or ", fputcsv will mess it up
1178 891 // because fputcsv needs to tokenize
1179 - // we can standardize the CSV enclosure here and replace all ' with "
1180 - // we can assume that if there are an even number of ' they should be changed to "
1181 - // but that will screw up words like fo'c'sle
1182 - // 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 );
1183 894 fwrite( $handle, $row );
1184 895 fwrite( $handle, PHP_EOL );
1185 896 }
1186 897 }
@@ -1217,9 +928,9 @@
1217 928 foreach ( $types as $type ) {
1218 929 if ( empty( $type ) ) {
1219 930 $exclude[] = $index;
1220 931 }
1221 - ++$index;
932 + $index++;
1222 933 }
1223 934
1224 935 // when N headers are being renamed, the number of headers increases by N
1225 936 // because of the way datatable duplicates header information
@@ -1277,16 +988,11 @@
1277 988 public function uploadData() {
1278 989 // if this is being called internally from pro and VISUALIZER_DO_NOT_DIE is set.
1279 990 // otherwise, assume this is a normal web request.
1280 991 $can_die = ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE );
1281 - // $can_die also gates the capability checks below, so VISUALIZER_DO_NOT_DIE must stay internal-only (never set from request input or globally).
1282 992
1283 - // validate nonce; capability check applies to web requests only, not trusted internal calls.
1284 - if (
1285 - ! isset( $_GET['nonce'] ) ||
1286 - ! wp_verify_nonce( $_GET['nonce'], 'visualizer-upload-data' ) ||
1287 - ( $can_die && ! current_user_can( 'edit_posts' ) )
1288 - ) {
993 + // validate nonce
994 + if ( ! isset( $_GET['nonce'] ) || ! wp_verify_nonce( $_GET['nonce'] ) ) {
1289 995 if ( ! $can_die ) {
1290 996 return;
1291 997 }
1292 998 status_header( 403 );
@@ -1295,15 +1001,9 @@
1295 1001
1296 1002 // check chart, if chart exists
1297 1003 // do not use filter_input as it does not work for phpunit test cases, use filter_var instead
1298 1004 $chart_id = isset( $_GET['chart'] ) ? filter_var( $_GET['chart'], FILTER_VALIDATE_INT ) : '';
1299 - $chart = $chart_id ? get_post( $chart_id ) : null;
1300 - if (
1301 - ! $chart_id ||
1302 - ! $chart ||
1303 - $chart->post_type !== Visualizer_Plugin::CPT_VISUALIZER ||
1304 - ( $can_die && ! current_user_can( 'edit_post', $chart_id ) )
1305 - ) {
1005 + if ( ! $chart_id || ! ( $chart = get_post( $chart_id ) ) || $chart->post_type !== Visualizer_Plugin::CPT_VISUALIZER ) {
1306 1006 if ( ! $can_die ) {
1307 1007 return;
1308 1008 }
1309 1009 status_header( 400 );
@@ -1339,35 +1039,18 @@
1339 1039
1340 1040 // delete editor related data.
1341 1041 delete_post_meta( $chart_id, Visualizer_Plugin::CF_EDITOR );
1342 1042
1343 - // delete this so that a JSON import can be later edited manually without a problem.
1344 - delete_post_meta( $chart_id, Visualizer_Plugin::CF_EDITABLE_TABLE );
1345 -
1346 1043 $source = null;
1347 1044 $render = new Visualizer_Render_Page_Update();
1348 -
1349 - $remote_data = false;
1350 - if ( isset( $_POST['remote_data'] ) && function_exists( 'wp_http_validate_url' ) ) {
1351 - $remote_data = wp_http_validate_url( $_POST['remote_data'] );
1352 - }
1353 - if ( false !== $remote_data ) {
1354 - $remote_ext = strtolower( pathinfo( parse_url( $remote_data, PHP_URL_PATH ), PATHINFO_EXTENSION ) );
1355 - if ( 'xlsx' === $remote_ext || ( 'csv' !== $remote_ext && self::_url_is_xlsx( $remote_data ) ) ) {
1356 - $source = new Visualizer_Source_Xlsx_Remote( $remote_data );
1357 - } else {
1358 - $source = new Visualizer_Source_Csv_Remote( $remote_data );
1359 - }
1045 + if ( isset( $_POST['remote_data'] ) && filter_var( $_POST['remote_data'], FILTER_VALIDATE_URL ) ) {
1046 + $source = new Visualizer_Source_Csv_Remote( $_POST['remote_data'] );
1360 1047 if ( isset( $_POST['vz-import-time'] ) ) {
1361 - 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'] );
1362 1049 }
1363 - } elseif ( isset( $_FILES['local_data'] ) && $_FILES['local_data']['error'] === 0 ) {
1364 - $local_ext = strtolower( pathinfo( isset( $_FILES['local_data']['name'] ) ? $_FILES['local_data']['name'] : '', PATHINFO_EXTENSION ) );
1365 - if ( 'xlsx' === $local_ext ) {
1366 - $source = new Visualizer_Source_Xlsx( $_FILES['local_data']['tmp_name'] );
1367 - } else {
1368 - $source = new Visualizer_Source_Csv( $_FILES['local_data']['tmp_name'] );
1369 - }
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'] );
1370 1053 } elseif ( isset( $_POST['chart_data'] ) && strlen( $_POST['chart_data'] ) > 0 ) {
1371 1054 $source = $this->handleCSVasString( $_POST['chart_data'], $_POST['editor-type'] );
1372 1055 update_post_meta( $chart_id, Visualizer_Plugin::CF_EDITOR, $_POST['editor-type'] );
1373 1056 } elseif ( isset( $_POST['table_data'] ) && 'yes' === $_POST['table_data'] ) {
@@ -1374,10 +1057,10 @@
1374 1057 $source = $this->handleTabularData();
1375 1058 update_post_meta( $chart_id, Visualizer_Plugin::CF_EDITOR, $_POST['editor-type'] );
1376 1059 } else {
1377 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__ );
1378 - $render->message = esc_html__( 'No CSV file was received. Select a file and try uploading again.', 'visualizer' );
1379 - 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' ) );
1380 1063 }
1381 1064
1382 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__ );
1383 1066
@@ -1382,12 +1065,12 @@
1382 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__ );
1383 1066
1384 1067 if ( $source ) {
1385 1068 if ( $source->fetch() ) {
1386 - $content = $source->getData( get_post_meta( $chart_id, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) );
1069 + $content = $source->getData();
1387 1070 $populate = true;
1388 - $json = self::decode_content( $content );
1389 - if ( is_array( $json ) ) {
1071 + if ( is_string( $content ) && is_array( unserialize( $content ) ) ) {
1072 + $json = unserialize( $content );
1390 1073 // if source exists, so should data. if source exists but data is blank, do not populate the chart.
1391 1074 // if we populate the data even if it is empty, the chart will show "Table has no columns".
1392 1075 if ( array_key_exists( 'source', $json ) && ! empty( $json['source'] ) && ( ! array_key_exists( 'data', $json ) || empty( $json['data'] ) ) ) {
1393 1076 do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( 'Not populating chart data as source exists (%s) but data is empty!', $json['source'] ), 'warn', __FILE__, __LINE__ );
@@ -1398,9 +1081,8 @@
1398 1081 if ( $populate ) {
1399 1082 $chart->post_content = $content;
1400 1083 }
1401 1084 wp_update_post( $chart->to_array() );
1402 -
1403 1085 update_post_meta( $chart->ID, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
1404 1086 update_post_meta( $chart->ID, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() );
1405 1087 update_post_meta( $chart->ID, Visualizer_Plugin::CF_DEFAULT_DATA, 0 );
1406 1088
@@ -1408,26 +1090,17 @@
1408 1090
1409 1091 Visualizer_Module_Utility::set_defaults( $chart, null );
1410 1092
1411 1093 $settings = get_post_meta( $chart->ID, Visualizer_Plugin::CF_SETTINGS, true );
1412 - if ( isset( $settings['series'] ) && ! ( count( $settings['series'] ) - count( $source->getSeries() ) > 1 ) ) {
1413 - $diff_total_series = abs( count( $settings['series'] ) - count( $source->getSeries() ) );
1414 - if ( $diff_total_series ) {
1415 - foreach ( range( 1, $diff_total_series ) as $k => $diff_series ) {
1416 - $settings['series'][] = end( $settings['series'] );
1417 - }
1418 - update_post_meta( $chart->ID, Visualizer_Plugin::CF_SETTINGS, $settings );
1419 - }
1420 - }
1421 1094
1422 1095 $render->id = $chart->ID;
1423 - $render->data = json_encode( $source->getRawData( get_post_meta( $chart->ID, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) ) );
1096 + $render->data = json_encode( $source->getRawData() );
1424 1097 $render->series = json_encode( $source->getSeries() );
1425 1098 $render->settings = json_encode( $settings );
1426 1099 } else {
1427 1100 $error = $source->get_error();
1428 1101 if ( empty( $error ) ) {
1429 - $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' );
1430 1103 }
1431 1104 $render->message = $error;
1432 1105 do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( '%s for chart %d.', $error, $chart_id ), 'error', __FILE__, __LINE__ );
1433 1106 update_post_meta( $chart_id, Visualizer_Plugin::CF_ERROR, $error );
@@ -1438,9 +1111,9 @@
1438 1111 $render->render();
1439 1112 if ( ! $can_die ) {
1440 1113 return;
1441 1114 }
1442 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1115 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1443 1116 }
1444 1117
1445 1118 /**
1446 1119 * Clones the chart.
@@ -1451,11 +1124,12 @@
1451 1124 */
1452 1125 public function cloneChart() {
1453 1126 $chart_id = $success = false;
1454 1127 $nonce = isset( $_GET['nonce'] ) && wp_verify_nonce( $_GET['nonce'], Visualizer_Plugin::ACTION_CLONE_CHART );
1455 - if ( $nonce ) {
1128 + $capable = current_user_can( 'edit_posts' );
1129 + if ( $nonce && $capable ) {
1456 1130 $chart_id = isset( $_GET['chart'] ) ? filter_var( $_GET['chart'], FILTER_VALIDATE_INT ) : '';
1457 - if ( $chart_id && self::can_edit_chart( $chart_id ) ) {
1131 + if ( $chart_id ) {
1458 1132 $chart = get_post( $chart_id );
1459 1133 $success = $chart && $chart->post_type === Visualizer_Plugin::CPT_VISUALIZER;
1460 1134 }
1461 1135 }
@@ -1475,29 +1149,26 @@
1475 1149 } else {
1476 1150 $post_meta = get_post_meta( $chart_id );
1477 1151 foreach ( $post_meta as $key => $value ) {
1478 1152 if ( strpos( $key, 'visualizer-' ) !== false ) {
1479 - add_post_meta( $new_chart_id, $key, self::maybe_decode_content( $value[0] ) );
1153 + add_post_meta( $new_chart_id, $key, maybe_unserialize( $value[0] ) );
1480 1154 }
1481 1155 }
1482 - $redirect = esc_url(
1483 - add_query_arg(
1484 - array(
1485 - 'page' => 'visualizer',
1486 - 'type' => filter_input( INPUT_GET, 'type' ),
1487 - 'vaction' => false,
1488 - ),
1489 - admin_url( 'admin.php' )
1156 + $redirect = add_query_arg(
1157 + array(
1158 + 'page' => 'visualizer',
1159 + 'type' => filter_input( INPUT_GET, 'type' ),
1160 + 'vaction' => false,
1490 1161 ),
1491 - null,
1492 - 'db'
1162 + admin_url( 'admin.php' )
1493 1163 );
1494 1164 }
1495 1165 }
1496 1166
1497 - if ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) {
1167 + if ( defined( 'WP_TESTS_DOMAIN' ) ) {
1498 1168 wp_die();
1499 1169 }
1170 +
1500 1171 wp_redirect( $redirect );
1501 1172 exit;
1502 1173 }
1503 1174
@@ -1509,25 +1180,28 @@
1509 1180 * @access public
1510 1181 */
1511 1182 public function exportData() {
1512 1183 check_ajax_referer( Visualizer_Plugin::ACTION_EXPORT_DATA . Visualizer_Plugin::VERSION, 'security' );
1513 - $chart_id = isset( $_GET['chart'] ) ? filter_var(
1514 - $_GET['chart'],
1515 - FILTER_VALIDATE_INT,
1516 - array(
1517 - 'options' => array(
1518 - 'min_range' => 1,
1519 - ),
1520 - )
1521 - ) : '';
1522 - if ( $chart_id && self::can_edit_chart( $chart_id ) ) {
1523 - $data = $this->_getDataAs( $chart_id, 'csv' );
1524 - if ( $data ) {
1525 - echo wp_send_json_success( $data );
1184 + $capable = current_user_can( 'edit_posts' );
1185 + if ( $capable ) {
1186 + $chart_id = isset( $_GET['chart'] ) ? filter_var(
1187 + $_GET['chart'],
1188 + FILTER_VALIDATE_INT,
1189 + array(
1190 + 'options' => array(
1191 + 'min_range' => 1,
1192 + ),
1193 + )
1194 + ) : '';
1195 + if ( $chart_id ) {
1196 + $data = $this->_getDataAs( $chart_id, 'csv' );
1197 + if ( $data ) {
1198 + echo wp_send_json_success( $data );
1199 + }
1526 1200 }
1527 1201 }
1528 1202
1529 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1203 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1530 1204 }
1531 1205
1532 1206 /**
1533 1207 * Handles chart data page.
@@ -1551,11 +1225,10 @@
1551 1225 'visualizer-render',
1552 1226 'visualizer',
1553 1227 array(
1554 1228 'l10n' => array(
1555 - 'invalid_source' => esc_html__( 'The URL you entered is invalid. Please enter a valid URL.', 'visualizer' ),
1556 - 'loading' => esc_html__( 'Loading...', 'visualizer' ),
1557 - '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' ),
1558 1231 ),
1559 1232 'charts' => array(
1560 1233 'canvas' => $data,
1561 1234 ),
@@ -1581,24 +1254,12 @@
1581 1254 */
1582 1255 public function getQueryData() {
1583 1256 check_ajax_referer( Visualizer_Plugin::ACTION_FETCH_DB_DATA . Visualizer_Plugin::VERSION, 'security' );
1584 1257
1585 - if ( ! current_user_can( 'administrator' ) ) {
1586 - wp_send_json_error( array( 'msg' => __( 'Action not allowed for this user.', 'visualizer' ) ) );
1587 - }
1588 - if ( ! is_super_admin() ) {
1589 - wp_send_json_error( array( 'msg' => __( 'Action not allowed for this user.', 'visualizer' ) ) );
1590 - }
1591 -
1592 - if ( ! Visualizer_Module::is_pro() ) {
1593 - wp_send_json_error( array( 'msg' => __( 'Feature is not available.', 'visualizer' ) ) );
1594 - }
1595 -
1596 1258 $params = wp_parse_args( $_POST['params'] );
1597 1259 $chart_id = filter_var( $params['chart_id'], FILTER_VALIDATE_INT );
1598 - $query = trim( $params['query'], ';' );
1599 1260
1600 - $source = new Visualizer_Source_Query( stripslashes( $query ), $chart_id, $params );
1261 + $source = new Visualizer_Source_Query( stripslashes( $params['query'] ), $chart_id, $params );
1601 1262 $html = $source->fetch( true );
1602 1263 $error = $source->get_error();
1603 1264 if ( ! empty( $error ) ) {
1604 1265 wp_send_json_error( array( 'msg' => $error ) );
@@ -1613,19 +1274,8 @@
1613 1274 */
1614 1275 public function saveQuery() {
1615 1276 check_ajax_referer( Visualizer_Plugin::ACTION_SAVE_DB_QUERY . Visualizer_Plugin::VERSION, 'security' );
1616 1277
1617 - if ( ! current_user_can( 'administrator' ) ) {
1618 - wp_send_json_error( array( 'msg' => __( 'Action not allowed for this user.', 'visualizer' ) ) );
1619 - }
1620 - if ( ! is_super_admin() ) {
1621 - wp_send_json_error( array( 'msg' => __( 'Action not allowed for this user.', 'visualizer' ) ) );
1622 - }
1623 -
1624 - if ( ! Visualizer_Module::is_pro() ) {
1625 - wp_send_json_error( array( 'msg' => __( 'Feature is not available.', 'visualizer' ) ) );
1626 - }
1627 -
1628 1278 $chart_id = filter_input(
1629 1279 INPUT_GET,
1630 1280 'chart',
1631 1281 FILTER_VALIDATE_INT,
@@ -1638,9 +1288,9 @@
1638 1288
1639 1289 $hours = filter_input(
1640 1290 INPUT_POST,
1641 1291 'refresh',
1642 - FILTER_VALIDATE_FLOAT,
1292 + FILTER_VALIDATE_INT,
1643 1293 array(
1644 1294 'options' => array(
1645 1295 'min_range' => -1,
1646 1296 'max_range' => apply_filters( 'visualizer_is_business', false ) ? PHP_INT_MAX : -1,
@@ -1647,9 +1297,9 @@
1647 1297 ),
1648 1298 )
1649 1299 );
1650 1300
1651 - if ( ! is_numeric( $hours ) ) {
1301 + if ( ! is_int( $hours ) ) {
1652 1302 $hours = -1;
1653 1303 }
1654 1304
1655 1305 $render = new Visualizer_Render_Page_Update();
@@ -1654,14 +1304,13 @@
1654 1304
1655 1305 $render = new Visualizer_Render_Page_Update();
1656 1306 if ( $chart_id ) {
1657 1307 $params = wp_parse_args( $_POST['params'] );
1658 - $query = trim( $params['query'], ';' );
1659 - $source = new Visualizer_Source_Query( stripslashes( $query ), $chart_id, $params );
1308 + $source = new Visualizer_Source_Query( stripslashes( $params['query'] ), $chart_id, $params );
1660 1309 $source->fetch( false );
1661 1310 $error = $source->get_error();
1662 1311 if ( empty( $error ) ) {
1663 - 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'] ) );
1664 1313 update_post_meta( $chart_id, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() );
1665 1314 update_post_meta( $chart_id, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
1666 1315 update_post_meta( $chart_id, Visualizer_Plugin::CF_DB_SCHEDULE, $hours );
1667 1316 update_post_meta( $chart_id, Visualizer_Plugin::CF_DEFAULT_DATA, 0 );
@@ -1678,12 +1327,12 @@
1678 1327
1679 1328 wp_update_post(
1680 1329 array(
1681 1330 'ID' => $chart_id,
1682 - 'post_content' => $source->getData( get_post_meta( $chart_id, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) ),
1331 + 'post_content' => $source->getData(),
1683 1332 )
1684 1333 );
1685 - $render->data = json_encode( $source->getRawData( get_post_meta( $chart_id, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) ) );
1334 + $render->data = json_encode( $source->getRawData() );
1686 1335 $render->series = json_encode( $source->getSeries() );
1687 1336 $render->id = $chart_id;
1688 1337 } else {
1689 1338 $render->message = $error;
@@ -1690,9 +1339,9 @@
1690 1339 }
1691 1340 }
1692 1341 $render->render();
1693 1342 if ( ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE ) ) {
1694 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1343 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1695 1344 }
1696 1345 }
1697 1346
1698 1347
@@ -1703,10 +1352,11 @@
1703 1352 */
1704 1353 public function saveFilter() {
1705 1354 check_ajax_referer( Visualizer_Plugin::ACTION_SAVE_FILTER_QUERY . Visualizer_Plugin::VERSION, 'security' );
1706 1355
1707 - $chart_id = isset( $_GET['chart'] ) ? filter_var(
1708 - $_GET['chart'],
1356 + $chart_id = filter_input(
1357 + INPUT_GET,
1358 + 'chart',
1709 1359 FILTER_VALIDATE_INT,
1710 1360 array(
1711 1361 'options' => array(
1712 1362 'min_range' => 1,
@@ -1711,18 +1361,14 @@
1711 1361 'options' => array(
1712 1362 'min_range' => 1,
1713 1363 ),
1714 1364 )
1715 - ) : false;
1365 + );
1716 1366
1717 - if ( ! self::can_edit_chart( $chart_id ) ) {
1718 - wp_send_json_error( array( 'msg' => esc_html__( 'You do not have permission to perform this action.', 'visualizer' ) ), 403 );
1719 - }
1720 -
1721 1367 $hours = filter_input(
1722 1368 INPUT_POST,
1723 1369 'refresh',
1724 - FILTER_VALIDATE_FLOAT,
1370 + FILTER_VALIDATE_INT,
1725 1371 array(
1726 1372 'options' => array(
1727 1373 'min_range' => -1,
1728 1374 'max_range' => apply_filters( 'visualizer_is_business', false ) ? PHP_INT_MAX : -1,
@@ -1729,9 +1375,9 @@
1729 1375 ),
1730 1376 )
1731 1377 );
1732 1378
1733 - if ( ! is_numeric( $hours ) ) {
1379 + if ( ! $hours ) {
1734 1380 $hours = -1;
1735 1381 }
1736 1382
1737 1383 do_action( 'visualizer_save_filter', $chart_id, $hours );
@@ -1736,65 +1382,8 @@
1736 1382
1737 1383 do_action( 'visualizer_save_filter', $chart_id, $hours );
1738 1384
1739 1385 if ( ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE ) ) {
1740 - ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) ? wp_die() : exit();
1386 + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1741 1387 }
1742 - }
1743 -
1744 - /**
1745 - * Save chart image.
1746 - *
1747 - * @param string $base64_img Chart image.
1748 - * @param int $chart_id Chart ID.
1749 - * @param bool $save_attachment Save attachment.
1750 - * @return int Attachment ID, or 0 when no attachment was saved.
1751 - */
1752 - public function save_chart_image( $base64_img, $chart_id, $save_attachment = true ) {
1753 - // Delete old chart image.
1754 - $old_attachment_id = get_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_IMAGE, true );
1755 - if ( $old_attachment_id ) {
1756 - wp_delete_attachment( $old_attachment_id, true );
1757 - }
1758 -
1759 - if ( ! $save_attachment ) {
1760 - return 0;
1761 - }
1762 -
1763 - // Upload dir.
1764 - $upload_dir = wp_upload_dir();
1765 - $upload_path = str_replace( '/', DIRECTORY_SEPARATOR, $upload_dir['path'] ) . DIRECTORY_SEPARATOR;
1766 -
1767 - $img = str_replace( 'data:image/png;base64,', '', (string) $base64_img );
1768 - $img = str_replace( ' ', '+', $img );
1769 - $decoded = base64_decode( $img, true );
1770 - // The value comes from an untrusted request; only write real PNG bytes to uploads.
1771 - if ( false === $decoded || 0 !== strncmp( $decoded, "\x89PNG\r\n\x1a\n", 8 ) ) {
1772 - return 0;
1773 - }
1774 - $filename = 'visualization-' . $chart_id . '.png';
1775 - $file_type = 'image/png';
1776 - $hashed_filename = $filename;
1777 -
1778 - // Save the image in the uploads directory.
1779 - require_once ABSPATH . '/wp-admin/includes/file.php';
1780 - \WP_Filesystem();
1781 - global $wp_filesystem;
1782 - if ( ! is_a( $wp_filesystem, 'WP_Filesystem_Base' ) ) {
1783 - $creds = request_filesystem_credentials( site_url() );
1784 - wp_filesystem( $creds );
1785 - }
1786 - $upload_file = $wp_filesystem->put_contents( $upload_path . $hashed_filename, $decoded );
1787 -
1788 - // Insert new chart image.
1789 - $attachment = array(
1790 - 'post_mime_type' => $file_type,
1791 - 'post_title' => preg_replace( '/\.[^.]+$/', '', basename( $hashed_filename ) ),
1792 - 'post_content' => '',
1793 - 'post_status' => 'inherit',
1794 - 'guid' => $upload_dir['url'] . '/' . basename( $hashed_filename ),
1795 - );
1796 -
1797 - $attach_id = wp_insert_attachment( $attachment, $upload_dir['path'] . '/' . $hashed_filename );
1798 - return $attach_id;
1799 1388 }
1800 1389 }