PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.10.1
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.10.1
4.0.8 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 All 149 releases
← All changes | classes/Visualizer/Module/Admin.php +665 -93 3.0.83.10.1 View file →
@@ -52,26 +52,110 @@
52 52 public function __construct( Visualizer_Plugin $plugin ) {
53 53 parent::__construct( $plugin );
54 54 $this->_addAction( 'load-post.php', 'enqueueMediaScripts' );
55 55 $this->_addAction( 'load-post-new.php', 'enqueueMediaScripts' );
56 - $this->_addAction( 'admin_footer', 'renderTempaltes' );
57 - $this->_addAction( 'admin_enqueue_scripts', 'enqueueLibraryScripts', null, 8 );
56 + $this->_addAction( 'admin_footer', 'renderTemplates' );
57 + $this->_addAction( 'admin_enqueue_scripts', 'enqueueLibraryScripts', null, 0 );
58 58 $this->_addAction( 'admin_menu', 'registerAdminMenu' );
59 59 $this->_addFilter( 'media_view_strings', 'setupMediaViewStrings' );
60 60 $this->_addFilter( 'plugin_action_links', 'getPluginActionLinks', 10, 2 );
61 + $this->_addFilter( 'plugin_row_meta', 'getPluginMetaLinks', 10, 2 );
61 62 $this->_addFilter( 'visualizer_logger_data', 'getLoggerData' );
62 - $this->_addFilter( 'visualizer_get_chart_counts', 'getChartCountsByTypeAndMeta' );
63 63 $this->_addFilter( 'visualizer_feedback_review_trigger', 'feedbackReviewTrigger' );
64 64
65 + // screen pagination
66 + $this->_addFilter( 'set-screen-option', 'setScreenOptions', 10, 3 );
67 +
65 68 // revision support.
66 69 $this->_addFilter( 'wp_revisions_to_keep', 'limitRevisions', null, 10, 2 );
67 70 $this->_addAction( '_wp_put_post_revision', 'addRevision', null, 10, 1 );
68 71 $this->_addAction( 'wp_restore_post_revision', 'restoreRevision', null, 10, 2 );
69 72
73 + $this->_addAction( 'visualizer_chart_schedules_spl', 'addSplChartSchedules', null, 10, 3 );
74 +
70 75 $this->_addAction( 'admin_init', 'init' );
76 +
77 + $this->_addAction( 'visualizer_chart_languages', 'addMultilingualSupport' );
78 +
79 + if ( defined( 'TI_CYPRESS_TESTING' ) ) {
80 + $this->load_cypress_hooks();
81 + }
82 +
71 83 }
72 84
73 85 /**
86 + * Define the hooks that are needed for cypress.
87 + *
88 + * @since 3.4.0
89 + * @access private
90 + */
91 + private function load_cypress_hooks() {
92 + // all charts should load on the same page without pagination.
93 + add_filter(
94 + 'visualizer_query_args', function( $args ) {
95 + $args['posts_per_page'] = 20;
96 + return $args;
97 + }, 10, 1
98 + );
99 + }
100 +
101 + /**
102 + * Add disabled `optgroup` schedules to the drop downs.
103 + *
104 + * @since ?
105 + *
106 + * @access public
107 + *
108 + * @param string $feature The feature for which to add schedules.
109 + * @param int $chart_id The chart ID.
110 + * @param int $plan The plan number.
111 + */
112 + public function addSplChartSchedules( $feature, $chart_id, $plan ) {
113 + if ( apply_filters( 'visualizer_is_business', false ) ) {
114 + return;
115 + }
116 +
117 + $license = __( 'PRO', 'visualizer' );
118 + if ( Visualizer_Module::is_pro() ) {
119 + switch ( $plan ) {
120 + case 1:
121 + $license = __( 'Developer', 'visualizer' );
122 + break;
123 + }
124 + }
125 +
126 + $hours = array(
127 + '0' => __( 'Live', 'visualizer' ),
128 + '1' => __( 'Each hour', 'visualizer' ),
129 + '12' => __( 'Each 12 hours', 'visualizer' ),
130 + '24' => __( 'Each day', 'visualizer' ),
131 + '72' => __( 'Each 3 days', 'visualizer' ),
132 + );
133 +
134 + switch ( $feature ) {
135 + case 'json':
136 + case 'csv':
137 + // no more schedules if pro is already active.
138 + if ( Visualizer_Module::is_pro() ) {
139 + return;
140 + }
141 + break;
142 + case 'wp':
143 + // fall-through.
144 + case 'db':
145 + break;
146 + default:
147 + return;
148 + }
149 +
150 + echo '<optgroup disabled label="' . sprintf( __( 'More in the %s version', 'visualizer' ), $license ) . '">';
151 + foreach ( $hours as $hour => $desc ) {
152 + echo '<option disabled>' . $desc . '</option>';
153 + }
154 + echo '</optgroup>';
155 + }
156 +
157 + /**
74 158 * No limits on revisions.
75 159 */
76 160 public function limitRevisions( $num, $post ) {
77 161 if ( Visualizer_Plugin::CPT_VISUALIZER === $post->post_type ) {
@@ -132,16 +216,31 @@
132 216 *
133 217 * @access public
134 218 */
135 219 public function init() {
220 + // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
136 221 if ( current_user_can( 'edit_posts' ) && current_user_can( 'edit_pages' ) && 'true' == get_user_option( 'rich_editing' ) ) {
137 222 $this->_addFilter( 'mce_external_languages', 'add_tinymce_lang', 10, 1 );
138 223 $this->_addFilter( 'mce_external_plugins', 'tinymce_plugin', 10, 1 );
139 224 $this->_addFilter( 'mce_buttons', 'register_mce_button', 10, 1 );
225 + $this->_addFilter( 'tiny_mce_before_init', 'get_strings_for_block', 10, 1 );
140 226 }
141 227 }
142 228
143 229 /**
230 + * Add the strings required for the TinyMCE buttons for the classic block (not the classic editor).
231 + *
232 + * @since ?
233 + * @access friendly
234 + */
235 + function get_strings_for_block( $settings ) {
236 + $class = new Visualizer_Module_Language();
237 + $strings = $class->get_strings();
238 + $array = array( 'visualizer_tinymce_plugin' => json_encode( $strings ) );
239 + return array_merge( $settings, $array );
240 + }
241 +
242 + /**
144 243 * Load plugin translation for - TinyMCE API
145 244 *
146 245 * @access public
147 246 * @param array $arr The tinymce_lang array.
@@ -212,16 +311,23 @@
212 311 public function enqueueMediaScripts() {
213 312 global $typenow;
214 313 if ( post_type_supports( $typenow, 'editor' ) ) {
215 314 wp_enqueue_style( 'visualizer-media', VISUALIZER_ABSURL . 'css/media.css', array( 'media-views' ), Visualizer_Plugin::VERSION );
216 - wp_enqueue_script( 'visualizer-google-jsapi-new', '//www.gstatic.com/charts/loader.js', array( 'media-editor' ), null, true );
217 - wp_enqueue_script( 'visualizer-google-jsapi-old', '//www.google.com/jsapi', array( 'visualizer-google-jsapi-new' ), null, true );
218 - wp_enqueue_script( 'visualizer-media-model', VISUALIZER_ABSURL . 'js/media/model.js', array( 'visualizer-google-jsapi-old' ), Visualizer_Plugin::VERSION, true );
315 +
316 + // Load all the assets for the different libraries we support.
317 + $deps = array(
318 + Visualizer_Render_Sidebar_Google::enqueue_assets( array( 'media-editor' ) ),
319 + Visualizer_Render_Sidebar_Type_DataTable_Tabular::enqueue_assets( array( 'media-editor' ) ),
320 + );
321 +
322 + wp_enqueue_script( 'visualizer-media-model', VISUALIZER_ABSURL . 'js/media/model.js', $deps, Visualizer_Plugin::VERSION, true );
219 323 wp_enqueue_script( 'visualizer-media-collection', VISUALIZER_ABSURL . 'js/media/collection.js', array( 'visualizer-media-model' ), Visualizer_Plugin::VERSION, true );
220 324 wp_enqueue_script( 'visualizer-media-controller', VISUALIZER_ABSURL . 'js/media/controller.js', array( 'visualizer-media-collection' ), Visualizer_Plugin::VERSION, true );
221 325 wp_enqueue_script( 'visualizer-media-view', VISUALIZER_ABSURL . 'js/media/view.js', array( 'visualizer-media-controller' ), Visualizer_Plugin::VERSION, true );
222 326 wp_localize_script(
223 - 'visualizer-media-view', 'visualizer', array(
327 + 'visualizer-media-view',
328 + 'visualizer',
329 + array(
224 330 'i10n' => array(
225 331 'insert' => __( 'Insert', 'visualizer' ),
226 332 ),
227 333 )
@@ -260,9 +366,9 @@
260 366 'filters' => $chart_types,
261 367 'types' => array_keys( $chart_types ),
262 368 ),
263 369 'nonce' => wp_create_nonce(),
264 - 'buildurl' => add_query_arg( 'action', Visualizer_Plugin::ACTION_CREATE_CHART, admin_url( 'admin-ajax.php' ) ),
370 + 'buildurl' => esc_url( add_query_arg( 'action', Visualizer_Plugin::ACTION_CREATE_CHART, admin_url( 'admin-ajax.php' ) ) ),
265 371 );
266 372
267 373 return $strings;
268 374 }
@@ -275,9 +381,9 @@
275 381 * @static
276 382 * @access private
277 383 * @return array The associated array of chart types with localized names.
278 384 */
279 - public static function _getChartTypesLocalized( $enabledOnly = false, $get2Darray = false, $add_select = false ) {
385 + public static function _getChartTypesLocalized( $enabledOnly = false, $get2Darray = false, $add_select = false, $where = null ) {
280 386 $additional = array();
281 387 if ( $add_select ) {
282 388 $additional['select'] = array(
283 389 'name' => esc_html__( 'All', 'visualizer' ),
@@ -284,59 +390,91 @@
284 390 'enabled' => true,
285 391 );
286 392 }
287 393
394 + $enabled = self::proFeaturesLocked();
395 +
288 396 $types = array_merge(
289 - $additional, array(
397 + $additional,
398 + array(
399 + 'tabular' => array(
400 + 'name' => esc_html__( 'Table', 'visualizer' ),
401 + 'enabled' => true,
402 + 'supports' => $enabled ? array( 'Google Charts', 'DataTable' ) : array( 'DataTable' ),
403 + ),
290 404 'pie' => array(
291 - 'name' => esc_html__( 'Pie', 'visualizer' ),
405 + 'name' => esc_html__( 'Pie/Donut', 'visualizer' ),
292 406 'enabled' => true,
407 + 'supports' => $enabled ? array( 'Google Charts', 'ChartJS' ) : array( 'Google Charts' ),
293 408 ),
294 409 'line' => array(
295 410 'name' => esc_html__( 'Line', 'visualizer' ),
296 411 'enabled' => true,
412 + 'supports' => $enabled ? array( 'Google Charts', 'ChartJS' ) : array( 'Google Charts' ),
297 413 ),
414 + 'bar' => array(
415 + 'name' => esc_html__( 'Bar', 'visualizer' ),
416 + 'enabled' => true,
417 + 'supports' => $enabled ? array( 'Google Charts', 'ChartJS' ) : array( 'Google Charts' ),
418 + ),
298 419 'area' => array(
299 420 'name' => esc_html__( 'Area', 'visualizer' ),
300 - 'enabled' => true,
421 + 'enabled' => $enabled,
422 + // in ChartJS, the fill option is used to make Line chart an area: https://www.chartjs.org/docs/latest/charts/area.html
423 + 'supports' => array( 'Google Charts' ),
301 424 ),
302 425 'geo' => array(
303 426 'name' => esc_html__( 'Geo', 'visualizer' ),
304 - 'enabled' => true,
427 + 'enabled' => $enabled,
428 + 'supports' => array( 'Google Charts' ),
305 429 ),
306 - 'bar' => array(
307 - 'name' => esc_html__( 'Bar', 'visualizer' ),
308 - 'enabled' => true,
309 - ),
310 430 'column' => array(
311 431 'name' => esc_html__( 'Column', 'visualizer' ),
312 - 'enabled' => true,
432 + 'enabled' => $enabled,
433 + 'supports' => array( 'Google Charts', 'ChartJS' ),
313 434 ),
314 - 'gauge' => array(
315 - 'name' => esc_html__( 'Gauge', 'visualizer' ),
316 - 'enabled' => true,
435 + 'bubble' => array(
436 + 'name' => esc_html__( 'Bubble', 'visualizer' ),
437 + 'enabled' => $enabled,
438 + // chartjs' bubble is ugly looking (and it won't work off the default bubble.csv) so it is being excluded for the time being.
439 + 'supports' => array( 'Google Charts' ),
317 440 ),
318 441 'scatter' => array(
319 442 'name' => esc_html__( 'Scatter', 'visualizer' ),
320 - 'enabled' => true,
443 + 'enabled' => $enabled,
444 + 'supports' => array( 'Google Charts' ),
321 445 ),
446 + 'gauge' => array(
447 + 'name' => esc_html__( 'Gauge', 'visualizer' ),
448 + 'enabled' => $enabled,
449 + 'supports' => array( 'Google Charts' ),
450 + ),
322 451 'candlestick' => array(
323 452 'name' => esc_html__( 'Candlestick', 'visualizer' ),
324 - 'enabled' => true,
453 + 'enabled' => $enabled,
454 + 'supports' => array( 'Google Charts' ),
325 455 ),
326 456 // pro types
327 - 'table' => array(
328 - 'name' => esc_html__( 'Table', 'visualizer' ),
329 - 'enabled' => false,
330 - ),
331 457 'timeline' => array(
332 458 'name' => esc_html__( 'Timeline', 'visualizer' ),
333 459 'enabled' => false,
460 + 'supports' => array( 'Google Charts', 'ChartJS' ),
334 461 ),
335 462 'combo' => array(
336 463 'name' => esc_html__( 'Combo', 'visualizer' ),
337 464 'enabled' => false,
465 + 'supports' => array( 'Google Charts' ),
338 466 ),
467 + 'polarArea' => array(
468 + 'name' => esc_html__( 'Polar Area', 'visualizer' ),
469 + 'enabled' => false,
470 + 'supports' => array( 'ChartJS' ),
471 + ),
472 + 'radar' => array(
473 + 'name' => esc_html__( 'Radar/Spider', 'visualizer' ),
474 + 'enabled' => false,
475 + 'supports' => array( 'ChartJS' ),
476 + ),
339 477 )
340 478 );
341 479 $types = apply_filters( 'visualizer_pro_chart_types', $types );
342 480 if ( $enabledOnly ) {
@@ -345,8 +483,12 @@
345 483 if ( ! is_array( $array ) ) {
346 484 // support for old pro
347 485 $array = array( 'enabled' => true, 'name' => $array );
348 486 }
487 + // backward compatibility for PRO before v1.9.0
488 + if ( ! array_key_exists( 'supports', $array ) ) {
489 + $array['supports'] = array( 'Google Charts' );
490 + }
349 491 if ( ! $array['enabled'] ) {
350 492 continue;
351 493 }
352 494 $filtered[ $type ] = $array;
@@ -359,13 +501,74 @@
359 501 if ( ! is_array( $array ) ) {
360 502 // support for old pro
361 503 $array = array( 'enabled' => true, 'name' => $array );
362 504 }
505 + // backward compatibility for PRO before v1.9.0
506 + if ( ! array_key_exists( 'supports', $array ) ) {
507 + $array['supports'] = array( 'Google Charts' );
508 + }
363 509 $doubleD[ $type ] = $array['name'];
364 510 }
365 511 $types = $doubleD;
366 512 }
367 513
514 + return self::handleDeprecatedCharts( $types, $enabledOnly, $get2Darray, $where );
515 + }
516 +
517 + /**
518 + * Handle (soon-to-be) deprecated charts.
519 + */
520 + private static function handleDeprecatedCharts( $types, $enabledOnly, $get2Darray, $where ) {
521 + $deprecated = array();
522 +
523 + switch ( $where ) {
524 + case 'types':
525 + // fall-through
526 + case 'library':
527 + // if a user has a Gauge/Candlestick chart, then let them keep using it.
528 + if ( ! Visualizer_Module::is_pro() ) {
529 + if ( ! self::hasChartType( 'gauge' ) ) {
530 + if ( $get2Darray ) {
531 + $deprecated[] = 'gauge';
532 + } else {
533 + $types['gauge']['enabled'] = false;
534 + }
535 + }
536 + if ( ! self::hasChartType( 'candlestick' ) ) {
537 + if ( $get2Darray ) {
538 + $deprecated[] = 'candlestick';
539 + } else {
540 + $types['candlestick']['enabled'] = false;
541 + }
542 + }
543 + }
544 + break;
545 + default:
546 + // if a user has a Gauge/Candlestick chart, then let them keep using it.
547 + if ( ! Visualizer_Module::is_pro() ) {
548 + if ( ! self::hasChartType( 'gauge' ) ) {
549 + if ( $get2Darray ) {
550 + $deprecated[] = 'gauge';
551 + } else {
552 + $types['gauge']['enabled'] = false;
553 + }
554 + }
555 + if ( ! self::hasChartType( 'candlestick' ) ) {
556 + if ( $get2Darray ) {
557 + $deprecated[] = 'candlestick';
558 + } else {
559 + $types['candlestick']['enabled'] = false;
560 + }
561 + }
562 + }
563 + }
564 +
565 + if ( $deprecated ) {
566 + foreach ( $deprecated as $type ) {
567 + unset( $types[ $type ] );
568 + }
569 + }
570 +
368 571 return $types;
369 572 }
370 573
371 574 /**
@@ -375,11 +578,11 @@
375 578 * @global string $pagenow The name of the current page.
376 579 *
377 580 * @access public
378 581 */
379 - public function renderTempaltes() {
582 + public function renderTemplates() {
380 583 global $pagenow;
381 - if ( 'post.php' != $pagenow && 'post-new.php' != $pagenow ) {
584 + if ( 'post.php' !== $pagenow && 'post-new.php' !== $pagenow ) {
382 585 return;
383 586 }
384 587 $render = new Visualizer_Render_Templates();
385 588 $render->render();
@@ -397,26 +600,41 @@
397 600 *
398 601 * @param string $suffix The current page suffix.
399 602 */
400 603 public function enqueueLibraryScripts( $suffix ) {
401 - if ( $suffix == $this->_libraryPage ) {
604 + if ( $suffix === $this->_libraryPage ) {
402 605 wp_enqueue_style( 'visualizer-library', VISUALIZER_ABSURL . 'css/library.css', array(), Visualizer_Plugin::VERSION );
403 606 $this->_addFilter( 'media_upload_tabs', 'setupVisualizerTab' );
404 607 wp_enqueue_media();
405 608 wp_enqueue_script(
406 - 'visualizer-library', VISUALIZER_ABSURL . 'js/library.js', array(
609 + 'visualizer-library',
610 + VISUALIZER_ABSURL . 'js/library.js',
611 + array(
407 612 'jquery',
408 613 'media-views',
409 - ), Visualizer_Plugin::VERSION, true
614 + 'clipboard',
615 + ),
616 + Visualizer_Plugin::VERSION,
617 + true
410 618 );
411 - wp_enqueue_script( 'google-jsapi-new', '//www.gstatic.com/charts/loader.js', array(), null, true );
412 - wp_enqueue_script( 'google-jsapi-old', '//www.google.com/jsapi', array( 'google-jsapi-new' ), null, true );
413 - wp_enqueue_script(
414 - 'visualizer-render', VISUALIZER_ABSURL . 'js/render.js', array(
415 - 'google-jsapi-old',
416 - 'visualizer-library',
417 - ), Visualizer_Plugin::VERSION, true
418 - );
619 +
620 + wp_enqueue_script( 'visualizer-customization', $this->get_user_customization_js(), array(), null, true );
621 +
622 + $query = $this->getQuery();
623 + while ( $query->have_posts() ) {
624 + $chart = $query->next_post();
625 + $library = $this->load_chart_type( $chart->ID );
626 + if ( is_null( $library ) ) {
627 + continue;
628 + }
629 + wp_enqueue_script(
630 + "visualizer-render-$library",
631 + VISUALIZER_ABSURL . 'js/render-facade.js',
632 + apply_filters( 'visualizer_assets_render', array( 'visualizer-library', 'visualizer-customization' ), true ),
633 + Visualizer_Plugin::VERSION,
634 + true
635 + );
636 + }
419 637 }
420 638 }
421 639
422 640 /**
@@ -443,24 +661,201 @@
443 661 *
444 662 * @access public
445 663 */
446 664 public function registerAdminMenu() {
447 - $title = esc_html__( 'Visualizer Library', 'visualizer' );
448 - $callback = array( $this, 'renderLibraryPage' );
449 - $this->_libraryPage = add_submenu_page( 'upload.php', $title, $title, 'edit_posts', Visualizer_Plugin::NAME, $callback );
665 + $svg_base64_icon = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iNzdweCIgaGVpZ2h0PSI3N3B4IiB2aWV3Qm94PSIwIDAgNzcgNzciIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICA8IS0tIEdlbmVyYXRvcjogU2tldGNoIDUyLjYgKDY3NDkxKSAtIGh0dHA6Ly93d3cuYm9oZW1pYW5jb2RpbmcuY29tL3NrZXRjaCAtLT4KICAgIDx0aXRsZT5Db21iaW5lZCBTaGFwZTwvdGl0bGU+CiAgICA8ZGVzYz5DcmVhdGVkIHdpdGggU2tldGNoLjwvZGVzYz4KICAgIDxnIGlkPSJQcm9kdWN0LVBhZ2UiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPgogICAgICAgIDxnIGlkPSJXb3JkUHJlc3MtcGx1Z2lucyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTE5MC4wMDAwMDAsIC00MzUuMDAwMDAwKSIgZmlsbD0iIzM5QzNEMiI+CiAgICAgICAgICAgIDxwYXRoIGQ9Ik0yMjguNSw1MTIgQzIwNy4yMzcwMzcsNTEyIDE5MCw0OTQuNzYyOTYzIDE5MCw0NzMuNSBDMTkwLDQ1Mi4yMzcwMzcgMjA3LjIzNzAzNyw0MzUgMjI4LjUsNDM1IEMyNDkuNzYyOTYzLDQzNSAyNjcsNDUyLjIzNzAzNyAyNjcsNDczLjUgQzI2Nyw0OTQuNzYyOTYzIDI0OS43NjI5NjMsNTEyIDIyOC41LDUxMiBaIE0yNDYuODQzNzUsNDgzLjU5MjA1OSBMMjE1LjYyNSw0ODMuNTkyMDU5IEwyMTUuNjI1LDQ2MC44MjY1NDQgQzIxNS42MjUsNDYwLjE2NDU0NyAyMTUuMTA3NTc4LDQ1OS42MjgzNTkgMjE0LjQ2ODc1LDQ1OS42MjgzNTkgTDIxMi4xNTYyNSw0NTkuNjI4MzU5IEMyMTEuNTE3NDIyLDQ1OS42MjgzNTkgMjExLDQ2MC4xNjQ1NDcgMjExLDQ2MC44MjY1NDQgTDIxMSw0ODUuOTg4NDI5IEMyMTEsNDg3LjMxMTY3NCAyMTIuMDM1NTY2LDQ4OC4zODQ3OTggMjEzLjMxMjUsNDg4LjM4NDc5OCBMMjQ2Ljg0Mzc1LDQ4OC4zODQ3OTggQzI0Ny40ODI1NzgsNDg4LjM4NDc5OCAyNDgsNDg3Ljg0ODYxMSAyNDgsNDg3LjE4NjYxMyBMMjQ4LDQ4NC43OTAyNDQgQzI0OCw0ODQuMTI4MjQ2IDI0Ny40ODI1NzgsNDgzLjU5MjA1OSAyNDYuODQzNzUsNDgzLjU5MjA1OSBaIE0yNDQuNTMxMjUsNDYyLjAyNDcyOSBMMjM1Ljk5OTU3LDQ2Mi4wMjQ3MjkgQzIzNC40NTQ1MzEsNDYyLjAyNDcyOSAyMzMuNjgwNTY2LDQ2My45NjA1NDcgMjM0Ljc3MzIyMyw0NjUuMDkyODMyIEwyMzcuMTE0NjI5LDQ2Ny41MTkxNTYgTDIzMS44MTI1LDQ3My4wMTQzMzIgTDIyNi41MTAzNzEsNDY3LjUxOTkwNSBDMjI1LjYwNzA1MSw0NjYuNTgzODIzIDIyNC4xNDI5NDksNDY2LjU4MzgyMyAyMjMuMjQwMzUyLDQ2Ny41MTk5MDUgTDIxOC4yNzY0MjYsNDcyLjY2Mzg2MyBDMjE3LjgyNDc2Niw0NzMuMTMxOTA0IDIxNy44MjQ3NjYsNDczLjg5MDUwNSAyMTguMjc2NDI2LDQ3NC4zNTg1NDYgTDIxOS45MTEwNzQsNDc2LjA1MjQ4IEMyMjAuMzYyNzM0LDQ3Ni41MjA1MjEgMjIxLjA5NDc4NSw0NzYuNTIwNTIxIDIyMS41NDY0NDUsNDc2LjA1MjQ4IEwyMjQuODc1LDQ3Mi42MDI0NTYgTDIzMC4xNzcxMjksNDc4LjA5Njg4MyBDMjMxLjA4MDQ0OSw0NzkuMDMyOTY1IDIzMi41NDQ1NTEsNDc5LjAzMjk2NSAyMzMuNDQ3MTQ4LDQ3OC4wOTY4ODMgTDI0MC4zODQ2NDgsNDcwLjkwNzc3MyBMMjQyLjcyNjA1NSw0NzMuMzM0MDk4IEMyNDMuODE4NzExLDQ3NC40NjYzODIgMjQ1LjY4Njc3Nyw0NzMuNjY0MzQ3IDI0NS42ODY3NzcsNDcyLjA2MzI3MyBMMjQ1LjY4Njc3Nyw0NjMuMjIyOTE0IEMyNDUuNjg3NSw0NjIuNTYwOTE3IDI0NS4xNzAwNzgsNDYyLjAyNDcyOSAyNDQuNTMxMjUsNDYyLjAyNDcyOSBaIiBpZD0iQ29tYmluZWQtU2hhcGUiPjwvcGF0aD4KICAgICAgICA8L2c+CiAgICA8L2c+Cjwvc3ZnPg==';
666 +
667 + $this->_libraryPage = add_menu_page( __( 'Visualizer', 'visualizer' ), __( 'Visualizer', 'visualizer' ), 'edit_posts', Visualizer_Plugin::NAME, array( $this, 'renderLibraryPage' ), $svg_base64_icon, 99.7666 );
668 +
669 + add_submenu_page(
670 + Visualizer_Plugin::NAME,
671 + __( 'Chart Library', 'visualizer' ),
672 + __( 'Chart Library', 'visualizer' ),
673 + 'edit_posts',
674 + admin_url( 'admin.php?page=' . Visualizer_Plugin::NAME )
675 + );
676 + add_submenu_page(
677 + Visualizer_Plugin::NAME,
678 + __( 'Add New Chart', 'visualizer' ),
679 + __( 'Add New Chart', 'visualizer' ),
680 + 'edit_posts',
681 + admin_url( 'admin.php?page=' . Visualizer_Plugin::NAME . '&vaction=addnew' )
682 + );
683 + add_submenu_page(
684 + Visualizer_Plugin::NAME,
685 + __( 'Support', 'visualizer' ),
686 + __( 'Support', 'visualizer' ) . '<span class="dashicons dashicons-editor-help more-features-icon" style="width: 17px; height: 17px; margin-left: 4px; color: #ffca54; font-size: 17px; vertical-align: -3px;"></span>',
687 + 'edit_posts',
688 + 'viz-support',
689 + array( $this, 'renderSupportPage' )
690 + );
691 +
692 + if ( ! Visualizer_Module::is_pro() ) {
693 + add_submenu_page(
694 + Visualizer_Plugin::NAME,
695 + __( 'Get Visualizer Pro', 'visualizer' ),
696 + __( 'Get Visualizer Pro', 'visualizer' ),
697 + 'edit_posts',
698 + 'viz-get-pro',
699 + '__return_null'
700 + );
701 + add_action( 'admin_footer', array( $this, 'handleGetProSubMenu' ) );
702 + }
703 + remove_submenu_page( Visualizer_Plugin::NAME, Visualizer_Plugin::NAME );
704 +
705 + add_action( "load-{$this->_libraryPage}", array( $this, 'addScreenOptions' ) );
450 706 }
451 707
452 708 /**
453 - * Renders visualizer library page.
454 - *
455 - * @since 1.0.0
456 - *
457 - * @access public
709 + * Handle get pro plugin submenu.
458 710 */
459 - public function renderLibraryPage() {
711 + public function handleGetProSubMenu() {
712 + ?>
713 + <style type="text/css">
714 + #toplevel_page_visualizer ul.wp-submenu li.wp-first-item + li + li + li {
715 + background: #FF7E65;
716 + font-size: 14px;
717 + font-weight: 600;
718 + color: #fff;
719 + }
720 + #toplevel_page_visualizer ul.wp-submenu li.wp-first-item + li + li + li > a {
721 + color: #fff !important;
722 + }
723 + #toplevel_page_visualizer ul.wp-submenu li.wp-first-item + li + li + li > a:hover {
724 + box-shadow: inherit;
725 + }
726 + #toplevel_page_visualizer ul.wp-submenu li.wp-first-item + li + li + li + li {
727 + display: none;
728 + }
729 + </style>
730 + <script type="text/javascript">
731 + jQuery( document ).ready( function() {
732 + jQuery( '#toplevel_page_visualizer' ).on( 'click', 'li:not(.wp-submenu-head, .wp-first-item):eq(2)', function( e ) {
733 + e.preventDefault();
734 + window.open( '<?php echo tsdk_utmify( 'https://themeisle.com/plugins/visualizer-charts-and-graphs/upgrade/', 'toplevel' ); ?>', '_blank' );
735 + } );
736 + } );
737 + </script>
738 + <?php
739 + }
740 +
741 + /**
742 + * Adds the screen options for pagination.
743 + */
744 + function addScreenOptions() {
745 + $screen = get_current_screen();
746 +
747 + // bail if it's some other page.
748 + if ( ! is_object( $screen ) || $screen->id !== $this->_libraryPage ) {
749 + return;
750 + }
751 +
752 + $args = array(
753 + 'label' => __( 'Number of charts per page:', 'visualizer' ),
754 + 'default' => 6,
755 + 'option' => 'visualizer_library_per_page',
756 + );
757 + add_screen_option( 'per_page', $args );
758 + }
759 +
760 + /**
761 + * Returns the screen option for pagination.
762 + */
763 + function setScreenOptions( $status, $option, $value ) {
764 + if ( 'visualizer_library_per_page' === $option ) {
765 + return $value;
766 + }
767 + }
768 +
769 + /**
770 + * Adds the display filters to be used in the meta_query while displaying the charts.
771 + */
772 + private function getDisplayFilters( &$query_args ) {
773 + $query = array();
774 + global $sitepress;
775 + if ( Visualizer_Module::is_pro() && ( function_exists( 'icl_get_languages' ) && $sitepress instanceof \SitePress ) ) {
776 + $current_lang = icl_get_current_language();
777 + if ( in_array( $current_lang, array( 'all', icl_get_default_language() ), true ) ) {
778 + $query[] = array(
779 + 'key' => 'chart_lang',
780 + 'compare' => 'NOT EXISTS',
781 + );
782 + } else {
783 + $query[] = array(
784 + 'key' => 'chart_lang',
785 + 'value' => $current_lang,
786 + 'compare' => '=',
787 + );
788 + }
789 + }
790 +
791 + // add chart type filter to the query arguments
792 + $type = filter_input( INPUT_GET, 'type' );
793 + if ( $type && in_array( $type, Visualizer_Plugin::getChartTypes(), true ) ) {
794 + $query[] = array(
795 + 'key' => Visualizer_Plugin::CF_CHART_TYPE,
796 + 'value' => $type,
797 + 'compare' => '=',
798 + );
799 + }
800 +
801 + // add chart library filter to the query arguments
802 + $library = filter_input( INPUT_GET, 'library' );
803 + if ( $library ) {
804 + $query[] = array(
805 + 'key' => Visualizer_Plugin::CF_CHART_LIBRARY,
806 + 'value' => $library,
807 + 'compare' => '=',
808 + );
809 + }
810 +
811 + // add date filter to the query arguments
812 + $date = filter_input( INPUT_GET, 'date' );
813 + $possible = array_keys( Visualizer_Plugin::getSupportedDateFilter() );
814 + if ( $date && in_array( $date, $possible, true ) ) {
815 + $query_args['date_query'] = array(
816 + 'after' => "$date -1 day",
817 + 'inclusive' => true,
818 + );
819 + }
820 +
821 + // add source filter to the query arguments
822 + $source = filter_input( INPUT_GET, 'source' );
823 + if ( $source ) {
824 + $source = ucwords( $source );
825 + $source = "Visualizer_Source_{$source}";
826 + $query[] = array(
827 + 'key' => Visualizer_Plugin::CF_SOURCE,
828 + 'value' => $source,
829 + 'compare' => '=',
830 + );
831 + }
832 +
833 + $query_args['meta_query'] = $query;
834 +
835 + $orderby = filter_input( INPUT_GET, 'orderby' );
836 + $order = filter_input( INPUT_GET, 'order' );
837 + if ( $orderby ) {
838 + $query_args['order_by'] = $orderby;
839 + }
840 + $query_args['order'] = empty( $order ) ? 'desc' : $order;
841 + }
842 +
843 + /**
844 + * Get the instance of WP_Query that fetches the charts as per the given criteria.
845 + */
846 + private function getQuery() {
847 + static $q;
848 + if ( ! is_null( $q ) ) {
849 + return $q;
850 + }
851 +
460 852 // get current page
461 853 $page = filter_input(
462 - INPUT_GET, 'vpage', FILTER_VALIDATE_INT, array(
854 + INPUT_GET,
855 + 'vpage',
856 + FILTER_VALIDATE_INT,
857 + array(
463 858 'options' => array(
464 859 'min_range' => 1,
465 860 'default' => 1,
466 861 ),
@@ -465,29 +860,34 @@
465 860 'default' => 1,
466 861 ),
467 862 )
468 863 );
864 +
865 + $per_page = 6;
866 + $screen = get_current_screen();
867 + if ( $screen ) {
868 + // retrieve the per_page option
869 + $screen_option = $screen->get_option( 'per_page', 'option' );
870 + // retrieve the value stored for the current user
871 + $user = get_current_user_id();
872 + $per_page = get_user_meta( $user, $screen_option, true );
873 + if ( empty( $per_page ) || $per_page < 1 ) {
874 + // nothing set, get the default value
875 + $per_page = $screen->get_option( 'per_page', 'default' );
876 + }
877 + }
878 +
469 879 // the initial query arguments to fetch charts
470 880 $query_args = array(
471 881 'post_type' => Visualizer_Plugin::CPT_VISUALIZER,
472 - 'posts_per_page' => 6,
882 + 'posts_per_page' => $per_page,
473 883 'paged' => $page,
474 884 );
475 - // add chart type filter to the query arguments
476 - $filter = filter_input( INPUT_GET, 'type' );
477 - if ( $filter && in_array( $filter, Visualizer_Plugin::getChartTypes() ) ) {
478 - $query_args['meta_query'] = array(
479 - array(
480 - 'key' => Visualizer_Plugin::CF_CHART_TYPE,
481 - 'value' => $filter,
482 - 'compare' => '=',
483 - ),
484 - );
485 - } else {
486 - $filter = 'all';
487 - }
885 +
886 + $this->getDisplayFilters( $query_args );
887 +
488 888 // Added by Ash/Upwork
489 - $filterByMeta = filter_input( INPUT_GET, 's', FILTER_SANITIZE_STRING );
889 + $filterByMeta = ! empty( $_GET['s'] ) ? sanitize_text_field( wp_unslash( $_GET['s'] ) ) : null; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
490 890 if ( $filterByMeta ) {
491 891 $query = array(
492 892 'key' => Visualizer_Plugin::CF_SETTINGS,
493 893 'value' => $filterByMeta,
@@ -496,56 +896,157 @@
496 896 $meta = isset( $query_args['meta_query'] ) ? $query_args['meta_query'] : array();
497 897 $meta[] = $query;
498 898 $query_args['meta_query'] = $meta;
499 899 }
500 - // Added by Ash/Upwork
501 - // fetch charts
900 + $q = new WP_Query( apply_filters( 'visualizer_query_args', $query_args ) );
901 + return $q;
902 + }
903 +
904 + /**
905 + * Renders support page.
906 + *
907 + * @since 3.3.0
908 + *
909 + * @access public
910 + */
911 + public function renderSupportPage() {
912 + wp_enqueue_style( 'visualizer-upsell', VISUALIZER_ABSURL . 'css/upsell.css', array(), Visualizer_Plugin::VERSION );
913 + include_once VISUALIZER_ABSPATH . '/templates/support.php';
914 + }
915 +
916 + /**
917 + * Renders visualizer library page.
918 + *
919 + * @since 1.0.0
920 + *
921 + * @access public
922 + */
923 + public function renderLibraryPage() {
502 924 $charts = array();
503 - $query = new WP_Query( $query_args );
925 + $query = $this->getQuery();
926 +
927 + // get current page
928 + $page = filter_input(
929 + INPUT_GET,
930 + 'vpage',
931 + FILTER_VALIDATE_INT,
932 + array(
933 + 'options' => array(
934 + 'min_range' => 1,
935 + 'default' => 1,
936 + ),
937 + )
938 + );
939 + // add chart type filter to the query arguments
940 + $filter = filter_input( INPUT_GET, 'type' );
941 + if ( ! ( $filter && in_array( $filter, Visualizer_Plugin::getChartTypes(), true ) ) ) {
942 + $filter = 'all';
943 + }
944 +
945 + $css = '';
504 946 while ( $query->have_posts() ) {
505 947 $chart = $query->next_post();
506 948
507 949 // if the user has updated a chart and instead of saving it, has closed the modal. If the user refreshes, they should get the original chart.
508 950 $chart = $this->handleExistingRevisions( $chart->ID, $chart );
951 + // refresh a "live" db query chart.
952 + $chart = apply_filters( 'visualizer_schedule_refresh_chart', $chart, $chart->ID, false );
509 953
954 + $type = get_post_meta( $chart->ID, Visualizer_Plugin::CF_CHART_TYPE, true );
955 +
510 956 // fetch and update settings
511 957 $settings = get_post_meta( $chart->ID, Visualizer_Plugin::CF_SETTINGS, true );
512 - unset( $settings['height'], $settings['width'] );
513 - $type = get_post_meta( $chart->ID, Visualizer_Plugin::CF_CHART_TYPE, true );
958 +
959 + $settings = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_SETTINGS, $settings, $chart->ID, $type );
960 + if ( ! empty( $atts['settings'] ) ) {
961 + $settings = apply_filters( $atts['settings'], $settings, $chart->ID, $type );
962 + }
963 +
964 + if ( $settings ) {
965 + unset( $settings['height'], $settings['width'], $settings['chartArea'] );
966 + }
967 +
514 968 $series = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_SERIES, get_post_meta( $chart->ID, Visualizer_Plugin::CF_SERIES, true ), $chart->ID, $type );
515 - $data = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_DATA, unserialize( html_entity_decode( $chart->post_content ) ), $chart->ID, $type );
969 + $data = self::get_chart_data( $chart, $type );
970 +
971 + // Set default setting series when add manual chart data - Only during first creation.
972 + if ( isset( $settings['series'] ) && ! empty( $series ) ) {
973 + $count_series = count( $series ) - count( $settings['series'] );
974 + if ( $count_series > 1 ) {
975 + $clone_last_series = end( $settings['series'] );
976 + $clone_last_series = array_fill_keys( array_keys( $clone_last_series ), '' );
977 + foreach ( range( 1, $count_series ) as $item ) {
978 + $settings['series'][] = $clone_last_series;
979 + }
980 + }
981 + }
982 +
983 + $library = $this->load_chart_type( $chart->ID );
984 +
985 + $id = 'visualizer-' . $chart->ID;
986 + $arguments = $this->get_inline_custom_css( $id, $settings );
987 + if ( ! empty( $arguments ) ) {
988 + $css .= $arguments[0];
989 + $settings = $arguments[1];
990 + }
991 +
992 + if ( isset( $settings['controls']['ui']['labelStacking'] ) ) {
993 + unset( $settings['controls']['ui']['labelStacking'] );
994 + }
995 + if ( isset( $settings['controls']['ui']['orientation'] ) ) {
996 + unset( $settings['controls']['ui']['orientation'] );
997 + }
998 +
516 999 // add chart to the array
517 - $charts[ 'visualizer-' . $chart->ID ] = array(
1000 + $charts[ $id ] = array(
518 1001 'id' => $chart->ID,
519 1002 'type' => $type,
520 1003 'series' => $series,
521 1004 'settings' => $settings,
522 1005 'data' => $data,
1006 + 'library' => $library,
523 1007 );
524 1008 }
525 1009 // enqueue charts array
526 1010 $ajaxurl = admin_url( 'admin-ajax.php' );
527 1011 wp_localize_script(
528 - 'visualizer-library', 'visualizer', array(
1012 + 'visualizer-library',
1013 + 'visualizer',
1014 + array(
529 1015 'language' => $this->get_language(),
530 1016 'map_api_key' => get_option( 'visualizer-map-api-key' ),
531 1017 'charts' => $charts,
532 1018 'urls' => array(
533 - 'base' => add_query_arg( 'vpage', false ),
534 - 'create' => add_query_arg(
535 - array(
536 - 'action' => Visualizer_Plugin::ACTION_CREATE_CHART,
537 - 'library' => 'yes',
538 - 'type' => isset( $_GET['type'] ) ? $_GET['type'] : '',
539 - ), $ajaxurl
1019 + 'base' => esc_url( add_query_arg( array( 'vpage' => false, 'vaction' => false ) ) ),
1020 + 'create' => esc_url(
1021 + add_query_arg(
1022 + array(
1023 + 'action' => Visualizer_Plugin::ACTION_CREATE_CHART,
1024 + 'library' => 'yes',
1025 + 'type' => isset( $_GET['type'] ) ? $_GET['type'] : '',
1026 + 'chart-library' => isset( $_GET['chart-library'] ) ? $_GET['chart-library'] : '',
1027 + 'vaction' => false,
1028 + ),
1029 + $ajaxurl
1030 + )
540 1031 ),
541 - 'edit' => add_query_arg(
542 - array(
543 - 'action' => Visualizer_Plugin::ACTION_EDIT_CHART,
544 - 'library' => 'yes',
545 - ), $ajaxurl
1032 + 'edit' => esc_url(
1033 + add_query_arg(
1034 + array(
1035 + 'action' => Visualizer_Plugin::ACTION_EDIT_CHART,
1036 + 'library' => 'yes',
1037 + 'vaction' => false,
1038 + ),
1039 + $ajaxurl
1040 + )
546 1041 ),
547 1042 ),
1043 + 'page_type' => 'library',
1044 + 'is_front' => false,
1045 + 'i10n' => array(
1046 + 'copied' => __( 'The shortcode has been copied to your clipboard. Hit Ctrl-V/Cmd-V to paste it.', 'visualizer' ),
1047 + 'conflict' => __( 'We have detected a potential conflict with another component that prevents Visualizer from functioning properly. Please disable any of the following components if they are activated on your instance: Modern Events Calendar plugin, Acronix plugin. In case the aforementioned components are not activated or you continue to see this error message, please disable all other plugins and enable them one by one to find out the component that is causing the conflict.', 'visualizer' ),
1048 + ),
548 1049 )
549 1050 );
550 1051 // render library page
551 1052 $render = new Visualizer_Render_Library();
@@ -550,12 +1051,13 @@
550 1051 // render library page
551 1052 $render = new Visualizer_Render_Library();
552 1053 $render->charts = $charts;
553 1054 $render->type = $filter;
554 - $render->types = self::_getChartTypesLocalized();
1055 + $render->types = self::_getChartTypesLocalized( false, false, false, true );
1056 + $render->custom_css = $css;
555 1057 $render->pagination = paginate_links(
556 1058 array(
557 - 'base' => add_query_arg( 'vpage', '%#%' ),
1059 + 'base' => add_query_arg( array( 'vpage' => '%#%', 'vaction' => false ) ),
558 1060 'format' => '',
559 1061 'current' => $page,
560 1062 'total' => $query->max_num_pages,
561 1063 'type' => 'array',
@@ -576,14 +1078,14 @@
576 1078 *
577 1079 * @return array Updated array of action links.
578 1080 */
579 1081 public function getPluginActionLinks( $links, $file ) {
580 - if ( $file == plugin_basename( VISUALIZER_BASEFILE ) ) {
1082 + if ( $file === plugin_basename( VISUALIZER_BASEFILE ) ) {
581 1083 array_unshift(
582 1084 $links,
583 1085 sprintf(
584 1086 '<a href="%s">%s</a>',
585 - admin_url( 'upload.php?page=' . Visualizer_Plugin::NAME ),
1087 + admin_url( 'admin.php?page=' . Visualizer_Plugin::NAME ),
586 1088 esc_html__( 'Library', 'visualizer' )
587 1089 )
588 1090 );
589 1091 }
@@ -603,17 +1105,17 @@
603 1105 *
604 1106 * @return array Updated array of plugin meta links.
605 1107 */
606 1108 public function getPluginMetaLinks( $plugin_meta, $plugin_file ) {
607 - if ( $plugin_file == plugin_basename( VISUALIZER_BASEFILE ) ) {
1109 + if ( $plugin_file === plugin_basename( VISUALIZER_BASEFILE ) ) {
608 1110 // knowledge base link
609 1111 $plugin_meta[] = sprintf(
610 - '<a href="https://github.com/codeinwp/visualizer/wiki" target="_blank">%s</a>',
611 - esc_html__( 'Knowledge Base', 'visualizer' )
1112 + '<a href="' . VISUALIZER_MAIN_DOC . '" target="_blank">%s</a>',
1113 + esc_html__( 'Docs', 'visualizer' )
612 1114 );
613 1115 // flattr link
614 1116 $plugin_meta[] = sprintf(
615 - '<a style="color:red" href="https://themeisle.com/plugins/visualizer-charts-and-graphs-pro-addon/" target="_blank">%s</a>',
1117 + '<a style="color:red" href="' . tsdk_utmify( Visualizer_Plugin::PRO_TEASER_URL, 'pluginrow' ) . '" target="_blank">%s</a>',
616 1118 esc_html__( 'Pro Addon', 'visualizer' )
617 1119 );
618 1120 }
619 1121
@@ -619,5 +1121,75 @@
619 1121
620 1122 return $plugin_meta;
621 1123 }
622 1124
1125 + /**
1126 + * If check is existing user.
1127 + *
1128 + * @return bool Default false
1129 + */
1130 + public static function proFeaturesLocked() {
1131 + if ( Visualizer_Module::is_pro() ) {
1132 + return true;
1133 + }
1134 + return 'yes' === get_option( 'visualizer-new-user', 'yes' ) ? false : true;
1135 + }
1136 +
1137 + /**
1138 + * Multilingual Support.
1139 + *
1140 + * @param int $chart_id Chart ID.
1141 + * @return bool Default false
1142 + */
1143 + public function addMultilingualSupport( $chart_id ) {
1144 + global $sitepress;
1145 + if ( Visualizer_Module::is_pro() ) {
1146 + return;
1147 + }
1148 + if ( function_exists( 'icl_get_languages' ) && $sitepress instanceof \SitePress ) {
1149 + $language = icl_get_languages();
1150 + $current_lang = icl_get_current_language();
1151 + $default_lang = icl_get_default_language();
1152 + $post_info = wpml_get_language_information( null, $chart_id );
1153 + $translations = array();
1154 + if ( ! empty( $post_info ) && ( $default_lang === $post_info['language_code'] ) ) {
1155 + $trid = $sitepress->get_element_trid( $chart_id, 'post_' . Visualizer_Plugin::CPT_VISUALIZER );
1156 + $translations = $sitepress->get_element_translations( $trid );
1157 + }
1158 + if ( empty( $translations ) ) {
1159 + return;
1160 + }
1161 + ?>
1162 + <hr><div class="visualizer-languages-list only-pro">
1163 + <?php
1164 + foreach ( $language as $lang ) {
1165 + $lang_code = $lang['code'];
1166 + if ( $current_lang !== $lang_code ) {
1167 + ?>
1168 + <a href="javascript:;">
1169 + <img src="<?php echo esc_url( $lang['country_flag_url'] ); ?>" alt="<?php echo esc_attr( $lang['translated_name'] ); ?>">
1170 + </a>
1171 + <?php
1172 + }
1173 + }
1174 + ?>
1175 + <a href="<?php echo tsdk_utmify( Visualizer_Plugin::PRO_TEASER_URL, 'wpml-support', 'visualizer_render_char' ); ?>"target="_blank"><?php esc_html_e( 'Upgrade to PRO to active this translation for charts', 'visualizer' ); ?></a>
1176 + </div>
1177 + <?php
1178 + }
1179 + }
1180 +
1181 + /**
1182 + * Check chart is enabled or not.
1183 + *
1184 + * @param string $type Chart ID.
1185 + *
1186 + * @return bool Default false
1187 + */
1188 + public static function checkChartStatus( $type ) {
1189 + $types = self::_getChartTypesLocalized( false, false, false, true );
1190 + if ( isset( $types[ $type ] ) ) {
1191 + return ! empty( $types[ $type ]['enabled'] );
1192 + }
1193 + return false;
1194 + }
623 1195 }