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