PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 1.1.2
Visualizer – Tables & Charts Manager with Built-in AI Generator v1.1.2
4.0.7 4.0.6 4.0.5 4.0.4 4.0.3 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.1 3.1.2 3.1.3 3.10.0 3.10.1 3.10.10 3.10.11 3.10.12 3.10.13 3.10.14 3.10.15 3.10.2 3.10.3 3.10.4 All 148 releases
← All changes | classes/Visualizer/Module/Chart.php +218 -1344 3.10.151.1.2 View file →
@@ -1,5 +1,6 @@
1 1 <?php
2 +
2 3 // +----------------------------------------------------------------------+
3 4 // | Copyright 2013 Madpixels (email : visualizer@madpixels.net) |
4 5 // +----------------------------------------------------------------------+
5 6 // | This program is free software; you can redistribute it and/or modify |
@@ -17,8 +18,9 @@
17 18 // | MA 02110-1301 USA |
18 19 // +----------------------------------------------------------------------+
19 20 // | Author: Eugene Manuilov <eugene@manuilov.org> |
20 21 // +----------------------------------------------------------------------+
22 +
21 23 /**
22 24 * The module for all stuff related to getting, editing, creating and deleting charts.
23 25 *
24 26 * @category Visualizer
@@ -45,13 +47,13 @@
45 47 *
46 48 * @since 1.0.0
47 49 *
48 50 * @access public
49 - *
50 51 * @param Visualizer_Plugin $plugin The instance of the plugin.
51 52 */
52 53 public function __construct( Visualizer_Plugin $plugin ) {
53 54 parent::__construct( $plugin );
55 +
54 56 $this->_addAjaxAction( Visualizer_Plugin::ACTION_GET_CHARTS, 'getCharts' );
55 57 $this->_addAjaxAction( Visualizer_Plugin::ACTION_DELETE_CHART, 'deleteChart' );
56 58 $this->_addAjaxAction( Visualizer_Plugin::ACTION_CREATE_CHART, 'renderChartPages' );
57 59 $this->_addAjaxAction( Visualizer_Plugin::ACTION_EDIT_CHART, 'renderChartPages' );
@@ -56,257 +58,55 @@
56 58 $this->_addAjaxAction( Visualizer_Plugin::ACTION_CREATE_CHART, 'renderChartPages' );
57 59 $this->_addAjaxAction( Visualizer_Plugin::ACTION_EDIT_CHART, 'renderChartPages' );
58 60 $this->_addAjaxAction( Visualizer_Plugin::ACTION_UPLOAD_DATA, 'uploadData' );
59 61 $this->_addAjaxAction( Visualizer_Plugin::ACTION_CLONE_CHART, 'cloneChart' );
60 - $this->_addAjaxAction( Visualizer_Plugin::ACTION_EXPORT_DATA, 'exportData' );
61 -
62 - $this->_addAjaxAction( Visualizer_Plugin::ACTION_FETCH_DB_DATA, 'getQueryData' );
63 - $this->_addAjaxAction( Visualizer_Plugin::ACTION_SAVE_DB_QUERY, 'saveQuery' );
64 -
65 - $this->_addAjaxAction( Visualizer_Plugin::ACTION_JSON_GET_ROOTS, 'getJsonRoots' );
66 - $this->_addAjaxAction( Visualizer_Plugin::ACTION_JSON_GET_DATA, 'getJsonData' );
67 - $this->_addAjaxAction( Visualizer_Plugin::ACTION_JSON_SET_DATA, 'setJsonData' );
68 - $this->_addAjaxAction( Visualizer_Plugin::ACTION_JSON_SET_SCHEDULE, 'setJsonSchedule' );
69 -
70 - $this->_addAjaxAction( Visualizer_Plugin::ACTION_SAVE_FILTER_QUERY, 'saveFilter' );
71 -
72 - $this->_addFilter( 'visualizer_get_sidebar', 'getSidebar', 10, 2 );
73 -
74 62 }
75 63
76 64 /**
77 - * Generates the HTML of the sidebar for the chart.
65 + * Sends json response.
78 66 *
79 - * @since ?
67 + * @since 1.0.0
80 68 *
81 - * @access public
69 + * @access private
70 + * @param array $results The response array.
82 71 */
83 - public function getSidebar( $sidebar, $chart_id ) {
84 - $chart = get_post( $chart_id );
85 - $data = $this->_getChartArray( $chart );
86 - $sidebar = '';
87 - $sidebar_class = $this->load_chart_class_name( $chart_id );
88 - if ( class_exists( $sidebar_class, true ) ) {
89 - $sidebar = new $sidebar_class( $data['settings'] );
90 - $sidebar->__series = $data['series'];
91 - $sidebar->__data = $data['data'];
92 - } else {
93 - $sidebar = apply_filters( 'visualizer_pro_chart_type_sidebar', '', $data );
94 - if ( $sidebar !== '' ) {
95 - $sidebar->__series = $data['series'];
96 - $sidebar->__data = $data['data'];
97 - }
98 - }
99 - return str_replace( "'", '"', $sidebar->__toString() );
100 - }
72 + private function _sendResponse( $results ) {
73 + header( 'Content-type: application/json' );
74 + nocache_headers();
101 75
102 - /**
103 - * Sets the schedule for how JSON-endpoint charts should be updated.
104 - *
105 - * @since ?
106 - *
107 - * @access public
108 - */
109 - public function setJsonSchedule() {
110 - check_ajax_referer( Visualizer_Plugin::ACTION_JSON_SET_SCHEDULE . Visualizer_Plugin::VERSION, 'security' );
111 -
112 - $chart_id = filter_input(
113 - INPUT_POST,
114 - 'chart',
115 - FILTER_VALIDATE_INT,
116 - array(
117 - 'options' => array(
118 - 'min_range' => 1,
119 - ),
120 - )
121 - );
122 -
123 - if ( ! $chart_id ) {
124 - wp_send_json_error();
125 - }
126 -
127 - $time = filter_input(
128 - INPUT_POST,
129 - 'time',
130 - FILTER_VALIDATE_INT,
131 - array(
132 - 'options' => array(
133 - 'min_range' => -1,
134 - ),
135 - )
136 - );
137 -
138 - if ( Visualizer_Module::is_pro() ) {
139 - $is_woocommerce_report = filter_input(
140 - INPUT_POST,
141 - 'is_woocommerce_report',
142 - FILTER_VALIDATE_BOOLEAN
143 - );
144 -
145 - if ( $is_woocommerce_report ) {
146 - update_post_meta( $chart_id, Visualizer_Plugin::CF_IS_WOOCOMMERCE_SOURCE, true );
147 - } else {
148 - delete_post_meta( $chart_id, Visualizer_Plugin::CF_IS_WOOCOMMERCE_SOURCE );
149 - }
150 - }
151 -
152 - delete_post_meta( $chart_id, Visualizer_Plugin::CF_JSON_SCHEDULE );
153 -
154 - if ( -1 < $time ) {
155 - add_post_meta( $chart_id, Visualizer_Plugin::CF_JSON_SCHEDULE, $time );
156 - // Update schedules.
157 - $schedules = get_option( Visualizer_Plugin::CF_JSON_SCHEDULE, array() );
158 - $schedules[ $chart_id ] = time() + $time * HOUR_IN_SECONDS;
159 - update_option( Visualizer_Plugin::CF_JSON_SCHEDULE, $schedules );
160 - }
161 - wp_send_json_success();
76 + echo json_encode( $results );
77 + exit;
162 78 }
163 79
164 80 /**
165 - * Get the root elements for JSON-endpoint.
81 + * Returns chart data required for rendering.
166 82 *
167 - * @since ?
83 + * @since 1.0.0
168 84 *
169 - * @access public
85 + * @access private
86 + * @param WP_Post $chart The chart object.
87 + * @return array The array of chart data.
170 88 */
171 - public function getJsonRoots() {
172 - check_ajax_referer( Visualizer_Plugin::ACTION_JSON_GET_ROOTS . Visualizer_Plugin::VERSION, 'security' );
173 -
174 - $params = wp_parse_args( $_POST['params'] );
175 -
176 - $source = new Visualizer_Source_Json( $params );
177 -
178 - $roots = $source->fetchRoots();
179 - if ( empty( $roots ) ) {
180 - wp_send_json_error( array( 'msg' => $source->get_error() ) );
89 + private function _getChartArray( WP_Post $chart = null ) {
90 + if ( is_null( $chart ) ) {
91 + $chart = $this->_chart;
181 92 }
182 93
183 - wp_send_json_success( array( 'url' => $params['url'], 'roots' => $roots ) );
184 - }
94 + $type = get_post_meta( $chart->ID, Visualizer_Plugin::CF_CHART_TYPE, true );
95 + $series = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_SERIES, get_post_meta( $chart->ID, Visualizer_Plugin::CF_SERIES, true ), $chart->ID, $type );
96 + $data = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_DATA, unserialize( $chart->post_content ), $chart->ID, $type );
185 97
186 - /**
187 - * Get the data for the JSON-endpoint corresponding to the chosen root.
188 - *
189 - * @since ?
190 - *
191 - * @access public
192 - */
193 - public function getJsonData() {
194 - check_ajax_referer( Visualizer_Plugin::ACTION_JSON_GET_DATA . Visualizer_Plugin::VERSION, 'security' );
195 -
196 - $params = wp_parse_args( $_POST['params'] );
197 -
198 - $chart_id = $params['chart'];
199 -
200 - if ( empty( $chart_id ) ) {
201 - wp_die();
202 - }
203 -
204 - $source = new Visualizer_Source_Json( $params );
205 - $source->fetch();
206 - $data = $source->getRawData();
207 -
208 - if ( empty( $data ) ) {
209 - wp_send_json_error( array( 'msg' => esc_html__( 'Unable to fetch data from the endpoint. Please try again.', 'visualizer' ) ) );
210 - }
211 -
212 - $data = Visualizer_Render_Layout::show( 'editor-table', $data, $chart_id, 'viz-json-table', false, false );
213 - wp_send_json_success( array( 'table' => $data, 'root' => $params['root'], 'url' => $params['url'], 'paging' => $source->getPaginationElements() ) );
214 - }
215 -
216 - /**
217 - * Updates the database with the correct post parameters for JSON-endpoint charts.
218 - *
219 - * @since ?
220 - *
221 - * @access public
222 - */
223 - public function setJsonData() {
224 - check_ajax_referer( Visualizer_Plugin::ACTION_JSON_SET_DATA . Visualizer_Plugin::VERSION, 'security' );
225 -
226 - $params = $_POST;
227 - $chart_id = $_GET['chart'];
228 -
229 - if ( empty( $chart_id ) ) {
230 - wp_die();
231 - }
232 -
233 - $chart = get_post( $chart_id );
234 -
235 - $source = new Visualizer_Source_Json( $params );
236 - update_post_meta( $chart->ID, Visualizer_Plugin::CF_EDITABLE_TABLE, true );
237 - $source->fetchFromEditableTable();
238 -
239 - $content = $source->getData( get_post_meta( $chart->ID, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) );
240 - $chart->post_content = $content;
241 - wp_update_post( $chart->to_array() );
242 - update_post_meta( $chart->ID, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
243 - update_post_meta( $chart->ID, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() );
244 - update_post_meta( $chart->ID, Visualizer_Plugin::CF_DEFAULT_DATA, 0 );
245 - update_post_meta( $chart->ID, Visualizer_Plugin::CF_JSON_URL, $params['url'] );
246 - update_post_meta( $chart->ID, Visualizer_Plugin::CF_JSON_ROOT, $params['root'] );
247 -
248 - delete_post_meta( $chart->ID, Visualizer_Plugin::CF_JSON_HEADERS );
249 - $headers = array( 'method' => $params['method'] );
250 - if ( ! empty( $params['auth'] ) ) {
251 - $headers['auth'] = $params['auth'];
252 - } elseif ( ! empty( $params['username'] ) && ! empty( $params['password'] ) ) {
253 - $headers['auth'] = array( 'username' => $params['username'], 'password' => $params['password'] );
254 - }
255 -
256 - add_post_meta( $chart->ID, Visualizer_Plugin::CF_JSON_HEADERS, $headers );
257 -
258 - delete_post_meta( $chart->ID, Visualizer_Plugin::CF_JSON_PAGING );
259 - if ( ! empty( $params['paging'] ) ) {
260 - add_post_meta( $chart->ID, Visualizer_Plugin::CF_JSON_PAGING, $params['paging'] );
261 - }
262 -
263 - if ( Visualizer_Module::is_pro() ) {
264 - if ( ! empty( $params['vz_woo_source'] ) ) {
265 - update_post_meta( $chart->ID, Visualizer_Plugin::CF_JSON_WOOCOMMERCE_SOURCE, $params['vz_woo_source'] );
266 - } else {
267 - delete_post_meta( $chart->ID, Visualizer_Plugin::CF_JSON_WOOCOMMERCE_SOURCE );
268 - }
269 - }
270 -
271 - $time = filter_input(
272 - INPUT_POST,
273 - 'time',
274 - FILTER_VALIDATE_INT,
275 - array(
276 - 'options' => array(
277 - 'min_range' => -1,
278 - ),
279 - )
98 + return array(
99 + 'type' => $type,
100 + 'series' => $series,
101 + 'settings' => get_post_meta( $chart->ID, Visualizer_Plugin::CF_SETTINGS, true ),
102 + 'data' => $data,
280 103 );
281 -
282 - delete_post_meta( $chart_id, Visualizer_Plugin::CF_JSON_SCHEDULE );
283 -
284 - if ( -1 < $time ) {
285 - add_post_meta( $chart_id, Visualizer_Plugin::CF_JSON_SCHEDULE, $time );
286 - }
287 -
288 - // delete other source specific parameters.
289 - delete_post_meta( $chart_id, Visualizer_Plugin::CF_DB_QUERY );
290 - delete_post_meta( $chart_id, Visualizer_Plugin::CF_DB_SCHEDULE );
291 - delete_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_URL );
292 - delete_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_SCHEDULE );
293 -
294 - $render = new Visualizer_Render_Page_Update();
295 - $render->id = $chart->ID;
296 - $render->data = json_encode( $source->getRawData( get_post_meta( $chart_id, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) ) );
297 - $render->series = json_encode( $source->getSeries() );
298 - $render->render();
299 -
300 - defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
301 104 }
302 105
303 -
304 106 /**
305 107 * Fetches charts from database.
306 108 *
307 - * This method is also called from the media pop-up (classic editor: create a post and add chart from insert content).
308 - *
309 109 * @since 1.0.0
310 110 *
311 111 * @access public
312 112 */
@@ -313,27 +113,18 @@
313 113 public function getCharts() {
314 114 $query_args = array(
315 115 'post_type' => Visualizer_Plugin::CPT_VISUALIZER,
316 116 'posts_per_page' => 9,
317 - 'paged' => filter_input(
318 - INPUT_GET,
319 - 'page',
320 - FILTER_VALIDATE_INT,
321 - array(
322 - 'options' => array(
323 - 'min_range' => 1,
324 - 'default' => 1,
325 - ),
117 + 'paged' => filter_input( INPUT_GET, 'page', FILTER_VALIDATE_INT, array(
118 + 'options' => array(
119 + 'min_range' => 1,
120 + 'default' => 1,
326 121 )
327 - ),
122 + ) )
328 123 );
329 - $filter = filter_input( INPUT_GET, 's', FILTER_SANITIZE_STRING );
330 - if ( empty( $filter ) ) {
331 - // 'filter' is from the modal from the add media button.
332 - $filter = filter_input( INPUT_GET, 'filter', FILTER_SANITIZE_STRING );
333 - }
334 124
335 - if ( $filter && in_array( $filter, Visualizer_Plugin::getChartTypes(), true ) ) {
125 + $filter = filter_input( INPUT_GET, 'filter' );
126 + if ( $filter && in_array( $filter, Visualizer_Plugin::getChartTypes() ) ) {
336 127 $query_args['meta_query'] = array(
337 128 array(
338 129 'key' => Visualizer_Plugin::CF_CHART_TYPE,
339 130 'value' => $filter,
@@ -340,98 +131,29 @@
340 131 'compare' => '=',
341 132 ),
342 133 );
343 134 }
344 - $query = new WP_Query( $query_args );
135 +
136 + $query = new WP_Query( $query_args );
137 +
345 138 $charts = array();
346 - while ( $query->have_posts() ) {
347 - $chart = $query->next_post();
348 - $chart_data = $this->_getChartArray( $chart );
139 + while( $query->have_posts() ) {
140 + $chart = $query->next_post();
141 +
142 + $chart_data = $this->_getChartArray( $chart );
349 143 $chart_data['id'] = $chart->ID;
350 - $chart_data['library'] = $this->load_chart_type( $chart->ID );
351 - $css = '';
352 - $settings = $chart_data['settings'];
353 - $arguments = $this->get_inline_custom_css( 'visualizer-chart-' . $chart->ID, $settings );
354 - if ( ! empty( $arguments ) ) {
355 - $css = $arguments[0];
356 - $settings = $arguments[1];
357 - }
358 - $chart_data['settings'] = $settings;
359 - $chart_data['css'] = $css;
360 - $charts[] = $chart_data;
361 - }
362 - self::_sendResponse(
363 - array(
364 - 'success' => true,
365 - 'data' => $charts,
366 - 'total' => $query->max_num_pages,
367 - )
368 - );
369 - }
370 144
371 - /**
372 - * Returns chart data required for rendering.
373 - *
374 - * @since 1.0.0
375 - *
376 - * @access private
377 - *
378 - * @param WP_Post $chart The chart object.
379 - *
380 - * @return array The array of chart data.
381 - */
382 - private function _getChartArray( WP_Post $chart = null ) {
383 - if ( is_null( $chart ) ) {
384 - $chart = $this->_chart;
145 + $charts[] = $chart_data;
385 146 }
386 - $type = get_post_meta( $chart->ID, Visualizer_Plugin::CF_CHART_TYPE, true );
387 - $series = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_SERIES, get_post_meta( $chart->ID, Visualizer_Plugin::CF_SERIES, true ), $chart->ID, $type );
388 - $data = self::get_chart_data( $chart, $type );
389 - $library = $this->load_chart_type( $chart->ID );
390 147
391 - $settings = get_post_meta( $chart->ID, Visualizer_Plugin::CF_SETTINGS, true );
392 - $settings = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_SETTINGS, $settings, $chart->ID, $type );
393 - if ( ! empty( $atts['settings'] ) ) {
394 - $settings = apply_filters( $atts['settings'], $settings, $chart->ID, $type );
395 - }
396 -
397 - $css = '';
398 - $arguments = $this->get_inline_custom_css( 'visualizer-' . $chart->ID, $settings );
399 - if ( ! empty( $arguments ) ) {
400 - $css = $arguments[0];
401 - $settings = $arguments[1];
402 - }
403 -
404 - $date_formats = Visualizer_Source::get_date_formats_if_exists( $series, $data );
405 -
406 - return array(
407 - 'type' => $type,
408 - 'series' => $series,
409 - 'settings' => $settings,
410 - 'data' => $data,
411 - 'library' => $library,
412 - 'css' => $css,
413 - 'date_formats' => $date_formats,
414 - );
148 + $this->_sendResponse( array(
149 + 'success' => true,
150 + 'data' => $charts,
151 + 'total' => $query->max_num_pages,
152 + ) );
415 153 }
416 154
417 155 /**
418 - * Sends json response.
419 - *
420 - * @since 1.0.0
421 - *
422 - * @access private
423 - *
424 - * @param array $results The response array.
425 - */
426 - public static function _sendResponse( $results ) {
427 - header( 'Content-type: application/json' );
428 - nocache_headers();
429 - echo json_encode( $results );
430 - defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
431 - }
432 -
433 - /**
434 156 * Deletes a chart from database.
435 157 *
436 158 * @since 1.0.0
437 159 * @uses wp_delete_post() To delete a chart.
@@ -438,85 +160,35 @@
438 160 *
439 161 * @access public
440 162 */
441 163 public function deleteChart() {
442 - $is_post = $_SERVER['REQUEST_METHOD'] === 'POST';
164 + $is_post = $_SERVER['REQUEST_METHOD'] == 'POST';
443 165 $input_method = $is_post ? INPUT_POST : INPUT_GET;
444 - $chart_id = $success = false;
445 - $nonce = wp_verify_nonce( filter_input( $input_method, 'nonce' ) );
446 - $capable = current_user_can( 'delete_posts' );
166 +
167 + $chart_id = $success = false;
168 + $nonce = Visualizer_Security::verifyNonce( filter_input( $input_method, 'nonce' ) );
169 + $capable = current_user_can( 'delete_posts' );
447 170 if ( $nonce && $capable ) {
448 - $chart_id = filter_input(
449 - $input_method,
450 - 'chart',
451 - FILTER_VALIDATE_INT,
452 - array(
453 - 'options' => array(
454 - 'min_range' => 1,
455 - ),
456 - )
457 - );
171 + $chart_id = filter_input( $input_method, 'chart', FILTER_VALIDATE_INT, array( 'options' => array( 'min_range' => 1 ) ) );
458 172 if ( $chart_id ) {
459 - $chart = get_post( $chart_id );
460 - $success = $chart && $chart->post_type === Visualizer_Plugin::CPT_VISUALIZER;
173 + $chart = get_post( $chart_id );
174 + $success = $chart && $chart->post_type == Visualizer_Plugin::CPT_VISUALIZER;
461 175 }
462 176 }
177 +
463 178 if ( $success ) {
464 - global $sitepress;
465 - if ( Visualizer_Module::is_pro() && ( function_exists( 'icl_get_languages' ) && $sitepress instanceof \SitePress ) ) {
466 - $trid = $sitepress->get_element_trid( $chart_id, 'post_' . Visualizer_Plugin::CPT_VISUALIZER );
467 - $translations = $sitepress->get_element_translations( $trid );
468 - if ( ! empty( $translations ) ) {
469 - foreach ( $translations as $translated_post ) {
470 - wp_delete_post( $translated_post->element_id, true );
471 - }
472 - } else {
473 - wp_delete_post( $chart_id, true );
474 - }
475 - } else {
476 - wp_delete_post( $chart_id, true );
477 - }
179 + wp_delete_post( $chart_id, true );
478 180 }
181 +
479 182 if ( $is_post ) {
480 - self::_sendResponse(
481 - array(
482 - 'success' => $success,
483 - )
484 - );
183 + $this->_sendResponse( array( 'success' => $success ) );
485 184 }
486 - wp_redirect( remove_query_arg( 'vaction', wp_get_referer() ) );
185 +
186 + wp_redirect( wp_get_referer() );
487 187 exit;
488 188 }
489 189
490 190 /**
491 - * Delete charts that are still in auto-draft mode.
492 - */
493 - private function deleteOldCharts() {
494 - $query = new WP_Query(
495 - array(
496 - 'post_type' => Visualizer_Plugin::CPT_VISUALIZER,
497 - 'post_status' => 'auto-draft',
498 - 'fields' => 'ids',
499 - 'update_post_meta_cache' => false,
500 - 'update_post_term_cache' => false,
501 - 'posts_per_page' => 50,
502 - 'date_query' => array(
503 - array(
504 - 'before' => 'today',
505 - ),
506 - ),
507 - )
508 - );
509 -
510 - if ( $query->have_posts() ) {
511 - $ids = array();
512 - while ( $query->have_posts() ) {
513 - wp_delete_post( $query->next_post(), true );
514 - }
515 - }
516 - }
517 -
518 - /**
519 191 * Renders appropriate page for chart builder. Creates new auto draft chart
520 192 * if no chart has been specified.
521 193 *
522 194 * @since 1.0.0
@@ -523,426 +195,65 @@
523 195 *
524 196 * @access public
525 197 */
526 198 public function renderChartPages() {
527 - defined( 'IFRAME_REQUEST' ) || define( 'IFRAME_REQUEST', 1 );
528 - if ( ! defined( 'ET_BUILDER_PRODUCT_VERSION' ) && function_exists( 'et_get_theme_version' ) ) {
529 - define( 'ET_BUILDER_PRODUCT_VERSION', et_get_theme_version() );
530 - }
531 - // Set current screen for the render chart.
532 - set_current_screen( 'visualizer_render_chart' );
199 + define ( 'IFRAME_REQUEST', 1 );
200 +
533 201 // check chart, if chart not exists, will create new one and redirects to the same page with proper chart id
534 - $chart_id = isset( $_GET['chart'] ) ? filter_var( $_GET['chart'], FILTER_VALIDATE_INT ) : '';
535 - if ( ! empty( $_POST ) ) {
536 - $_POST = map_deep( $_POST, 'wp_strip_all_tags' );
537 - }
538 - if ( ! $chart_id || ! ( $chart = get_post( $chart_id ) ) || $chart->post_type !== Visualizer_Plugin::CPT_VISUALIZER ) {
539 - if ( empty( $_GET['lang'] ) || empty( $_GET['parent_chart_id'] ) ) {
540 - $this->deleteOldCharts();
541 - $default_type = isset( $_GET['type'] ) && ! empty( $_GET['type'] ) ? $_GET['type'] : 'line';
542 - $chart_status = Visualizer_Module_Admin::checkChartStatus( $default_type );
543 - if ( ! $chart_status ) {
544 - $default_type = 'line';
545 - }
546 - $source = new Visualizer_Source_Csv( VISUALIZER_ABSPATH . DIRECTORY_SEPARATOR . 'samples' . DIRECTORY_SEPARATOR . $default_type . '.csv' );
547 - $source->fetch();
548 - $chart_id = wp_insert_post(
549 - array(
550 - 'post_type' => Visualizer_Plugin::CPT_VISUALIZER,
551 - 'post_title' => 'Visualization',
552 - 'post_author' => get_current_user_id(),
553 - 'post_status' => 'auto-draft',
554 - 'post_content' => $source->getData( get_post_meta( $chart_id, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) ),
555 - )
556 - );
557 - if ( $chart_id && ! is_wp_error( $chart_id ) ) {
558 - add_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_TYPE, $default_type );
559 - add_post_meta( $chart_id, Visualizer_Plugin::CF_DEFAULT_DATA, 1 );
560 - add_post_meta( $chart_id, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() );
561 - add_post_meta( $chart_id, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
562 - add_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_LIBRARY, '' );
563 - add_post_meta(
564 - $chart_id,
565 - Visualizer_Plugin::CF_SETTINGS,
566 - array(
567 - 'focusTarget' => 'datum',
568 - )
569 - );
202 + $chart_id = filter_input( INPUT_GET, 'chart', FILTER_VALIDATE_INT );
203 + if ( !$chart_id || !( $chart = get_post( $chart_id ) ) || $chart->post_type != Visualizer_Plugin::CPT_VISUALIZER ) {
204 + $default_type = 'line';
570 205
571 - do_action( 'visualizer_pro_new_chart_defaults', $chart_id );
572 - }
573 - } else {
574 - if ( current_user_can( 'edit_posts' ) ) {
575 - $parent_chart_id = isset( $_GET['parent_chart_id'] ) ? filter_var( $_GET['parent_chart_id'], FILTER_VALIDATE_INT ) : '';
576 - $success = false;
577 - if ( $parent_chart_id ) {
578 - $parent_chart = get_post( $parent_chart_id );
579 - $success = $parent_chart && $parent_chart->post_type === Visualizer_Plugin::CPT_VISUALIZER;
580 - }
581 - if ( $success ) {
582 - $new_chart_id = wp_insert_post(
583 - array(
584 - 'post_type' => Visualizer_Plugin::CPT_VISUALIZER,
585 - 'post_title' => 'Visualization',
586 - 'post_author' => get_current_user_id(),
587 - 'post_status' => $parent_chart->post_status,
588 - 'post_content' => $parent_chart->post_content,
589 - )
590 - );
206 + $source = new Visualizer_Source_Csv( VISUALIZER_ABSPATH . DIRECTORY_SEPARATOR . 'samples' . DIRECTORY_SEPARATOR . $default_type . '.csv' );
207 + $source->fetch();
591 208
592 - if ( is_wp_error( $new_chart_id ) ) {
593 - 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__ );
594 - } else {
595 - $post_meta = get_post_meta( $parent_chart_id );
596 - $chart_id = $new_chart_id;
597 - foreach ( $post_meta as $key => $value ) {
598 - if ( strpos( $key, 'visualizer-' ) !== false ) {
599 - add_post_meta( $new_chart_id, $key, maybe_unserialize( $value[0] ) );
600 - }
601 - }
602 - }
603 - }
604 - }
605 - do_action( 'visualizer_pro_new_chart_defaults', $chart_id );
606 - }
607 - wp_redirect( esc_url_raw( add_query_arg( 'chart', (int) $chart_id ) ) );
209 + $chart_id = wp_insert_post( array(
210 + 'post_type' => Visualizer_Plugin::CPT_VISUALIZER,
211 + 'post_title' => 'Visualization',
212 + 'post_author' => get_current_user_id(),
213 + 'post_status' => 'auto-draft',
214 + 'post_content' => $source->getData(),
215 + ) );
608 216
609 - if ( defined( 'WP_TESTS_DOMAIN' ) ) {
610 - wp_die();
217 + if ( $chart_id && !is_wp_error( $chart_id ) ) {
218 + add_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_TYPE, $default_type );
219 + add_post_meta( $chart_id, Visualizer_Plugin::CF_DEFAULT_DATA, 1 );
220 + add_post_meta( $chart_id, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() );
221 + add_post_meta( $chart_id, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
222 + add_post_meta( $chart_id, Visualizer_Plugin::CF_SETTINGS, array() );
611 223 }
612 - exit();
613 - }
614 224
615 - $_POST['save_chart_image'] = isset( $_POST['save_chart_image'] ) && 'yes' === $_POST['save_chart_image'] ? true : false;
616 - $_POST['lazy_load_chart'] = isset( $_POST['lazy_load_chart'] ) && 'yes' === $_POST['lazy_load_chart'] ? true : false;
617 -
618 - if ( isset( $_POST['chart-img'] ) && ! empty( $_POST['chart-img'] ) ) {
619 - $attachment_id = $this->save_chart_image( $_POST['chart-img'], $chart_id, $_POST['save_chart_image'] );
620 - if ( $attachment_id ) {
621 - update_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_IMAGE, $attachment_id );
622 - }
225 + wp_redirect( add_query_arg( 'chart', (int)$chart_id ) );
226 + exit;
623 227 }
624 - $lib = $this->load_chart_type( $chart_id );
625 228
626 - // the alpha color picker (RGBA) is not supported by google.
627 - $color_picker_dep = 'wp-color-picker';
628 - if ( in_array( $lib, array( 'chartjs', 'datatables' ), true ) && ! wp_script_is( 'wp-color-picker-alpha', 'registered' ) ) {
629 - wp_register_script( 'wp-color-picker-alpha', VISUALIZER_ABSURL . 'js/lib/wp-color-picker-alpha.min.js', array( 'wp-color-picker' ), Visualizer_Plugin::VERSION );
630 - $color_picker_dep = 'wp-color-picker-alpha';
631 - }
632 -
633 229 // enqueue and register scripts and styles
634 - wp_register_script( 'visualizer-chosen', VISUALIZER_ABSURL . 'js/lib/chosen.jquery.min.js', array( 'jquery' ), Visualizer_Plugin::VERSION );
635 - wp_register_style( 'visualizer-chosen', VISUALIZER_ABSURL . 'css/lib/chosen.min.css', array(), Visualizer_Plugin::VERSION );
230 + wp_register_style( 'visualizer-frame', VISUALIZER_ABSURL . 'css/frame.css', array(), Visualizer_Plugin::VERSION );
636 231
637 - wp_register_style( 'visualizer-frame', VISUALIZER_ABSURL . 'css/frame.css', array( 'visualizer-chosen' ), Visualizer_Plugin::VERSION );
638 - wp_register_script( 'visualizer-frame', VISUALIZER_ABSURL . 'js/frame.js', array( 'visualizer-chosen', 'jquery-ui-accordion', 'jquery-ui-tabs' ), Visualizer_Plugin::VERSION, true );
639 - wp_register_script( 'visualizer-customization', $this->get_user_customization_js(), array(), null, true );
640 - wp_register_script(
641 - 'visualizer-render',
642 - VISUALIZER_ABSURL . 'js/render-facade.js',
643 - apply_filters( 'visualizer_assets_render', array( 'visualizer-frame', 'visualizer-customization' ), false ),
644 - Visualizer_Plugin::VERSION,
645 - true
646 - );
647 - wp_register_script(
648 - 'visualizer-preview',
649 - VISUALIZER_ABSURL . 'js/preview.js',
650 - array(
651 - $color_picker_dep,
652 - 'visualizer-render',
653 - ),
654 - Visualizer_Plugin::VERSION,
655 - true
656 - );
657 - wp_register_script( 'visualizer-editor-simple', VISUALIZER_ABSURL . 'js/simple-editor.js', array( 'jquery' ), Visualizer_Plugin::VERSION, true );
232 + wp_register_script( 'visualizer-frame', VISUALIZER_ABSURL . 'js/frame.js', array( 'jquery' ), Visualizer_Plugin::VERSION, true );
233 + wp_register_script( 'google-jsapi', '//www.google.com/jsapi', array(), null, true );
234 + wp_register_script( 'visualizer-render', VISUALIZER_ABSURL . 'js/render.js', array( 'google-jsapi', 'visualizer-frame' ), Visualizer_Plugin::VERSION, true );
235 + wp_register_script( 'visualizer-preview', VISUALIZER_ABSURL . 'js/preview.js', array( 'wp-color-picker', 'visualizer-render' ), Visualizer_Plugin::VERSION, true );
658 236
659 - do_action( 'visualizer_add_scripts' );
660 -
661 - if ( Visualizer_Module::is_pro() && Visualizer_Module::is_pro_older_than( '1.9.0' ) ) {
662 - global $Visualizer_Pro;
663 - $Visualizer_Pro->_addScriptsAndStyles();
664 - }
665 -
666 237 // dispatch pages
667 - $this->_chart = get_post( $chart_id );
668 - $tab = isset( $_GET['tab'] ) && ! empty( $_GET['tab'] ) ? $_GET['tab'] : 'visualizer';
669 -
670 - // skip chart type pages only for existing charts.
671 - if ( VISUALIZER_SKIP_CHART_TYPE_PAGE && 'auto-draft' !== $this->_chart->post_status && ( ! empty( $_GET['tab'] ) && 'visualizer' === $_GET['tab'] ) ) {
672 - $tab = 'settings';
673 - }
674 -
675 - if ( isset( $_POST['cancel'] ) && 1 === intval( $_POST['cancel'] ) ) {
676 - // if the cancel button is clicked.
677 - $this->undoRevisions( $chart_id, true );
678 - } elseif ( isset( $_POST['save'] ) && 1 === intval( $_POST['save'] ) ) {
679 - $this->handlePermissions();
680 - // if the save button is clicked.
681 - $this->undoRevisions( $chart_id, false );
682 - } else {
683 - // if the edit button is clicked.
684 - $this->_chart = $this->handleExistingRevisions( $chart_id, $this->_chart );
685 - }
686 -
687 - // Clear existing chart cache.
688 - if ( isset( $_POST['save'] ) && 1 === intval( $_POST['save'] ) ) {
689 - $cache_key = Visualizer_Plugin::CF_CHART_CACHE . '_' . $chart_id;
690 - if ( get_transient( $cache_key ) ) {
691 - delete_transient( $cache_key );
692 - }
693 - }
694 -
695 - switch ( $tab ) {
238 + $this->_chart = $chart;
239 + switch ( filter_input( INPUT_GET, 'tab' ) ) {
240 + case 'data':
241 + $this->_handleDataPage();
242 + break;
696 243 case 'settings':
697 - $this->_handleDataAndSettingsPage();
244 + $this->_handleSettingsPage();
698 245 break;
699 - case 'type': // fall through.
700 - case 'visualizer': // fall through.
246 + case 'type':
247 + default:
701 248 $this->_handleTypesPage();
702 249 break;
703 - default:
704 - // this should never happen.
705 - break;
706 250 }
707 - defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
708 - }
709 251
710 - /**
711 - * Load code editor assets.
712 - */
713 - private function loadCodeEditorAssets( $chart_id ) {
714 - global $wp_version;
715 -
716 - $wp_scripts = wp_scripts();
717 -
718 - // data tables assets.
719 - wp_register_script( 'visualizer-datatables', VISUALIZER_ABSURL . 'js/lib/datatables.min.js', array( 'jquery-ui-core' ), Visualizer_Plugin::VERSION );
720 - wp_register_style( 'visualizer-datatables', VISUALIZER_ABSURL . 'css/lib/datatables.min.css', array(), Visualizer_Plugin::VERSION );
721 - 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 );
722 - wp_enqueue_script( 'visualizer-datatables' );
723 - wp_enqueue_style( 'visualizer-jquery-ui' );
724 -
725 - if ( ! Visualizer_Module::is_pro() ) {
726 - return;
727 - }
728 -
729 - $table_col_mapping = Visualizer_Source_Query_Params::get_all_db_tables_column_mapping( $chart_id );
730 -
731 - if ( version_compare( $wp_version, '4.9.0', '<' ) ) {
732 - // code mirror assets.
733 - wp_register_script( 'visualizer-codemirror-core', '//codemirror.net/lib/codemirror.js', array( 'jquery' ), Visualizer_Plugin::VERSION );
734 - wp_register_script( 'visualizer-codemirror-placeholder', '//codemirror.net/addon/display/placeholder.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
735 - wp_register_script( 'visualizer-codemirror-matchbrackets', '//codemirror.net/addon/edit/matchbrackets.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
736 - wp_register_script( 'visualizer-codemirror-closebrackets', '//codemirror.net/addon/edit/closebrackets.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
737 - wp_register_script( 'visualizer-codemirror-sql', '//codemirror.net/mode/sql/sql.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
738 - wp_register_script( 'visualizer-codemirror-sql-hint', '//codemirror.net/addon/hint/sql-hint.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
739 - 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 );
740 - wp_register_style( 'visualizer-codemirror-core', '//codemirror.net/lib/codemirror.css', array(), Visualizer_Plugin::VERSION );
741 - wp_register_style( 'visualizer-codemirror-hint', '//codemirror.net/addon/hint/show-hint.css', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION );
742 -
743 - wp_enqueue_script( 'visualizer-codemirror-hint' );
744 - wp_enqueue_style( 'visualizer-codemirror-hint' );
745 - } else {
746 - wp_enqueue_code_editor(
747 - array(
748 - 'type' => 'sql',
749 - 'codemirror' => array(
750 - 'autofocus' => true,
751 - 'lineWrapping' => true,
752 - 'dragDrop' => false,
753 - 'matchBrackets' => true,
754 - 'autoCloseBrackets' => true,
755 - 'extraKeys' => array( 'Ctrl-Space' => 'autocomplete' ),
756 - 'hintOptions' => array( 'tables' => $table_col_mapping ),
757 - ),
758 - )
759 - );
760 - }
761 -
762 - return $table_col_mapping;
252 + exit;
763 253 }
764 254
765 255 /**
766 - * Handle permissions from the new conslidated settings sidebar.
767 - */
768 - private function handlePermissions() {
769 - if ( ! Visualizer_Module::is_pro() ) {
770 - return;
771 - }
772 -
773 - // we will not support old free and new pro.
774 - // handling new free and old pro.
775 - if ( has_action( 'visualizer_pro_handle_tab' ) ) {
776 - do_action( 'visualizer_pro_handle_tab', 'permissions', $this->_chart );
777 - } else {
778 - do_action( 'visualizer_handle_permissions', $this->_chart );
779 - }
780 - }
781 -
782 - /**
783 - * Handle data and settings page
784 - */
785 - private function _handleDataAndSettingsPage() {
786 - if ( isset( $_POST['map_api_key'] ) ) {
787 - update_option( 'visualizer-map-api-key', $_POST['map_api_key'] );
788 - }
789 -
790 - if ( $_SERVER['REQUEST_METHOD'] === 'POST' && isset( $_GET['nonce'] ) && wp_verify_nonce( $_GET['nonce'] ) ) {
791 - if ( $this->_chart->post_status === 'auto-draft' ) {
792 - $this->_chart->post_status = 'publish';
793 -
794 - // 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.
795 - // we do not want any difference in data so disable revisions temporarily.
796 - $this->disableRevisionsTemporarily();
797 -
798 - wp_update_post( $this->_chart->to_array() );
799 - }
800 - // save meta data only when it is NOT being canceled.
801 - if ( ! ( isset( $_POST['cancel'] ) && 1 === intval( $_POST['cancel'] ) ) ) {
802 - update_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SETTINGS, $_POST );
803 -
804 - // we will keep a parameter called 'internal_title' that will be set to the given title or, if empty, the chart ID
805 - // this will help in searching with the chart id.
806 - $settings = get_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SETTINGS, true );
807 - $title = null;
808 - if ( isset( $settings['title'] ) && ! empty( $settings['title'] ) ) {
809 - $title = $settings['title'];
810 - if ( is_array( $title ) ) {
811 - $title = $settings['title']['text'];
812 - }
813 - }
814 - if ( empty( $title ) ) {
815 - $title = $this->_chart->ID;
816 - }
817 - $settings['internal_title'] = $title;
818 - $settings_label = isset( $settings['pieResidueSliceLabel'] ) ? $settings['pieResidueSliceLabel'] : '';
819 - if ( empty( $settings_label ) ) {
820 - $settings['pieResidueSliceLabel'] = esc_html__( 'Other', 'visualizer' );
821 - } else {
822 - $settings['pieResidueSliceLabel'] = $settings_label;
823 - }
824 - update_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SETTINGS, $settings );
825 - }
826 - $render = new Visualizer_Render_Page_Send();
827 - $render->text = sprintf( '[visualizer id="%d"]', $this->_chart->ID );
828 - wp_iframe( array( $render, 'render' ) );
829 - return;
830 - }
831 - $data = $this->_getChartArray();
832 - $sidebar = '';
833 - $sidebar_class = $this->load_chart_class_name( $this->_chart->ID );
834 - if ( class_exists( $sidebar_class, true ) ) {
835 - $sidebar = new $sidebar_class( $data['settings'] );
836 - $sidebar->__series = $data['series'];
837 - $sidebar->__data = $data['data'];
838 - } else {
839 - $sidebar = apply_filters( 'visualizer_pro_chart_type_sidebar', '', $data );
840 - if ( $sidebar !== '' ) {
841 - $sidebar->__series = $data['series'];
842 - $sidebar->__data = $data['data'];
843 - }
844 - }
845 - unset( $data['settings']['width'], $data['settings']['height'], $data['settings']['chartArea'] );
846 - wp_enqueue_style( 'wp-color-picker' );
847 - wp_enqueue_style( 'visualizer-frame' );
848 - wp_enqueue_script( 'visualizer-preview' );
849 - wp_enqueue_script( 'visualizer-chosen' );
850 - wp_enqueue_script( 'visualizer-render' );
851 -
852 - if ( Visualizer_Module::can_show_feature( 'simple-editor' ) ) {
853 - wp_enqueue_script( 'visualizer-editor-simple' );
854 - wp_localize_script(
855 - 'visualizer-editor-simple',
856 - 'visualizer1',
857 - array(
858 - 'ajax' => array(
859 - 'url' => admin_url( 'admin-ajax.php' ),
860 - 'nonces' => array(
861 - ),
862 - 'actions' => array(
863 - ),
864 - ),
865 - )
866 - );
867 - }
868 -
869 - $table_col_mapping = $this->loadCodeEditorAssets( $this->_chart->ID );
870 -
871 - wp_localize_script(
872 - 'visualizer-render',
873 - 'visualizer',
874 - array(
875 - 'l10n' => array(
876 - 'invalid_source' => esc_html__( 'You have entered an invalid URL. Please provide a valid URL.', 'visualizer' ),
877 - 'loading' => esc_html__( 'Loading...', 'visualizer' ),
878 - 'json_error' => esc_html__( 'An error occured in fetching data.', 'visualizer' ),
879 - 'select_columns' => esc_html__( 'Please select a few columns to include in the chart.', 'visualizer' ),
880 - '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' ),
881 - ),
882 - 'charts' => array(
883 - 'canvas' => $data,
884 - 'id' => $this->_chart->ID,
885 - ),
886 - 'language' => $this->get_language(),
887 - 'map_api_key' => get_option( 'visualizer-map-api-key' ),
888 - 'ajax' => array(
889 - 'url' => admin_url( 'admin-ajax.php' ),
890 - 'nonces' => array(
891 - 'permissions' => wp_create_nonce( Visualizer_Plugin::ACTION_FETCH_PERMISSIONS_DATA ),
892 - 'db_get_data' => wp_create_nonce( Visualizer_Plugin::ACTION_FETCH_DB_DATA . Visualizer_Plugin::VERSION ),
893 - 'json_get_roots' => wp_create_nonce( Visualizer_Plugin::ACTION_JSON_GET_ROOTS . Visualizer_Plugin::VERSION ),
894 - 'json_get_data' => wp_create_nonce( Visualizer_Plugin::ACTION_JSON_GET_DATA . Visualizer_Plugin::VERSION ),
895 - 'json_set_schedule' => wp_create_nonce( Visualizer_Plugin::ACTION_JSON_SET_SCHEDULE . Visualizer_Plugin::VERSION ),
896 - ),
897 - 'actions' => array(
898 - 'permissions' => Visualizer_Plugin::ACTION_FETCH_PERMISSIONS_DATA,
899 - 'db_get_data' => Visualizer_Plugin::ACTION_FETCH_DB_DATA,
900 - 'json_get_roots' => Visualizer_Plugin::ACTION_JSON_GET_ROOTS,
901 - 'json_get_data' => Visualizer_Plugin::ACTION_JSON_GET_DATA,
902 - 'json_set_schedule' => Visualizer_Plugin::ACTION_JSON_SET_SCHEDULE,
903 - ),
904 - ),
905 - 'db_query' => array(
906 - 'tables' => $table_col_mapping,
907 - ),
908 - 'is_pro' => Visualizer_Module::is_pro(),
909 - 'page_type' => 'chart',
910 - 'json_tag_separator' => Visualizer_Source_Json::TAG_SEPARATOR,
911 - 'json_tag_separator_view' => Visualizer_Source_Json::TAG_SEPARATOR_VIEW,
912 - 'is_front' => false,
913 - 'rest_base' => get_rest_url( null, 'wc/v3/reports/' ),
914 - )
915 - );
916 -
917 - $render = new Visualizer_Render_Page_Data();
918 - $render->chart = $this->_chart;
919 - $render->type = $data['type'];
920 - $render->custom_css = $data['css'];
921 - $render->sidebar = $sidebar;
922 - if ( filter_input( INPUT_GET, 'library', FILTER_VALIDATE_BOOLEAN ) ) {
923 - $render->button = filter_input( INPUT_GET, 'action' ) === Visualizer_Plugin::ACTION_EDIT_CHART
924 - ? esc_html__( 'Save Chart', 'visualizer' )
925 - : esc_html__( 'Create Chart', 'visualizer' );
926 - if ( filter_input( INPUT_GET, 'action' ) === Visualizer_Plugin::ACTION_EDIT_CHART ) {
927 - $render->cancel_button = esc_html__( 'Cancel', 'visualizer' );
928 - }
929 - } else {
930 - $render->button = esc_attr__( 'Insert Chart', 'visualizer' );
931 - }
932 -
933 - do_action( 'visualizer_enqueue_scripts_and_styles', $data, $this->_chart->ID );
934 -
935 - if ( Visualizer_Module::is_pro() && Visualizer_Module::is_pro_older_than( '1.9.0' ) ) {
936 - global $Visualizer_Pro;
937 - $Visualizer_Pro->_enqueueScriptsAndStyles( $data, $this->_chart->ID );
938 - }
939 -
940 - $this->_addAction( 'admin_head', 'renderFlattrScript' );
941 - wp_iframe( array( $render, 'render' ) );
942 - }
943 -
944 - /**
945 256 * Handles chart type selection page.
946 257 *
947 258 * @since 1.0.0
948 259 *
@@ -949,179 +260,130 @@
949 260 * @access private
950 261 */
951 262 private function _handleTypesPage() {
952 263 // process post request
953 - if ( $_SERVER['REQUEST_METHOD'] === 'POST' && wp_verify_nonce( filter_input( INPUT_POST, 'nonce' ) ) ) {
264 + if ( $_SERVER['REQUEST_METHOD'] == 'POST' && Visualizer_Security::verifyNonce( filter_input( INPUT_POST, 'nonce' ) ) ) {
954 265 $type = filter_input( INPUT_POST, 'type' );
955 - $library = filter_input( INPUT_POST, 'chart-library' );
956 - if ( Visualizer_Module_Admin::checkChartStatus( $type ) ) {
957 - if ( empty( $library ) ) {
958 - // library cannot be empty.
959 - do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, 'Chart library empty while creating the chart! Aborting...', 'error', __FILE__, __LINE__ );
960 - return;
961 - }
962 -
266 + if ( in_array( $type, Visualizer_Plugin::getChartTypes() ) ) {
963 267 // save new chart type
964 268 update_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_CHART_TYPE, $type );
965 - update_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_CHART_LIBRARY, $library );
269 +
966 270 // if the chart has default data, update it with appropriate default data for new type
967 271 if ( filter_var( get_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_DEFAULT_DATA, true ), FILTER_VALIDATE_BOOLEAN ) ) {
968 272 $source = new Visualizer_Source_Csv( VISUALIZER_ABSPATH . DIRECTORY_SEPARATOR . 'samples' . DIRECTORY_SEPARATOR . $type . '.csv' );
969 273 $source->fetch();
970 - $this->_chart->post_content = $source->getData( get_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) );
274 +
275 + $this->_chart->post_content = $source->getData();
971 276 wp_update_post( $this->_chart->to_array() );
277 +
972 278 update_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
973 279 }
974 280
975 - Visualizer_Module_Utility::set_defaults( $this->_chart );
976 -
977 281 // redirect to next tab
978 - // changed by Ash/Upwork
979 - wp_redirect( esc_url_raw( add_query_arg( 'tab', 'settings' ) ) );
980 -
282 + wp_redirect( add_query_arg( 'tab', 'data' ) );
981 283 return;
982 284 }
983 285 }
984 - $render = new Visualizer_Render_Page_Types();
985 - $render->type = get_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_CHART_TYPE, true );
986 - $render->types = Visualizer_Module_Admin::_getChartTypesLocalized( false, false, false, 'types' );
286 +
287 + $render = new Visualizer_Render_Page_Types();
288 + $render->type = get_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_CHART_TYPE, true );
289 + $render->types = Visualizer_Plugin::getChartTypes();
987 290 $render->chart = $this->_chart;
291 +
988 292 wp_enqueue_style( 'visualizer-frame' );
989 293 wp_enqueue_script( 'visualizer-frame' );
990 - wp_iframe( array( $render, 'render' ) );
294 +
295 + wp_iframe( array( $render, 'render') );
991 296 }
992 297
993 298 /**
994 - * Renders flattr script in the iframe <head>
299 + * Handles chart data page.
995 300 *
996 - * @since 1.4.2
997 - * @action admin_head
301 + * @since 1.0.0
998 302 *
999 - * @access public
303 + * @access private
1000 304 */
1001 - public function renderFlattrScript() {
1002 - echo '';
1003 - }
305 + private function _handleDataPage() {
306 + $data = $this->_getChartArray();
1004 307
1005 - /**
1006 - * Processes the CSV that is sent in the request as a string.
1007 - *
1008 - * @since 3.2.0
1009 - */
1010 - private function handleCSVasString( $data, $editor_type ) {
1011 - $source = null;
308 + $render = new Visualizer_Render_Page_Data();
309 + $render->chart = $this->_chart;
310 + $render->type = $data['type'];
1012 311
1013 - switch ( $editor_type ) {
1014 - case 'text':
1015 - // data coming in from the text editor.
1016 - $tmpfile = tempnam( get_temp_dir(), Visualizer_Plugin::NAME );
1017 - $handle = fopen( $tmpfile, 'w' );
1018 - $values = preg_split( '/[\n\r]+/', stripslashes( trim( $data ) ) );
1019 - if ( $values ) {
1020 - foreach ( $values as $row ) {
1021 - if ( empty( $row ) ) {
1022 - continue;
1023 - }
1024 - $row = explode( ',', $row );
1025 - $row = array_map(
1026 - function( $r ) {
1027 - return '' === $r ? ' ' : $r;
1028 - },
1029 - $row
1030 - );
1031 - $row = implode( ',', $row );
1032 - // don't use fpucsv here because we need to just dump the data
1033 - // minus the empty rows
1034 - // because fputcsv needs to tokenize
1035 - // we can standardize the CSV enclosure here and replace all ' with "
1036 - // we can assume that if there are an even number of ' they should be changed to "
1037 - // but that will screw up words like fo'c'sle
1038 - // so here let's just assume ' will NOT be used for enclosures
1039 - fwrite( $handle, $row );
1040 - fwrite( $handle, PHP_EOL );
1041 - }
1042 - }
1043 - $source = new Visualizer_Source_Csv( $tmpfile );
1044 - fclose( $handle );
1045 - break;
1046 - case 'table':
1047 - // Import from Chart
1048 - // fall-through.
1049 - case 'excel':
1050 - // data coming in from the excel editor.
1051 - $source = apply_filters( 'visualizer_pro_handle_chart_data', $data, '' );
1052 - break;
1053 - }
1054 - return $source;
312 + unset( $data['settings']['width'], $data['settings']['height'] );
313 +
314 + wp_enqueue_style( 'visualizer-frame' );
315 + wp_enqueue_script( 'visualizer-render' );
316 + wp_localize_script( 'visualizer-render', 'visualizer', array(
317 + 'l10n' => array(
318 + 'remotecsv_prompt' => esc_html__( 'Please, enter the URL of CSV file:', Visualizer_Plugin::NAME ),
319 + 'invalid_source' => esc_html__( 'You have entered invalid URL. Please, insert proper URL.', Visualizer_Plugin::NAME ),
320 + ),
321 + 'charts' => array(
322 + 'canvas' => $data,
323 + ),
324 + ) );
325 +
326 + wp_iframe( array( $render, 'render') );
1055 327 }
1056 328
1057 329 /**
1058 - * Parses the data uploaded as an HTML table.
330 + * Handles chart settigns page.
1059 331 *
1060 - * @since 3.2.0
332 + * @since 1.0.0
1061 333 *
1062 334 * @access private
1063 335 */
1064 - private function handleTabularData() {
1065 - $csv = array();
1066 - // the datatable mentions the headers twice, so lets remove the duplicates.
1067 - $headers = array_unique( array_filter( $_POST['header'] ) );
1068 - $types = $_POST['type'];
336 + private function _handleSettingsPage() {
337 + if ( $_SERVER['REQUEST_METHOD'] == 'POST' && Visualizer_Security::verifyNonce( filter_input( INPUT_GET, 'nonce' ) ) ) {
338 + if ( $this->_chart->post_status == 'auto-draft' ) {
339 + $this->_chart->post_status = 'publish';
340 + wp_update_post( $this->_chart->to_array() );
341 + }
1069 342
1070 - // capture all the indexes that correspond to excluded columns.
1071 - $exclude = array();
1072 - $index = 0;
1073 - foreach ( $types as $type ) {
1074 - if ( empty( $type ) ) {
1075 - $exclude[] = $index;
1076 - }
1077 - $index++;
343 + update_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SETTINGS, $_POST );
344 +
345 + $render = new Visualizer_Render_Page_Send();
346 + $render->text = sprintf( '[visualizer id="%d"]', $this->_chart->ID );
347 +
348 + wp_iframe( array( $render, 'render') );
349 + return;
1078 350 }
1079 351
1080 - // when N headers are being renamed, the number of headers increases by N
1081 - // because of the way datatable duplicates header information
1082 - // so unset the headers that have been renamed.
1083 - if ( count( $headers ) !== count( $types ) ) {
1084 - $to = count( $headers );
1085 - for ( $i = count( $types ); $i < $to; $i++ ) {
1086 - unset( $headers[ $i + 1 ] );
1087 - }
352 + $data = $this->_getChartArray();
353 +
354 + $sidebar = '';
355 + $sidebar_class = 'Visualizer_Render_Sidebar_Type_' . ucfirst( $data['type'] );
356 + if ( class_exists( $sidebar_class, true ) ) {
357 + $sidebar = new $sidebar_class( $data['settings'] );
358 + $sidebar->__series = $data['series'];
359 + $sidebar->__data = $data['data'];
1088 360 }
1089 361
1090 - $columns = array();
1091 - for ( $i = 0; $i < count( $headers ); $i++ ) {
1092 - if ( ! isset( $_POST[ 'data' . $i ] ) ) {
1093 - continue;
1094 - }
1095 - $columns[ $i ] = $_POST[ 'data' . $i ];
1096 - }
362 + unset( $data['settings']['width'], $data['settings']['height'] );
1097 363
1098 - $csv[] = $headers;
1099 - $csv[] = $types;
1100 - for ( $j = 0; $j < count( $columns[0] ); $j++ ) {
1101 - $row = array();
1102 - for ( $i = 0; $i < count( $headers ); $i++ ) {
1103 - $row[] = sanitize_text_field( $columns[ $i ][ $j ] );
1104 - }
1105 - $csv[] = $row;
1106 - }
364 + wp_enqueue_style( 'wp-color-picker' );
365 + wp_enqueue_style( 'visualizer-frame' );
1107 366
1108 - $tmpfile = tempnam( get_temp_dir(), Visualizer_Plugin::NAME );
1109 - $handle = fopen( $tmpfile, 'w' );
367 + wp_enqueue_script( 'visualizer-preview' );
368 + wp_localize_script( 'visualizer-render', 'visualizer', array(
369 + 'charts' => array(
370 + 'canvas' => $data,
371 + ),
372 + ) );
1110 373
1111 - if ( $csv ) {
1112 - $index = 0;
1113 - foreach ( $csv as $row ) {
1114 - // remove all the cells corresponding to the excluded headers.
1115 - foreach ( $exclude as $j ) {
1116 - unset( $row[ $j ] );
1117 - }
1118 - fputcsv( $handle, $row );
1119 - }
374 + $render = new Visualizer_Render_Page_Settings();
375 +
376 + $render->sidebar = $sidebar;
377 + if ( filter_input( INPUT_GET, 'library', FILTER_VALIDATE_BOOLEAN ) ) {
378 + $render->button = filter_input( INPUT_GET, 'action' ) == Visualizer_Plugin::ACTION_EDIT_CHART
379 + ? esc_html__( 'Save Chart', Visualizer_Plugin::NAME )
380 + : esc_html__( 'Create Chart', Visualizer_Plugin::NAME );
381 + } else {
382 + $render->button = esc_attr__( 'Insert Chart', Visualizer_Plugin::NAME );
1120 383 }
1121 - $source = new Visualizer_Source_Csv( $tmpfile );
1122 - fclose( $handle );
1123 - return $source;
384 +
385 + wp_iframe( array( $render, 'render') );
1124 386 }
1125 387
1126 388 /**
1127 389 * Parses uploaded CSV file and saves new data for the chart.
@@ -1130,111 +392,34 @@
1130 392 *
1131 393 * @access public
1132 394 */
1133 395 public function uploadData() {
1134 - // if this is being called internally from pro and VISUALIZER_DO_NOT_DIE is set.
1135 - // otherwise, assume this is a normal web request.
1136 - $can_die = ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE );
1137 -
1138 396 // validate nonce
1139 - if ( ! isset( $_GET['nonce'] ) || ! wp_verify_nonce( $_GET['nonce'] ) ) {
1140 - if ( ! $can_die ) {
1141 - return;
1142 - }
397 + if ( !Visualizer_Security::verifyNonce( filter_input( INPUT_GET, 'nonce' ) ) ) {
1143 398 status_header( 403 );
1144 399 exit;
1145 400 }
1146 401
1147 402 // check chart, if chart exists
1148 - // do not use filter_input as it does not work for phpunit test cases, use filter_var instead
1149 - $chart_id = isset( $_GET['chart'] ) ? filter_var( $_GET['chart'], FILTER_VALIDATE_INT ) : '';
1150 - if ( ! $chart_id || ! ( $chart = get_post( $chart_id ) ) || $chart->post_type !== Visualizer_Plugin::CPT_VISUALIZER ) {
1151 - if ( ! $can_die ) {
1152 - return;
1153 - }
403 + $chart_id = filter_input( INPUT_GET, 'chart', FILTER_VALIDATE_INT );
404 + if ( !$chart_id || !( $chart = get_post( $chart_id ) ) || $chart->post_type != Visualizer_Plugin::CPT_VISUALIZER ) {
1154 405 status_header( 400 );
1155 406 exit;
1156 407 }
1157 408
1158 - do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( 'Uploading data for chart %d with POST = %s and GET = %s', $chart_id, print_r( $_POST, true ), print_r( $_GET, true ) ), 'debug', __FILE__, __LINE__ );
1159 -
1160 - if ( ! isset( $_POST['vz-import-time'] ) ) {
1161 - apply_filters( 'visualizer_pro_remove_schedule', $chart_id );
1162 - }
1163 -
1164 - if ( ! isset( $_POST['chart_data_src'] ) || Visualizer_Plugin::CF_SOURCE_FILTER !== $_POST['chart_data_src'] ) {
1165 - // delete the filters in case this chart is being uploaded from other data sources
1166 - delete_post_meta( $chart_id, Visualizer_Plugin::CF_FILTER_CONFIG );
1167 - delete_post_meta( $chart_id, '__transient-' . Visualizer_Plugin::CF_FILTER_CONFIG );
1168 - delete_post_meta( $chart_id, '__transient-' . Visualizer_Plugin::CF_DB_QUERY );
1169 -
1170 - // delete "import from db" specific parameters.
1171 - delete_post_meta( $chart_id, Visualizer_Plugin::CF_DB_QUERY );
1172 - delete_post_meta( $chart_id, Visualizer_Plugin::CF_DB_SCHEDULE );
1173 - delete_post_meta( $chart_id, Visualizer_Plugin::CF_REMOTE_DB_PARAMS );
1174 - }
1175 -
1176 - // delete json related data.
1177 - delete_post_meta( $chart_id, Visualizer_Plugin::CF_JSON_URL );
1178 - delete_post_meta( $chart_id, Visualizer_Plugin::CF_JSON_ROOT );
1179 - delete_post_meta( $chart_id, Visualizer_Plugin::CF_JSON_PAGING );
1180 - delete_post_meta( $chart_id, Visualizer_Plugin::CF_JSON_HEADERS );
1181 -
1182 - // delete last error
1183 - delete_post_meta( $chart_id, Visualizer_Plugin::CF_ERROR );
1184 -
1185 - // delete editor related data.
1186 - delete_post_meta( $chart_id, Visualizer_Plugin::CF_EDITOR );
1187 -
1188 - // delete this so that a JSON import can be later edited manually without a problem.
1189 - delete_post_meta( $chart_id, Visualizer_Plugin::CF_EDITABLE_TABLE );
1190 -
1191 409 $source = null;
1192 410 $render = new Visualizer_Render_Page_Update();
1193 -
1194 - $remote_data = false;
1195 - if ( isset( $_POST['remote_data'] ) && function_exists( 'wp_http_validate_url' ) ) {
1196 - $remote_data = wp_http_validate_url( $_POST['remote_data'] );
1197 - }
1198 - if ( false !== $remote_data ) {
1199 - $source = new Visualizer_Source_Csv_Remote( $remote_data );
1200 - if ( isset( $_POST['vz-import-time'] ) ) {
1201 - apply_filters( 'visualizer_pro_chart_schedule', $chart_id, $remote_data, $_POST['vz-import-time'] );
1202 - }
1203 - // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
411 + if ( filter_input( INPUT_POST, 'remote_data', FILTER_VALIDATE_URL ) ) {
412 + $source = new Visualizer_Source_Csv_Remote( $_POST['remote_data'] );
1204 413 } elseif ( isset( $_FILES['local_data'] ) && $_FILES['local_data']['error'] == 0 ) {
1205 - $source = new Visualizer_Source_Csv( $_FILES['local_data']['tmp_name'] );
1206 - } elseif ( isset( $_POST['chart_data'] ) && strlen( $_POST['chart_data'] ) > 0 ) {
1207 - $source = $this->handleCSVasString( $_POST['chart_data'], $_POST['editor-type'] );
1208 - update_post_meta( $chart_id, Visualizer_Plugin::CF_EDITOR, $_POST['editor-type'] );
1209 - } elseif ( isset( $_POST['table_data'] ) && 'yes' === $_POST['table_data'] ) {
1210 - $source = $this->handleTabularData();
1211 - update_post_meta( $chart_id, Visualizer_Plugin::CF_EDITOR, $_POST['editor-type'] );
1212 - } else {
1213 - 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__ );
1214 - $render->message = esc_html__( 'CSV file with chart data was not uploaded. Please try again.', 'visualizer' );
1215 - update_post_meta( $chart_id, Visualizer_Plugin::CF_ERROR, esc_html__( 'CSV file with chart data was not uploaded. Please try again.', 'visualizer' ) );
414 + $source = new Visualizer_Source_Csv( $_FILES['local_data']['tmp_name'] );
415 + } else {
416 + $render->message = esc_html__( "CSV file with chart data was not uploaded. Please, try again.", Visualizer_Plugin::NAME );
1216 417 }
1217 418
1218 - 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__ );
1219 -
1220 419 if ( $source ) {
1221 420 if ( $source->fetch() ) {
1222 - $content = $source->getData( get_post_meta( $chart_id, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) );
1223 - $populate = true;
1224 - if ( is_string( $content ) && is_array( unserialize( $content ) ) ) {
1225 - $json = unserialize( $content );
1226 - // if source exists, so should data. if source exists but data is blank, do not populate the chart.
1227 - // if we populate the data even if it is empty, the chart will show "Table has no columns".
1228 - if ( array_key_exists( 'source', $json ) && ! empty( $json['source'] ) && ( ! array_key_exists( 'data', $json ) || empty( $json['data'] ) ) ) {
1229 - 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__ );
1230 - update_post_meta( $chart_id, Visualizer_Plugin::CF_ERROR, sprintf( 'Not populating chart data as source exists (%s) but data is empty!', $json['source'] ) );
1231 - $populate = false;
1232 - }
1233 - }
1234 - if ( $populate ) {
1235 - $chart->post_content = $content;
1236 - }
421 + $chart->post_content = $source->getData();
1237 422 wp_update_post( $chart->to_array() );
1238 423
1239 424 update_post_meta( $chart->ID, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
1240 425 update_post_meta( $chart->ID, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() );
@@ -1239,44 +424,17 @@
1239 424 update_post_meta( $chart->ID, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
1240 425 update_post_meta( $chart->ID, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() );
1241 426 update_post_meta( $chart->ID, Visualizer_Plugin::CF_DEFAULT_DATA, 0 );
1242 427
1243 - do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( 'Updated post for chart %d', $chart_id ), 'debug', __FILE__, __LINE__ );
1244 -
1245 - Visualizer_Module_Utility::set_defaults( $chart, null );
1246 -
1247 - $settings = get_post_meta( $chart->ID, Visualizer_Plugin::CF_SETTINGS, true );
1248 - if ( isset( $settings['series'] ) && ! ( count( $settings['series'] ) - count( $source->getSeries() ) > 1 ) ) {
1249 - $diff_total_series = abs( count( $settings['series'] ) - count( $source->getSeries() ) );
1250 - if ( $diff_total_series ) {
1251 - foreach ( range( 1, $diff_total_series ) as $k => $diff_series ) {
1252 - $settings['series'][] = end( $settings['series'] );
1253 - }
1254 - update_post_meta( $chart->ID, Visualizer_Plugin::CF_SETTINGS, $settings );
1255 - }
1256 - }
1257 -
1258 - $render->id = $chart->ID;
1259 - $render->data = json_encode( $source->getRawData( get_post_meta( $chart->ID, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) ) );
428 + $render->data = json_encode( $source->getRawData() );
1260 429 $render->series = json_encode( $source->getSeries() );
1261 - $render->settings = json_encode( $settings );
1262 430 } else {
1263 - $error = $source->get_error();
1264 - if ( empty( $error ) ) {
1265 - $error = esc_html__( 'CSV file is broken or invalid. Please try again.', 'visualizer' );
1266 - }
1267 - $render->message = $error;
1268 - do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( '%s for chart %d.', $error, $chart_id ), 'error', __FILE__, __LINE__ );
1269 - update_post_meta( $chart_id, Visualizer_Plugin::CF_ERROR, $error );
431 + $render->message = esc_html__( "CSV file is broken or invalid. Please, try again.", Visualizer_Plugin::NAME );
1270 432 }
1271 - } else {
1272 - do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( 'Unknown internal error for chart %d.', $chart_id ), 'error', __FILE__, __LINE__ );
1273 433 }
434 +
1274 435 $render->render();
1275 - if ( ! $can_die ) {
1276 - return;
1277 - }
1278 - defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
436 + exit;
1279 437 }
1280 438
1281 439 /**
1282 440 * Clones the chart.
@@ -1286,327 +444,43 @@
1286 444 * @access public
1287 445 */
1288 446 public function cloneChart() {
1289 447 $chart_id = $success = false;
1290 - $nonce = isset( $_GET['nonce'] ) && wp_verify_nonce( $_GET['nonce'], Visualizer_Plugin::ACTION_CLONE_CHART );
1291 - $capable = current_user_can( 'edit_posts' );
448 + $nonce = Visualizer_Security::verifyNonce( filter_input( INPUT_GET, 'nonce' ), Visualizer_Plugin::ACTION_CLONE_CHART );
449 + $capable = current_user_can( 'edit_posts' );
1292 450 if ( $nonce && $capable ) {
1293 - $chart_id = isset( $_GET['chart'] ) ? filter_var( $_GET['chart'], FILTER_VALIDATE_INT ) : '';
451 + $chart_id = filter_input( INPUT_GET, 'chart', FILTER_VALIDATE_INT, array( 'options' => array( 'min_range' => 1 ) ) );
1294 452 if ( $chart_id ) {
1295 - $chart = get_post( $chart_id );
1296 - $success = $chart && $chart->post_type === Visualizer_Plugin::CPT_VISUALIZER;
453 + $chart = get_post( $chart_id );
454 + $success = $chart && $chart->post_type == Visualizer_Plugin::CPT_VISUALIZER;
1297 455 }
1298 456 }
1299 - $redirect = remove_query_arg( 'vaction', wp_get_referer() );
457 +
458 + $redirect = wp_get_referer();
1300 459 if ( $success ) {
1301 - $new_chart_id = wp_insert_post(
1302 - array(
1303 - 'post_type' => Visualizer_Plugin::CPT_VISUALIZER,
1304 - 'post_title' => 'Visualization',
1305 - 'post_author' => get_current_user_id(),
1306 - 'post_status' => $chart->post_status,
1307 - 'post_content' => $chart->post_content,
1308 - )
1309 - );
1310 - if ( is_wp_error( $new_chart_id ) ) {
1311 - do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( 'Error while cloning chart %d = %s', $chart_id, print_r( $new_chart_id, true ) ), 'error', __FILE__, __LINE__ );
1312 - } else {
1313 - $post_meta = get_post_meta( $chart_id );
1314 - foreach ( $post_meta as $key => $value ) {
1315 - if ( strpos( $key, 'visualizer-' ) !== false ) {
1316 - add_post_meta( $new_chart_id, $key, maybe_unserialize( $value[0] ) );
1317 - }
1318 - }
1319 - $redirect = esc_url(
1320 - add_query_arg(
1321 - array(
1322 - 'page' => 'visualizer',
1323 - 'type' => filter_input( INPUT_GET, 'type' ),
1324 - 'vaction' => false,
1325 - ),
1326 - admin_url( 'admin.php' )
1327 - ),
1328 - null,
1329 - 'db'
1330 - );
460 + $new_chart_id = wp_insert_post( array(
461 + 'post_type' => Visualizer_Plugin::CPT_VISUALIZER,
462 + 'post_title' => 'Visualization',
463 + 'post_author' => get_current_user_id(),
464 + 'post_status' => $chart->post_status,
465 + 'post_content' => $chart->post_content,
466 + ) );
467 +
468 + if ( $new_chart_id && !is_wp_error( $new_chart_id ) ) {
469 + add_post_meta( $new_chart_id, Visualizer_Plugin::CF_CHART_TYPE, get_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_TYPE, true ) );
470 + add_post_meta( $new_chart_id, Visualizer_Plugin::CF_DEFAULT_DATA, get_post_meta( $chart_id, Visualizer_Plugin::CF_DEFAULT_DATA, true ) );
471 + add_post_meta( $new_chart_id, Visualizer_Plugin::CF_SOURCE, get_post_meta( $chart_id, Visualizer_Plugin::CF_SOURCE, true ) );
472 + add_post_meta( $new_chart_id, Visualizer_Plugin::CF_SERIES, get_post_meta( $chart_id, Visualizer_Plugin::CF_SERIES, true ) );
473 + add_post_meta( $new_chart_id, Visualizer_Plugin::CF_SETTINGS, get_post_meta( $chart_id, Visualizer_Plugin::CF_SETTINGS, true ) );
474 +
475 + $redirect = add_query_arg( array(
476 + 'page' => 'visualizer',
477 + 'type' => filter_input( INPUT_GET, 'type' ),
478 + ), admin_url( 'upload.php' ) );
1331 479 }
1332 480 }
1333 481
1334 - if ( defined( 'WP_TESTS_DOMAIN' ) ) {
1335 - wp_die();
1336 - }
1337 482 wp_redirect( $redirect );
1338 483 exit;
1339 484 }
1340 485
1341 - /**
1342 - * Exports the chart data
1343 - *
1344 - * @since 1.0.0
1345 - *
1346 - * @access public
1347 - */
1348 - public function exportData() {
1349 - check_ajax_referer( Visualizer_Plugin::ACTION_EXPORT_DATA . Visualizer_Plugin::VERSION, 'security' );
1350 - $capable = current_user_can( 'edit_posts' );
1351 - if ( $capable ) {
1352 - $chart_id = isset( $_GET['chart'] ) ? filter_var(
1353 - $_GET['chart'],
1354 - FILTER_VALIDATE_INT,
1355 - array(
1356 - 'options' => array(
1357 - 'min_range' => 1,
1358 - ),
1359 - )
1360 - ) : '';
1361 - if ( $chart_id ) {
1362 - $data = $this->_getDataAs( $chart_id, 'csv' );
1363 - if ( $data ) {
1364 - echo wp_send_json_success( $data );
1365 - }
1366 - }
1367 - }
1368 -
1369 - defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1370 - }
1371 -
1372 - /**
1373 - * Handles chart data page.
1374 - *
1375 - * @since 1.0.0
1376 - *
1377 - * @access private
1378 - */
1379 - private function _handleDataPage() {
1380 - $data = $this->_getChartArray();
1381 - $render = new Visualizer_Render_Page_Data();
1382 - $render->chart = $this->_chart;
1383 - $render->type = $data['type'];
1384 -
1385 - if ( $data && $data['settings'] ) {
1386 - unset( $data['settings']['width'], $data['settings']['height'], $data['settings']['chartArea'] );
1387 - }
1388 - wp_enqueue_style( 'visualizer-frame' );
1389 - wp_enqueue_script( 'visualizer-render' );
1390 - wp_localize_script(
1391 - 'visualizer-render',
1392 - 'visualizer',
1393 - array(
1394 - 'l10n' => array(
1395 - 'invalid_source' => esc_html__( 'You have entered an invalid URL. Please provide a valid URL.', 'visualizer' ),
1396 - 'loading' => esc_html__( 'Loading...', 'visualizer' ),
1397 - ),
1398 - 'charts' => array(
1399 - 'canvas' => $data,
1400 - ),
1401 - )
1402 - );
1403 -
1404 - do_action( 'visualizer_enqueue_scripts_and_styles', $data, $this->_chart->ID );
1405 -
1406 - if ( Visualizer_Module::is_pro() && Visualizer_Module::is_pro_older_than( '1.9.0' ) ) {
1407 - global $Visualizer_Pro;
1408 - $Visualizer_Pro->_enqueueScriptsAndStyles( $data, $this->_chart->ID );
1409 - }
1410 -
1411 - // Added by Ash/Upwork
1412 - $this->_addAction( 'admin_head', 'renderFlattrScript' );
1413 - wp_iframe( array( $render, 'render' ) );
1414 - }
1415 -
1416 - /**
1417 - * Returns the data for the query.
1418 - *
1419 - * @access public
1420 - */
1421 - public function getQueryData() {
1422 - check_ajax_referer( Visualizer_Plugin::ACTION_FETCH_DB_DATA . Visualizer_Plugin::VERSION, 'security' );
1423 -
1424 - if ( ! current_user_can( 'administrator' ) ) {
1425 - wp_send_json_error( array( 'msg' => __( 'Action not allowed for this user.', 'visualizer' ) ) );
1426 - }
1427 -
1428 - $params = wp_parse_args( $_POST['params'] );
1429 - $chart_id = filter_var( $params['chart_id'], FILTER_VALIDATE_INT );
1430 -
1431 - $source = new Visualizer_Source_Query( stripslashes( $params['query'] ), $chart_id, $params );
1432 - $html = $source->fetch( true );
1433 - $error = $source->get_error();
1434 - if ( ! empty( $error ) ) {
1435 - wp_send_json_error( array( 'msg' => $error ) );
1436 - }
1437 - wp_send_json_success( array( 'table' => $html ) );
1438 - }
1439 -
1440 - /**
1441 - * Saves the query and the schedule.
1442 - *
1443 - * @access public
1444 - */
1445 - public function saveQuery() {
1446 - check_ajax_referer( Visualizer_Plugin::ACTION_SAVE_DB_QUERY . Visualizer_Plugin::VERSION, 'security' );
1447 -
1448 - $chart_id = filter_input(
1449 - INPUT_GET,
1450 - 'chart',
1451 - FILTER_VALIDATE_INT,
1452 - array(
1453 - 'options' => array(
1454 - 'min_range' => 1,
1455 - ),
1456 - )
1457 - );
1458 -
1459 - $hours = filter_input(
1460 - INPUT_POST,
1461 - 'refresh',
1462 - FILTER_VALIDATE_FLOAT,
1463 - array(
1464 - 'options' => array(
1465 - 'min_range' => -1,
1466 - 'max_range' => apply_filters( 'visualizer_is_business', false ) ? PHP_INT_MAX : -1,
1467 - ),
1468 - )
1469 - );
1470 -
1471 - if ( ! is_numeric( $hours ) ) {
1472 - $hours = -1;
1473 - }
1474 -
1475 - $render = new Visualizer_Render_Page_Update();
1476 - if ( $chart_id ) {
1477 - $params = wp_parse_args( $_POST['params'] );
1478 - $source = new Visualizer_Source_Query( stripslashes( $params['query'] ), $chart_id, $params );
1479 - $source->fetch( false );
1480 - $error = $source->get_error();
1481 - if ( empty( $error ) ) {
1482 - update_post_meta( $chart_id, Visualizer_Plugin::CF_DB_QUERY, stripslashes( $params['query'] ) );
1483 - update_post_meta( $chart_id, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() );
1484 - update_post_meta( $chart_id, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
1485 - update_post_meta( $chart_id, Visualizer_Plugin::CF_DB_SCHEDULE, $hours );
1486 - update_post_meta( $chart_id, Visualizer_Plugin::CF_DEFAULT_DATA, 0 );
1487 - if ( isset( $params['db_type'] ) && $params['db_type'] !== Visualizer_Plugin::WP_DB_NAME ) {
1488 - $remote_db_params = $params;
1489 - unset( $remote_db_params['query'] );
1490 - unset( $remote_db_params['chart_id'] );
1491 - update_post_meta( $chart_id, Visualizer_Plugin::CF_REMOTE_DB_PARAMS, $remote_db_params );
1492 - }
1493 -
1494 - $schedules = get_option( Visualizer_Plugin::CF_DB_SCHEDULE, array() );
1495 - $schedules[ $chart_id ] = time() + $hours * HOUR_IN_SECONDS;
1496 - update_option( Visualizer_Plugin::CF_DB_SCHEDULE, $schedules );
1497 -
1498 - wp_update_post(
1499 - array(
1500 - 'ID' => $chart_id,
1501 - 'post_content' => $source->getData( get_post_meta( $chart_id, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) ),
1502 - )
1503 - );
1504 - $render->data = json_encode( $source->getRawData( get_post_meta( $chart_id, Visualizer_Plugin::CF_EDITABLE_TABLE, true ) ) );
1505 - $render->series = json_encode( $source->getSeries() );
1506 - $render->id = $chart_id;
1507 - } else {
1508 - $render->message = $error;
1509 - }
1510 - }
1511 - $render->render();
1512 - if ( ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE ) ) {
1513 - defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1514 - }
1515 - }
1516 -
1517 -
1518 - /**
1519 - * Saves the filter query and the schedule.
1520 - *
1521 - * @access public
1522 - */
1523 - public function saveFilter() {
1524 - check_ajax_referer( Visualizer_Plugin::ACTION_SAVE_FILTER_QUERY . Visualizer_Plugin::VERSION, 'security' );
1525 -
1526 - $chart_id = filter_input(
1527 - INPUT_GET,
1528 - 'chart',
1529 - FILTER_VALIDATE_INT,
1530 - array(
1531 - 'options' => array(
1532 - 'min_range' => 1,
1533 - ),
1534 - )
1535 - );
1536 -
1537 - $hours = filter_input(
1538 - INPUT_POST,
1539 - 'refresh',
1540 - FILTER_VALIDATE_INT,
1541 - array(
1542 - 'options' => array(
1543 - 'min_range' => -1,
1544 - 'max_range' => apply_filters( 'visualizer_is_business', false ) ? PHP_INT_MAX : -1,
1545 - ),
1546 - )
1547 - );
1548 -
1549 - if ( 0 !== $hours && empty( $hours ) ) {
1550 - $hours = -1;
1551 - }
1552 -
1553 - do_action( 'visualizer_save_filter', $chart_id, $hours );
1554 -
1555 - if ( ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE ) ) {
1556 - defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
1557 - }
1558 - }
1559 -
1560 - /**
1561 - * Save chart image.
1562 - *
1563 - * @param string $base64_img Chart image.
1564 - * @param int $chart_id Chart ID.
1565 - * @param bool $save_attachment Save attachment.
1566 - * @return attachment ID
1567 - */
1568 - public function save_chart_image( $base64_img, $chart_id, $save_attachment = true ) {
1569 - // Delete old chart image.
1570 - $old_attachment_id = get_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_IMAGE, true );
1571 - if ( $old_attachment_id ) {
1572 - wp_delete_attachment( $old_attachment_id, true );
1573 - }
1574 -
1575 - if ( ! $save_attachment ) {
1576 - return 0;
1577 - }
1578 -
1579 - // Upload dir.
1580 - $upload_dir = wp_upload_dir();
1581 - $upload_path = str_replace( '/', DIRECTORY_SEPARATOR, $upload_dir['path'] ) . DIRECTORY_SEPARATOR;
1582 -
1583 - $img = str_replace( 'data:image/png;base64,', '', $base64_img );
1584 - $img = str_replace( ' ', '+', $img );
1585 - $decoded = base64_decode( $img );
1586 - $filename = 'visualization-' . $chart_id . '.png';
1587 - $file_type = 'image/png';
1588 - $hashed_filename = $filename;
1589 -
1590 - // Save the image in the uploads directory.
1591 - require_once ABSPATH . '/wp-admin/includes/file.php';
1592 - \WP_Filesystem();
1593 - global $wp_filesystem;
1594 - if ( ! is_a( $wp_filesystem, 'WP_Filesystem_Base' ) ) {
1595 - $creds = request_filesystem_credentials( site_url() );
1596 - wp_filesystem( $creds );
1597 - }
1598 - $upload_file = $wp_filesystem->put_contents( $upload_path . $hashed_filename, $decoded );
1599 -
1600 - // Insert new chart image.
1601 - $attachment = array(
1602 - 'post_mime_type' => $file_type,
1603 - 'post_title' => preg_replace( '/\.[^.]+$/', '', basename( $hashed_filename ) ),
1604 - 'post_content' => '',
1605 - 'post_status' => 'inherit',
1606 - 'guid' => $upload_dir['url'] . '/' . basename( $hashed_filename ),
1607 - );
1608 -
1609 - $attach_id = wp_insert_attachment( $attachment, $upload_dir['path'] . '/' . $hashed_filename );
1610 - return $attach_id;
1611 - }
1612 -}
486 +}