PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.4.4
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.4.4
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/Frontend.php +174 -35 3.1.23.4.4 View file →
@@ -68,11 +68,32 @@
68 68 add_filter( 'term_description', 'do_shortcode' );
69 69 }
70 70
71 71 add_action( 'rest_api_init', array( $this, 'endpoint_register' ) );
72 +
73 + $this->_addFilter( 'script_loader_tag', 'script_loader_tag', null, 10, 3 );
72 74 }
73 75
74 76 /**
77 + * Adds the async attribute to certain scripts.
78 + */
79 + function script_loader_tag( $tag, $handle, $src ) {
80 + if ( is_admin() ) {
81 + return $tag;
82 + }
83 +
84 + $scripts = array( 'google-jsapi-new', 'google-jsapi-old', 'visualizer-render-google-lib', 'visualizer-render-google' );
85 +
86 + foreach ( $scripts as $async ) {
87 + if ( $async === $handle ) {
88 + $tag = str_replace( ' src', ' defer="defer" src', $tag );
89 + break;
90 + }
91 + }
92 + return $tag;
93 + }
94 +
95 + /**
75 96 * Returns the language/locale.
76 97 */
77 98 function getLanguage( $dummy, $only_language ) {
78 99 return $this->get_language();
@@ -98,17 +119,42 @@
98 119 *
99 120 * @access private
100 121 */
101 122 private function get_actions() {
102 - return apply_filters(
123 + $actions = apply_filters(
103 124 'visualizer_action_buttons',
104 125 array(
105 - 'print' => __( 'Print', 'visualizer' ),
106 - 'csv' => __( 'CSV', 'visualizer' ),
107 - 'xls' => __( 'Excel', 'visualizer' ),
108 - 'copy' => __( 'Copy', 'visualizer' ),
126 + 'print' => array(
127 + 'label' => esc_html__( 'Print', 'visualizer' ),
128 + 'title' => esc_html__( 'Print Chart', 'visualizer' ),
129 + ),
130 + 'csv' => array(
131 + 'label' => esc_html__( 'CSV', 'visualizer' ),
132 + 'title' => esc_html__( 'Download as a CSV', 'visualizer' ),
133 + ),
134 + 'xls' => array(
135 + 'label' => esc_html__( 'Excel', 'visualizer' ),
136 + 'title' => esc_html__( 'Download as a spreadsheet', 'visualizer' ),
137 + ),
138 + 'copy' => array(
139 + 'label' => esc_html__( 'Copy', 'visualizer' ),
140 + 'title' => esc_html__( 'Copy data', 'visualizer' ),
141 + ),
142 + 'image' => array(
143 + 'label' => esc_html__( 'Download', 'visualizer' ),
144 + 'title' => esc_html__( 'Download as an image', 'visualizer' ),
145 + ),
109 146 )
110 147 );
148 +
149 + // backward compatibility before label and title attributes were introduced.
150 + if ( isset( $actions['edit'] ) && is_string( $actions['edit'] ) ) {
151 + $actions['edit'] = array(
152 + 'label' => esc_html__( 'Edit', 'visualizer' ),
153 + 'title' => esc_html__( 'Edit data', 'visualizer' ),
154 + );
155 + }
156 + return $actions;
111 157 }
112 158
113 159 /**
114 160 * The print button
@@ -139,8 +185,23 @@
139 185 break;
140 186 case 'xls':
141 187 $data = $this->_getDataAs( $chart_id, 'xls' );
142 188 break;
189 + case 'image':
190 + $settings = get_post_meta( $chart_id, Visualizer_Plugin::CF_SETTINGS, true );
191 + $title = 'visualizer#' . $chart_id;
192 + if ( ! empty( $settings['title'] ) ) {
193 + $title = $settings['title'];
194 + }
195 + // for ChartJS, title is an array.
196 + if ( is_array( $title ) && isset( $title['text'] ) ) {
197 + $title = $title['text'];
198 + }
199 + if ( empty( $title ) ) {
200 + $title = 'visualizer#' . $chart_id;
201 + }
202 + $data = array( 'name' => $title );
203 + break;
143 204 default:
144 205 $data = apply_filters( 'visualizer_action_data', $data, $chart_id, $type, $params, $this );
145 206 break;
146 207 }
@@ -189,9 +250,9 @@
189 250 $atts
190 251 );
191 252
192 253 // if empty id or chart does not exists, then return empty string
193 - if ( ! $atts['id'] || ! ( $chart = get_post( $atts['id'] ) ) || $chart->post_type != Visualizer_Plugin::CPT_VISUALIZER ) {
254 + if ( ! $atts['id'] || ! ( $chart = get_post( $atts['id'] ) ) || $chart->post_type !== Visualizer_Plugin::CPT_VISUALIZER ) {
194 255 return '';
195 256 }
196 257
197 258 if ( ! apply_filters( 'visualizer_pro_show_chart', true, $atts['id'] ) ) {
@@ -198,8 +259,9 @@
198 259 return '';
199 260 }
200 261
201 262 // in case revisions exist.
263 + // phpcs:ignore WordPress.CodeAnalysis.AssignmentInCondition.Found
202 264 if ( true === ( $revisions = $this->undoRevisions( $chart->ID, true ) ) ) {
203 265 $chart = get_post( $chart->ID );
204 266 }
205 267
@@ -230,9 +292,9 @@
230 292 $settings = apply_filters( $atts['settings'], $settings, $chart->ID, $type );
231 293 }
232 294
233 295 // handle data filter hooks
234 - $data = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_DATA, unserialize( html_entity_decode( $chart->post_content ) ), $chart->ID, $type );
296 + $data = self::get_chart_data( $chart, $type );
235 297 if ( ! empty( $atts['data'] ) ) {
236 298 $data = apply_filters( $atts['data'], $data, $chart->ID, $type );
237 299 }
238 300
@@ -244,8 +306,15 @@
244 306 }
245 307
246 308 $library = $this->load_chart_type( $chart->ID );
247 309
310 + $id = $id . '-' . rand();
311 +
312 + $amp = Visualizer_Plugin::instance()->getModule( Visualizer_Module_AMP::NAME );
313 + if ( $amp && $amp->is_amp() ) {
314 + return '<div id="' . $id . '"' . $class . '>' . $amp->get_chart( $chart, $data, $series, $settings ) . '</div>';
315 + }
316 +
248 317 // add chart to the array
249 318 $this->_charts[ $id ] = array(
250 319 'type' => $type,
251 320 'series' => $series,
@@ -253,33 +322,8 @@
253 322 'data' => $data,
254 323 'library' => $library,
255 324 );
256 325
257 - wp_register_script(
258 - "visualizer-render-$library",
259 - VISUALIZER_ABSURL . 'js/render-facade.js',
260 - apply_filters( 'visualizer_assets_render', array( 'jquery', 'visualizer-customization' ), true ),
261 - Visualizer_Plugin::VERSION,
262 - true
263 - );
264 -
265 - wp_enqueue_script( "visualizer-render-$library" );
266 - wp_localize_script(
267 - "visualizer-render-$library",
268 - 'visualizer',
269 - array(
270 - 'charts' => $this->_charts,
271 - 'language' => $this->get_language(),
272 - 'map_api_key' => get_option( 'visualizer-map-api-key' ),
273 - 'rest_url' => version_compare( $wp_version, '4.7.0', '>=' ) ? rest_url( 'visualizer/v' . VISUALIZER_REST_VERSION . '/action/#id#/#type#/' ) : '',
274 - 'i10n' => array(
275 - 'copied' => __( 'Copied!', 'visualizer' ),
276 - ),
277 - 'page_type' => 'frontend',
278 - )
279 - );
280 - wp_enqueue_style( 'visualizer-front' );
281 -
282 326 $actions_div = '';
283 327 $actions_visible = apply_filters( 'visualizer_pro_add_actions', isset( $settings['actions'] ) ? $settings['actions'] : array(), $atts['id'] );
284 328 if ( ! empty( $actions_visible ) ) {
285 329 $actions = $this->get_actions();
@@ -291,10 +335,11 @@
291 335 $array = explode( ';', $action_type );
292 336 $key = $array[0];
293 337 $mime = end( $array );
294 338 }
295 - $label = $actions[ $key ];
296 - $actions_div .= '<a href="#" class="visualizer-action visualizer-action-' . $key . '" data-visualizer-type="' . $key . '" data-visualizer-chart-id="' . $atts['id'] . '" data-visualizer-mime="' . $mime . '" title="' . $label . '" ';
339 + $label = $actions[ $key ]['label'];
340 + $title = $actions[ $key ]['title'];
341 + $actions_div .= sprintf( '<a href="#" class="visualizer-action visualizer-action-%s" data-visualizer-type="%s" data-visualizer-chart-id="%s" data-visualizer-container-id="%s" data-visualizer-mime="%s" title="%s"', $key, $key, $atts['id'], $id, $mime, $title );
297 342
298 343 if ( 'copy' === $key ) {
299 344 $copy = $this->_getDataAs( $atts['id'], 'csv' );
300 345 $actions_div .= ' data-clipboard-text="' . esc_attr( $copy['csv'] ) . '"';
@@ -309,8 +354,102 @@
309 354 }
310 355
311 356 $actions_div .= $css;
312 357
358 + foreach ( $this->_charts as $id => $attributes ) {
359 + $library = $attributes['library'];
360 + wp_register_script(
361 + "visualizer-render-$library",
362 + VISUALIZER_ABSURL . 'js/render-facade.js',
363 + apply_filters( 'visualizer_assets_render', array( 'jquery', 'visualizer-customization' ), true ),
364 + Visualizer_Plugin::VERSION,
365 + true
366 + );
367 +
368 + wp_enqueue_script( "visualizer-render-$library" );
369 + wp_localize_script(
370 + "visualizer-render-$library",
371 + 'visualizer',
372 + array(
373 + 'charts' => $this->_charts,
374 + 'language' => $this->get_language(),
375 + 'map_api_key' => get_option( 'visualizer-map-api-key' ),
376 + 'rest_url' => version_compare( $wp_version, '4.7.0', '>=' ) ? rest_url( 'visualizer/v' . VISUALIZER_REST_VERSION . '/action/#id#/#type#/' ) : '',
377 + 'i10n' => array(
378 + 'copied' => __( 'The data has been copied to your clipboard. Hit Ctrl-V/Cmd-V in your spreadsheet editor to paste the data.', 'visualizer' ),
379 + ),
380 + 'page_type' => 'frontend',
381 + 'is_front' => true,
382 + )
383 + );
384 + wp_enqueue_style( 'visualizer-front' );
385 + }
386 +
313 387 // return placeholder div
314 - return $actions_div . '<div id="' . $id . '"' . $class . '></div>';
388 + return $actions_div . '<div id="' . $id . '"' . $class . '></div>' . $this->addSchema( $chart->ID );
389 + }
390 +
391 + /**
392 + * Adds the schema corresponding to the dataset.
393 + *
394 + * @since 3.3.2
395 + *
396 + * @access private
397 + */
398 + private function addSchema( $id ) {
399 + // should we show informative errors as HTML comments?
400 + $show_errors = apply_filters( 'visualizer_schema_show_errors', true, $id );
401 +
402 + $settings = get_post_meta( $id, Visualizer_Plugin::CF_SETTINGS, true );
403 + $title = '';
404 + if ( isset( $settings['title'] ) && ! empty( $settings['title'] ) ) {
405 + $title = $settings['title'];
406 + if ( is_array( $title ) ) {
407 + $title = $settings['title']['text'];
408 + }
409 + }
410 + $title = apply_filters( 'visualizer_schema_name', $title, $id );
411 + if ( empty( $title ) ) {
412 + if ( $show_errors ) {
413 + return "<!-- Not showing structured data for chart $id because title is empty -->";
414 + }
415 + return '';
416 + }
417 +
418 + $desc = '';
419 + if ( isset( $settings['description'] ) && ! empty( $settings['description'] ) ) {
420 + $desc = $settings['description'];
421 + }
422 + $desc = apply_filters( 'visualizer_schema_description', $desc, $id );
423 + if ( empty( $desc ) ) {
424 + if ( $show_errors ) {
425 + return "<!-- Not showing structured data for chart $id because description is empty -->";
426 + }
427 + return '';
428 + }
429 +
430 + // descriptions below 50 chars are not allowed.
431 + if ( strlen( $desc ) < 50 ) {
432 + if ( $show_errors ) {
433 + return "<!-- Not showing structured data for chart $id because description is shorter than 50 characters -->";
434 + }
435 + return '';
436 + }
437 +
438 + $schema = apply_filters(
439 + 'visualizer_schema',
440 + '{
441 + "@context":"https://schema.org/",
442 + "@type":"Dataset",
443 + "name":"' . esc_html( $title ) . '",
444 + "description":"' . esc_html( $desc ) . '"
445 + }',
446 + $id
447 + );
448 +
449 + if ( empty( $schema ) ) {
450 + return '';
451 + }
452 +
453 + return '<script type="application/ld+json">' . $schema . '</script>';
315 454 }
316 455 }