PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.4.5
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.4.5
4.0.7 4.0.6 4.0.5 4.0.4 4.0.3 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.1 3.1.2 3.1.3 3.10.0 3.10.1 3.10.10 3.10.11 3.10.12 3.10.13 3.10.14 3.10.15 3.10.2 3.10.3 3.10.4 All 148 releases
visualizer / classes / Visualizer / Gutenberg / Block.php

Block.php in Visualizer – Tables & Charts Manager with Built-in AI Generator 3.4.5, at classes/Visualizer/Gutenberg/Block.php

803 lines 24.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 // +----------------------------------------------------------------------+
3 // | Copyright 2018 ThemeIsle (email : friends@themeisle.com) |
4 // +----------------------------------------------------------------------+
5 // | This program is free software; you can redistribute it and/or modify |
6 // | it under the terms of the GNU General Public License, version 2, as |
7 // | published by the Free Software Foundation. |
8 // | |
9 // | This program is distributed in the hope that it will be useful, |
10 // | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 // | GNU General Public License for more details. |
13 // | |
14 // | You should have received a copy of the GNU General Public License |
15 // | along with this program; if not, write to the Free Software |
16 // | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, |
17 // | MA 02110-1301 USA |
18 // +----------------------------------------------------------------------+
19 // | Author: Hardeep Asrani <hardeep@themeisle.com> |
20 // +----------------------------------------------------------------------+
21 /**
22 * All the Gutenberg block related code.
23 *
24 * @category Visualizer
25 * @package Gutenberg
26 *
27 * @since 3.1.0
28 */
29 class Visualizer_Gutenberg_Block {
30
31 /**
32 * A reference to an instance of this class.
33 *
34 * @var Visualizer_Gutenberg_Block The one Visualizer_Gutenberg_Block instance.
35 */
36 private static $instance;
37
38 /**
39 * Visualizer plugin version.
40 *
41 * @var string $version The current version of the plugin.
42 */
43 protected $version;
44
45 /**
46 * Returns an instance of this class.
47 */
48 public static function get_instance() {
49 if ( null === self::$instance ) {
50 self::$instance = new Visualizer_Gutenberg_Block();
51 }
52 return self::$instance;
53 }
54
55 /**
56 * Initializes the plugin by setting filters and administration functions.
57 */
58 private function __construct() {
59 $this->version = Visualizer_Plugin::VERSION;
60 add_action( 'enqueue_block_editor_assets', array( $this, 'enqueue_gutenberg_scripts' ) );
61 add_action( 'init', array( $this, 'register_block_type' ) );
62 add_action( 'rest_api_init', array( $this, 'register_rest_endpoints' ) );
63 add_filter( 'rest_visualizer_query', array( $this, 'add_rest_query_vars' ), 9, 2 );
64 }
65
66 /**
67 * Enqueue front end and editor JavaScript and CSS
68 */
69 public function enqueue_gutenberg_scripts() {
70 global $wp_version;
71
72 $blockPath = VISUALIZER_ABSURL . 'classes/Visualizer/Gutenberg/build/block.js';
73 $handsontableJS = VISUALIZER_ABSURL . 'classes/Visualizer/Gutenberg/build/handsontable.js';
74 $stylePath = VISUALIZER_ABSURL . 'classes/Visualizer/Gutenberg/build/block.css';
75 $handsontableCSS = VISUALIZER_ABSURL . 'classes/Visualizer/Gutenberg/build/handsontable.css';
76
77 if ( VISUALIZER_TEST_JS_CUSTOMIZATION ) {
78 $version = filemtime( VISUALIZER_ABSPATH . '/classes/Visualizer/Gutenberg/build/block.js' );
79 } else {
80 $version = $this->version;
81 }
82
83 // Enqueue the bundled block JS file
84 wp_enqueue_script( 'handsontable', $handsontableJS );
85 wp_enqueue_script( 'visualizer-gutenberg-block', $blockPath, array( 'wp-api', 'handsontable', 'visualizer-datatables', 'moment' ), $version, true );
86
87 $type = 'community';
88
89 if ( Visualizer_Module::is_pro() ) {
90 $type = 'pro';
91 if ( apply_filters( 'visualizer_is_business', false ) ) {
92 $type = 'business';
93 }
94 }
95
96 $table_col_mapping = Visualizer_Source_Query_Params::get_all_db_tables_column_mapping( null, false );
97
98 $translation_array = array(
99 'isPro' => $type,
100 'proTeaser' => Visualizer_Plugin::PRO_TEASER_URL,
101 'absurl' => VISUALIZER_ABSURL,
102 'charts' => Visualizer_Module_Admin::_getChartTypesLocalized(),
103 'adminPage' => menu_page_url( 'visualizer', false ),
104 'sqlTable' => $table_col_mapping,
105 'chartsPerPage' => defined( 'TI_CYPRESS_TESTING' ) ? 20 : 6,
106 );
107 wp_localize_script( 'visualizer-gutenberg-block', 'visualizerLocalize', $translation_array );
108
109 // Enqueue frontend and editor block styles
110 wp_enqueue_style( 'handsontable', $handsontableCSS );
111 wp_enqueue_style( 'visualizer-gutenberg-block', $stylePath, array( 'visualizer-datatables' ), $version );
112
113 if ( version_compare( $wp_version, '4.9.0', '>' ) ) {
114
115 wp_enqueue_code_editor(
116 array(
117 'type' => 'sql',
118 'codemirror' => array(
119 'autofocus' => true,
120 'lineWrapping' => true,
121 'dragDrop' => false,
122 'matchBrackets' => true,
123 'autoCloseBrackets' => true,
124 'extraKeys' => array( 'Ctrl-Space' => 'autocomplete' ),
125 'hintOptions' => array( 'tables' => $table_col_mapping ),
126 ),
127 )
128 );
129 }
130 }
131 /**
132 * Hook server side rendering into render callback
133 */
134 public function register_block_type() {
135 register_block_type(
136 'visualizer/chart', array(
137 'render_callback' => array( $this, 'gutenberg_block_callback' ),
138 'attributes' => array(
139 'id' => array(
140 'type' => 'number',
141 ),
142 'lazy' => array(
143 'type' => 'string',
144 ),
145 ),
146 )
147 );
148 }
149
150 /**
151 * Gutenberg Block Callback Function
152 */
153 public function gutenberg_block_callback( $atts ) {
154 // no id, no fun.
155 if ( ! isset( $atts['id'] ) ) {
156 return '';
157 }
158
159 $atts = shortcode_atts(
160 array(
161 'id' => false,
162 'lazy' => apply_filters( 'visualizer_lazy_by_default', false, $atts['id'] ),
163 // we are deliberating excluding the class attribute from here
164 // as this will be handled by the custom class in Gutenberg
165 ),
166 $atts
167 );
168
169 // no id, no fun.
170 if ( ! $atts['id'] ) {
171 return '';
172 }
173
174 // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
175 if ( $atts['lazy'] == -1 || $atts['lazy'] == false ) {
176 $atts['lazy'] = 'no';
177 }
178
179 // we don't want the chart in the editor lazy-loading.
180 if ( is_admin() ) {
181 unset( $atts['lazy'] );
182 }
183
184 $shortcode = '[visualizer';
185 foreach ( $atts as $name => $value ) {
186 $shortcode .= sprintf( ' %s="%s"', $name, $value );
187 }
188 $shortcode .= ']';
189
190 return $shortcode;
191 }
192
193 /**
194 * Hook server side rendering into render callback
195 */
196 public function register_rest_endpoints() {
197 register_rest_field(
198 'visualizer',
199 'chart_data',
200 array(
201 'get_callback' => array( $this, 'get_visualizer_data' ),
202 )
203 );
204
205 register_rest_route(
206 'visualizer/v' . VISUALIZER_REST_VERSION,
207 '/get-query-data',
208 array(
209 'methods' => 'GET',
210 'callback' => array( $this, 'get_query_data' ),
211 'permission_callback' => function () {
212 return current_user_can( 'edit_posts' );
213 },
214 )
215 );
216
217 register_rest_route(
218 'visualizer/v' . VISUALIZER_REST_VERSION,
219 '/get-json-root',
220 array(
221 'methods' => 'GET',
222 'callback' => array( $this, 'get_json_root_data' ),
223 'args' => array(
224 'url' => array(
225 'sanitize_callback' => 'esc_url_raw',
226 ),
227 ),
228 'permission_callback' => function () {
229 return current_user_can( 'edit_posts' );
230 },
231 )
232 );
233
234 register_rest_route(
235 'visualizer/v' . VISUALIZER_REST_VERSION,
236 '/get-json-data',
237 array(
238 'methods' => 'GET',
239 'callback' => array( $this, 'get_json_data' ),
240 'args' => array(
241 'url' => array(
242 'sanitize_callback' => 'esc_url_raw',
243 ),
244 'chart' => array(
245 'sanitize_callback' => 'absint',
246 ),
247 ),
248 'permission_callback' => function () {
249 return current_user_can( 'edit_posts' );
250 },
251 )
252 );
253
254 register_rest_route(
255 'visualizer/v' . VISUALIZER_REST_VERSION,
256 '/set-json-data',
257 array(
258 'methods' => 'GET',
259 'callback' => array( $this, 'set_json_data' ),
260 'args' => array(
261 'url' => array(
262 'sanitize_callback' => 'esc_url_raw',
263 ),
264 ),
265 'permission_callback' => function () {
266 return current_user_can( 'edit_posts' );
267 },
268 )
269 );
270
271 register_rest_route(
272 'visualizer/v' . VISUALIZER_REST_VERSION,
273 '/update-chart',
274 array(
275 'methods' => 'POST',
276 'callback' => array( $this, 'update_chart_data' ),
277 'args' => array(
278 'id' => array(
279 'sanitize_callback' => 'absint',
280 ),
281 ),
282 'permission_callback' => function () {
283 return current_user_can( 'edit_posts' );
284 },
285 )
286 );
287
288 register_rest_route(
289 'visualizer/v' . VISUALIZER_REST_VERSION,
290 '/upload-data',
291 array(
292 'methods' => 'POST',
293 'callback' => array( $this, 'upload_csv_data' ),
294 'args' => array(
295 'url' => array(
296 'sanitize_callback' => 'esc_url_raw',
297 ),
298 ),
299 'permission_callback' => function () {
300 return current_user_can( 'edit_posts' );
301 },
302 )
303 );
304
305 register_rest_route(
306 'visualizer/v' . VISUALIZER_REST_VERSION,
307 '/get-permission-data',
308 array(
309 'methods' => 'GET',
310 'callback' => array( $this, 'get_permission_data' ),
311 'args' => array(
312 'type' => array(
313 'sanitize_callback' => 'sanitize_text_field',
314 ),
315 ),
316 'permission_callback' => function () {
317 return current_user_can( 'edit_posts' );
318 },
319 )
320 );
321 }
322
323 /**
324 * Get Post Meta Fields
325 */
326 public function get_visualizer_data( $post ) {
327 if ( ! current_user_can( 'edit_posts' ) ) {
328 return false;
329 }
330
331 $data = array();
332 $post_id = $post['id'];
333
334 $data['visualizer-chart-type'] = get_post_meta( $post_id, Visualizer_Plugin::CF_CHART_TYPE, true );
335
336 $library = get_post_meta( $post_id, Visualizer_Plugin::CF_CHART_LIBRARY, true );
337 $data['visualizer-chart-library'] = $library;
338
339 $data['visualizer-source'] = get_post_meta( $post_id, Visualizer_Plugin::CF_SOURCE, true );
340
341 $data['visualizer-default-data'] = get_post_meta( $post_id, Visualizer_Plugin::CF_DEFAULT_DATA, true );
342
343 // faetch and update settings
344 $data['visualizer-settings'] = get_post_meta( $post_id, Visualizer_Plugin::CF_SETTINGS, true );
345
346 // handle series filter hooks
347 $data['visualizer-series'] = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_SERIES, get_post_meta( $post_id, Visualizer_Plugin::CF_SERIES, true ), $post_id, $data['visualizer-chart-type'] );
348
349 // handle settings filter hooks
350 $data['visualizer-settings'] = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_SETTINGS, $data['visualizer-settings'], $post_id, $data['visualizer-chart-type'] );
351
352 // handle data filter hooks
353 $data['visualizer-data'] = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_DATA, unserialize( html_entity_decode( get_the_content( $post_id ) ) ), $post_id, $data['visualizer-chart-type'] );
354
355 $data['visualizer-data-exploded'] = '';
356 // handle annotations for google charts
357 if ( 'GoogleCharts' === $library ) {
358 // this will contain the data of both axis.
359 $settings = $data['visualizer-settings'];
360 // this will contain data only of Y axis.
361 $series = $data['visualizer-series'];
362 $annotations = array();
363 if ( isset( $settings['series'] ) ) {
364 foreach ( $settings['series'] as $index => $serie ) {
365 // skip X axis data.
366 if ( $index === 0 ) {
367 continue;
368 }
369 if ( ! empty( $serie['role'] ) ) {
370 // this series is some kind of annotation, so let's collect its index.
371 // the index will be +1 because the X axis value is index 0, which is being ignored.
372 $annotations[ 'role' . ( intval( $index ) + 1 ) ] = $serie['role'];
373 }
374 }
375 }
376 if ( ! empty( $annotations ) ) {
377 $exploded_data = array();
378 $series_names = array();
379 foreach ( $series as $index => $serie ) {
380 // skip X axis data.
381 if ( $index === 0 ) {
382 continue;
383 }
384 if ( array_key_exists( 'role' . $index, $annotations ) ) {
385 $series_names[] = (object) array( 'role' => $annotations[ 'role' . $index ], 'type' => $serie['type'] );
386 } else {
387 $series_names[] = $serie['label'];
388 }
389 }
390 $exploded_data[] = $series_names;
391
392 foreach ( $data['visualizer-data'] as $datum ) {
393 // skip X axis data.
394 unset( $datum[0] );
395 $exploded_data[] = $datum;
396 }
397 $data['visualizer-data-exploded'] = array( $exploded_data );
398 }
399 }
400
401 $import = get_post_meta( $post_id, Visualizer_Plugin::CF_CHART_URL, true );
402
403 $schedule = get_post_meta( $post_id, Visualizer_Plugin::CF_CHART_SCHEDULE, true );
404
405 $db_schedule = get_post_meta( $post_id, Visualizer_Plugin::CF_DB_SCHEDULE, true );
406
407 $db_query = get_post_meta( $post_id, Visualizer_Plugin::CF_DB_QUERY, true );
408
409 $json_url = get_post_meta( $post_id, Visualizer_Plugin::CF_JSON_URL, true );
410
411 $json_headers = get_post_meta( $post_id, Visualizer_Plugin::CF_JSON_HEADERS, true );
412
413 $json_schedule = get_post_meta( $post_id, Visualizer_Plugin::CF_JSON_SCHEDULE, true );
414
415 $json_root = get_post_meta( $post_id, Visualizer_Plugin::CF_JSON_ROOT, true );
416
417 $json_paging = get_post_meta( $post_id, Visualizer_Plugin::CF_JSON_PAGING, true );
418
419 if ( ! empty( $import ) && ! empty( $schedule ) ) {
420 $data['visualizer-chart-url'] = $import;
421 $data['visualizer-chart-schedule'] = $schedule;
422 }
423
424 if ( ! empty( $db_schedule ) && ! empty( $db_query ) ) {
425 $data['visualizer-db-schedule'] = $db_schedule;
426 $data['visualizer-db-query'] = $db_query;
427 }
428
429 if ( ! empty( $json_url ) ) {
430 $data['visualizer-json-schedule'] = $json_schedule;
431 $data['visualizer-json-url'] = $json_url;
432 $data['visualizer-json-headers'] = $json_headers;
433 $data['visualizer-json-root'] = $json_root;
434
435 if ( Visualizer_Module::is_pro() && ! empty( $json_paging ) ) {
436 $data['visualizer-json-paging'] = $json_paging;
437 }
438 }
439
440 if ( Visualizer_Module::is_pro() ) {
441 $permissions = get_post_meta( $post_id, Visualizer_PRO::CF_PERMISSIONS, true );
442
443 if ( ! empty( $permissions ) ) {
444 $data['visualizer-permissions'] = $permissions;
445 }
446 }
447
448 return $data;
449 }
450
451 /**
452 * Returns the data for the query.
453 *
454 * @access public
455 */
456 public function get_query_data( $data ) {
457 if ( ! current_user_can( 'edit_posts' ) ) {
458 return false;
459 }
460
461 $source = new Visualizer_Source_Query( stripslashes( $data['query'] ) );
462 $html = $source->fetch( true );
463 $source->fetch( false );
464 $name = $source->getSourceName();
465 $series = $source->getSeries();
466 $data = $source->getRawData();
467 $error = '';
468 if ( empty( $html ) ) {
469 $error = $source->get_error();
470 wp_send_json_error( array( 'msg' => $error ) );
471 }
472 wp_send_json_success( array( 'table' => $html, 'name' => $name, 'series' => $series, 'data' => $data ) );
473 }
474
475 /**
476 * Returns the JSON root.
477 *
478 * @access public
479 */
480 public function get_json_root_data( $data ) {
481 if ( ! current_user_can( 'edit_posts' ) ) {
482 return false;
483 }
484
485 $source = new Visualizer_Source_Json( $data );
486
487 $roots = $source->fetchRoots();
488 if ( empty( $roots ) ) {
489 wp_send_json_error( array( 'msg' => $source->get_error() ) );
490 }
491
492 wp_send_json_success( array( 'url' => $data['url'], 'roots' => $roots ) );
493 }
494
495 /**
496 * Returns the JSON data.
497 *
498 * @access public
499 */
500 public function get_json_data( $data ) {
501 if ( ! current_user_can( 'edit_posts' ) ) {
502 return false;
503 }
504
505 $chart_id = $data['chart'];
506
507 if ( empty( $chart_id ) ) {
508 wp_die();
509 }
510
511 $source = new Visualizer_Source_Json( $data );
512 $source->fetch();
513 $table = $source->getRawData();
514
515 if ( empty( $table ) ) {
516 wp_send_json_error( array( 'msg' => esc_html__( 'Unable to fetch data from the endpoint. Please try again.', 'visualizer' ) ) );
517 }
518
519 $table = Visualizer_Render_Layout::show( 'editor-table', $table, $chart_id, 'viz-json-table', false, false );
520 wp_send_json_success( array( 'table' => $table, 'root' => $data['root'], 'url' => $data['url'], 'paging' => $source->getPaginationElements() ) );
521 }
522
523 /**
524 * Set the JSON data.
525 *
526 * @access public
527 */
528 public function set_json_data( $data ) {
529 if ( ! current_user_can( 'edit_posts' ) ) {
530 return false;
531 }
532
533 $source = new Visualizer_Source_Json( $data );
534
535 $table = $source->fetch();
536 if ( empty( $table ) ) {
537 wp_send_json_error( array( 'msg' => esc_html__( 'Unable to fetch data from the endpoint. Please try again.', 'visualizer' ) ) );
538 }
539
540 $source->fetchFromEditableTable();
541 $name = $source->getSourceName();
542 $series = json_encode( $source->getSeries() );
543 $data = json_encode( $source->getRawData() );
544 wp_send_json_success( array( 'name' => $name, 'series' => $series, 'data' => $data ) );
545 }
546
547 /**
548 * Rest Callback Method
549 */
550 public function update_chart_data( $data ) {
551 if ( ! current_user_can( 'edit_posts' ) ) {
552 return false;
553 }
554
555 if ( $data['id'] && ! is_wp_error( $data['id'] ) ) {
556 if ( get_post_type( $data['id'] ) !== Visualizer_Plugin::CPT_VISUALIZER ) {
557 return new WP_Error( 'invalid_post_type', 'Invalid post type.' );
558 }
559 $chart_type = sanitize_text_field( $data['visualizer-chart-type'] );
560 $source_type = sanitize_text_field( $data['visualizer-source'] );
561
562 update_post_meta( $data['id'], Visualizer_Plugin::CF_CHART_TYPE, $chart_type );
563 update_post_meta( $data['id'], Visualizer_Plugin::CF_SOURCE, $source_type );
564 update_post_meta( $data['id'], Visualizer_Plugin::CF_DEFAULT_DATA, $data['visualizer-default-data'] );
565 update_post_meta( $data['id'], Visualizer_Plugin::CF_SERIES, $data['visualizer-series'] );
566 update_post_meta( $data['id'], Visualizer_Plugin::CF_SETTINGS, $data['visualizer-settings'] );
567
568 if ( $data['visualizer-chart-url'] && $data['visualizer-chart-schedule'] ) {
569 $chart_url = esc_url_raw( $data['visualizer-chart-url'] );
570 $chart_schedule = intval( $data['visualizer-chart-schedule'] );
571 update_post_meta( $data['id'], Visualizer_Plugin::CF_CHART_URL, $chart_url );
572 apply_filters( 'visualizer_pro_chart_schedule', $data['id'], $chart_url, $chart_schedule );
573 } else {
574 delete_post_meta( $data['id'], Visualizer_Plugin::CF_CHART_URL );
575 apply_filters( 'visualizer_pro_remove_schedule', $data['id'] );
576 }
577
578 if ( $source_type === 'Visualizer_Source_Query' ) {
579 $db_schedule = intval( $data['visualizer-db-schedule'] );
580 $db_query = $data['visualizer-db-query'];
581 update_post_meta( $data['id'], Visualizer_Plugin::CF_DB_SCHEDULE, $db_schedule );
582 update_post_meta( $data['id'], Visualizer_Plugin::CF_DB_QUERY, stripslashes( $db_query ) );
583 } else {
584 delete_post_meta( $data['id'], Visualizer_Plugin::CF_DB_SCHEDULE );
585 delete_post_meta( $data['id'], Visualizer_Plugin::CF_DB_QUERY );
586 }
587
588 if ( $source_type === 'Visualizer_Source_Json' ) {
589 $json_schedule = intval( $data['visualizer-json-schedule'] );
590 $json_url = esc_url_raw( $data['visualizer-json-url'] );
591 $json_headers = esc_url_raw( $data['visualizer-json-headers'] );
592 $json_root = $data['visualizer-json-root'];
593 $json_paging = $data['visualizer-json-paging'];
594
595 update_post_meta( $data['id'], Visualizer_Plugin::CF_JSON_SCHEDULE, $json_schedule );
596 update_post_meta( $data['id'], Visualizer_Plugin::CF_JSON_URL, $json_url );
597 update_post_meta( $data['id'], Visualizer_Plugin::CF_JSON_HEADERS, $json_headers );
598 update_post_meta( $data['id'], Visualizer_Plugin::CF_JSON_ROOT, $json_root );
599
600 if ( ! empty( $json_paging ) ) {
601 update_post_meta( $data['id'], Visualizer_Plugin::CF_JSON_PAGING, $json_paging );
602 } else {
603 delete_post_meta( $data['id'], Visualizer_Plugin::CF_JSON_PAGING );
604 }
605 } else {
606 delete_post_meta( $data['id'], Visualizer_Plugin::CF_JSON_SCHEDULE );
607 delete_post_meta( $data['id'], Visualizer_Plugin::CF_JSON_URL );
608 delete_post_meta( $data['id'], Visualizer_Plugin::CF_JSON_HEADERS );
609 delete_post_meta( $data['id'], Visualizer_Plugin::CF_JSON_ROOT );
610 delete_post_meta( $data['id'], Visualizer_Plugin::CF_JSON_PAGING );
611 }
612
613 if ( Visualizer_Module::is_pro() ) {
614 update_post_meta( $data['id'], Visualizer_PRO::CF_PERMISSIONS, $data['visualizer-permissions'] );
615 }
616
617 if ( $data['visualizer-chart-url'] ) {
618 $chart_url = esc_url_raw( $data['visualizer-chart-url'] );
619 $content['source'] = $chart_url;
620 $content['data'] = $this->format_chart_data( $data['visualizer-data'], $data['visualizer-series'] );
621 } else {
622 $content = $this->format_chart_data( $data['visualizer-data'], $data['visualizer-series'] );
623 }
624
625 $chart = array(
626 'ID' => $data['id'],
627 'post_content' => serialize( $content ),
628 );
629
630 wp_update_post( $chart );
631
632 $revisions = wp_get_post_revisions( $data['id'], array( 'order' => 'ASC' ) );
633
634 if ( count( $revisions ) > 1 ) {
635 $revision_ids = array_keys( $revisions );
636
637 // delete all revisions.
638 foreach ( $revision_ids as $id ) {
639 wp_delete_post_revision( $id );
640 }
641 }
642
643 return new \WP_REST_Response( array( 'success' => sprintf( 'Chart updated' ) ) );
644 }
645 }
646
647 /**
648 * Format chart data.
649 */
650 public function format_chart_data( $data, $series ) {
651 foreach ( $series as $i => $row ) {
652 // if no value exists for the seires, then add null
653 if ( ! isset( $series[ $i ] ) ) {
654 $series[ $i ] = null;
655 }
656
657 if ( is_null( $series[ $i ] ) ) {
658 continue;
659 }
660
661 if ( $row['type'] === 'number' ) {
662 foreach ( $data as $o => $col ) {
663 $data[ $o ][ $i ] = ( is_numeric( $col[ $i ] ) ) ? floatval( $col[ $i ] ) : ( is_numeric( str_replace( ',', '', $col[ $i ] ) ) ? floatval( str_replace( ',', '', $col[ $i ] ) ) : null );
664 }
665 }
666
667 if ( $row['type'] === 'boolean' ) {
668 foreach ( $data as $o => $col ) {
669 $data[ $o ][ $i ] = ! empty( $col[ $i ] ) ? filter_var( $col[ $i ], FILTER_VALIDATE_BOOLEAN ) : null;
670 }
671 }
672
673 if ( $row['type'] === 'timeofday' ) {
674 foreach ( $data as $o => $col ) {
675 $date = new DateTime( '1984-03-16T' . $col[ $i ] );
676 if ( $date ) {
677 $data[ $o ][ $i ] = array(
678 intval( $date->format( 'H' ) ),
679 intval( $date->format( 'i' ) ),
680 intval( $date->format( 's' ) ),
681 0,
682 );
683 }
684 }
685 }
686
687 if ( $row['type'] === 'string' ) {
688 foreach ( $data as $o => $col ) {
689 $data[ $o ][ $i ] = $this->toUTF8( $col[ $i ] );
690 }
691 }
692 }
693
694 return $data;
695 }
696
697 /**
698 * Use toUTF8 function
699 */
700 public function toUTF8( $datum ) {
701 if ( ! function_exists( 'mb_detect_encoding' ) || mb_detect_encoding( $datum ) !== 'ASCII' ) {
702 $datum = \ForceUTF8\Encoding::toUTF8( $datum );
703 }
704 return $datum;
705 }
706
707 /**
708 * Handle remote CSV data
709 */
710 public function upload_csv_data( $data ) {
711 if ( ! current_user_can( 'edit_posts' ) ) {
712 return false;
713 }
714
715 if ( $data['url'] && ! is_wp_error( $data['url'] ) && filter_var( $data['url'], FILTER_VALIDATE_URL ) ) {
716 $source = new Visualizer_Source_Csv_Remote( $data['url'] );
717 if ( $source->fetch() ) {
718 $temp = $source->getData();
719 if ( is_string( $temp ) && is_array( unserialize( $temp ) ) ) {
720 $content['series'] = $source->getSeries();
721 $content['data'] = $source->getRawData();
722 return $content;
723 } else {
724 return new \WP_REST_Response( array( 'failed' => sprintf( 'Invalid CSV URL' ) ) );
725 }
726 } else {
727 return new \WP_REST_Response( array( 'failed' => sprintf( 'Invalid CSV URL' ) ) );
728 }
729 } else {
730 return new \WP_REST_Response( array( 'failed' => sprintf( 'Invalid CSV URL' ) ) );
731 }
732 }
733
734 /**
735 * Get permission data
736 */
737 public function get_permission_data( $data ) {
738 if ( ! current_user_can( 'edit_posts' ) ) {
739 return false;
740 }
741
742 $options = array();
743 switch ( $data['type'] ) {
744 case 'users':
745 $query = new WP_User_Query(
746 array(
747 'number' => 1000,
748 'orderby' => 'display_name',
749 'fields' => array( 'ID', 'display_name' ),
750 'count_total' => false,
751 )
752 );
753 $users = $query->get_results();
754 if ( ! empty( $users ) ) {
755 $i = 0;
756 foreach ( $users as $user ) {
757 $options[ $i ]['value'] = $user->ID;
758 $options[ $i ]['label'] = $user->display_name;
759 $i++;
760 }
761 }
762 break;
763 case 'roles':
764 if ( ! function_exists( 'get_editable_roles' ) ) {
765 require_once ABSPATH . 'wp-admin/includes/user.php';
766 }
767 $roles = get_editable_roles();
768 if ( ! empty( $roles ) ) {
769 $i = 0;
770 foreach ( get_editable_roles() as $name => $info ) {
771 $options[ $i ]['value'] = $name;
772 $options[ $i ]['label'] = $name;
773 $i++;
774 }
775 }
776 break;
777 }
778 return $options;
779 }
780
781 /**
782 * Filter Rest Query
783 */
784 public function add_rest_query_vars( $args, \WP_REST_Request $request ) {
785 if ( isset( $request['meta_key'] ) && isset( $request['meta_value'] ) ) {
786 $args['meta_query'] = array(
787 'relation' => 'OR',
788 array(
789 'key' => $request->get_param( 'meta_key' ),
790 'value' => $request->get_param( 'meta_value' ),
791 'compare' => '!=',
792 ),
793 array(
794 'key' => $request->get_param( 'meta_key' ),
795 'value' => $request->get_param( 'meta_value' ),
796 'compare' => 'NOT EXISTS',
797 ),
798 );
799 }
800 return $args;
801 }
802 }
803