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