PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.11.1
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.11.1
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
visualizer / classes / Visualizer / Module / Admin.php

Admin.php in Visualizer – Tables & Charts Manager with Built-in AI Generator 3.11.1, at classes/Visualizer/Module/Admin.php

1,282 lines 40.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 // +----------------------------------------------------------------------+
3 // | Copyright 2013 Madpixels (email : visualizer@madpixels.net) |
4 // +----------------------------------------------------------------------+
5 // | This program is free software; you can redistribute it and/or modify |
6 // | it under the terms of the GNU General Public License, version 2, as |
7 // | published by the Free Software Foundation. |
8 // | |
9 // | This program is distributed in the hope that it will be useful, |
10 // | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 // | GNU General Public License for more details. |
13 // | |
14 // | You should have received a copy of the GNU General Public License |
15 // | along with this program; if not, write to the Free Software |
16 // | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, |
17 // | MA 02110-1301 USA |
18 // +----------------------------------------------------------------------+
19 // | Author: Eugene Manuilov <eugene@manuilov.org> |
20 // +----------------------------------------------------------------------+
21 /**
22 * The module for all admin stuff.
23 *
24 * @category Visualizer
25 * @package Module
26 *
27 * @since 1.0.0
28 */
29 class Visualizer_Module_Admin extends Visualizer_Module {
30
31 const NAME = __CLASS__;
32
33 /**
34 * Library page suffix.
35 *
36 * @since 1.0.0
37 *
38 * @access private
39 * @var string
40 */
41 private $_libraryPage;
42
43 /**
44 * Constructor.
45 *
46 * @since 1.0.0
47 *
48 * @access public
49 *
50 * @param Visualizer_Plugin $plugin The instance of the plugin.
51 */
52 public function __construct( Visualizer_Plugin $plugin ) {
53 parent::__construct( $plugin );
54 $this->_addAction( 'load-post.php', 'enqueueMediaScripts' );
55 $this->_addAction( 'load-post-new.php', 'enqueueMediaScripts' );
56 $this->_addAction( 'admin_footer', 'renderTemplates' );
57 $this->_addAction( 'admin_enqueue_scripts', 'enqueueLibraryScripts', null, 0 );
58 $this->_addAction( 'admin_menu', 'registerAdminMenu' );
59 $this->_addFilter( 'media_view_strings', 'setupMediaViewStrings' );
60 $this->_addFilter( 'plugin_action_links', 'getPluginActionLinks', 10, 2 );
61 $this->_addFilter( 'plugin_row_meta', 'getPluginMetaLinks', 10, 2 );
62 $this->_addFilter( 'visualizer_logger_data', 'getLoggerData' );
63 $this->_addFilter( 'visualizer_feedback_review_trigger', 'feedbackReviewTrigger' );
64
65 // screen pagination
66 $this->_addFilter( 'set-screen-option', 'setScreenOptions', 10, 3 );
67
68 // revision support.
69 $this->_addFilter( 'wp_revisions_to_keep', 'limitRevisions', null, 10, 2 );
70 $this->_addAction( '_wp_put_post_revision', 'addRevision', null, 10, 1 );
71 $this->_addAction( 'wp_restore_post_revision', 'restoreRevision', null, 10, 2 );
72
73 $this->_addAction( 'visualizer_chart_schedules_spl', 'addSplChartSchedules', null, 10, 3 );
74
75 $this->_addAction( 'admin_init', 'init' );
76
77 $this->_addAction( 'visualizer_chart_languages', 'addMultilingualSupport' );
78
79 $this->_addFilter( 'admin_footer_text', 'render_review_notice' );
80
81 if ( defined( 'TI_CYPRESS_TESTING' ) ) {
82 $this->load_cypress_hooks();
83 }
84
85 }
86 /**
87 * Display review notice.
88 */
89 public function render_review_notice( $footer_text ) {
90 $current_screen = get_current_screen();
91
92 $visualizer_page_ids = ['toplevel_page_visualizer', 'visualizer_page_viz-support', 'visualizer_page_ti-about-visualizer' ];
93
94 if ( ! empty( $current_screen ) && isset( $current_screen->id ) ) {
95 foreach ( $visualizer_page_ids as $page_to_check ) {
96 if ( strpos( $current_screen->id, $page_to_check ) !== false ) {
97 $footer_text = sprintf(
98 __( 'Enjoying %1$s? %2$s %3$s rating. Thank you for being so supportive!', 'visualizer' ),
99 '<b>Visualizer</b>',
100 esc_html__( 'You can help us by leaving a', 'visualizer' ),
101 '<a href="https://wordpress.org/support/plugin/visualizer/reviews/" target="_blank">&#9733;&#9733;&#9733;&#9733;&#9733;</a>'
102 );
103 break;
104 }
105 }
106 }
107
108 return $footer_text;
109 }
110
111
112 /**
113 * Define the hooks that are needed for cypress.
114 *
115 * @since 3.4.0
116 * @access private
117 */
118 private function load_cypress_hooks() {
119 // all charts should load on the same page without pagination.
120 add_filter(
121 'visualizer_query_args', function( $args ) {
122 $args['posts_per_page'] = 20;
123 return $args;
124 }, 10, 1
125 );
126 }
127
128 /**
129 * Add disabled `optgroup` schedules to the drop downs.
130 *
131 * @since ?
132 *
133 * @access public
134 *
135 * @param string $feature The feature for which to add schedules.
136 * @param int $chart_id The chart ID.
137 * @param int $plan The plan number.
138 */
139 public function addSplChartSchedules( $feature, $chart_id, $plan ) {
140 if ( apply_filters( 'visualizer_is_business', false ) ) {
141 return;
142 }
143
144 $is_new_personal = apply_filters( 'visualizer_is_new_personal', false );
145
146 $hours = array(
147 '0.16' => __( '10 minutes', 'visualizer' ),
148 '1' => __( 'Each hour', 'visualizer' ),
149 '12' => __( 'Each 12 hours', 'visualizer' ),
150 '24' => __( 'Each day', 'visualizer' ),
151 '72' => __( 'Each 3 days', 'visualizer' ),
152 );
153
154 switch ( $feature ) {
155 case 'json':
156 case 'csv':
157 // no more schedules if pro is already active.
158 if ( Visualizer_Module::is_pro() && ! $is_new_personal ) {
159 return;
160 }
161 break;
162 case 'wp':
163 // fall-through.
164 case 'db':
165 break;
166 default:
167 return;
168 }
169
170 echo '<optgroup disabled label="' . __( 'Upgrade required', 'visualizer' ) . '">';
171 foreach ( $hours as $hour => $desc ) {
172 echo '<option disabled>' . $desc . '</option>';
173 }
174 echo '</optgroup>';
175 }
176
177 /**
178 * No limits on revisions.
179 */
180 public function limitRevisions( $num, $post ) {
181 if ( Visualizer_Plugin::CPT_VISUALIZER === $post->post_type ) {
182 return -1;
183 }
184 return $num;
185 }
186
187 /**
188 * Add a revision.
189 */
190 public function addRevision( $revision_id ) {
191 $parent_id = wp_is_post_revision( $revision_id );
192 if ( Visualizer_Plugin::CPT_VISUALIZER === get_post_type( $parent_id ) ) {
193 // add the meta data to this revision.
194 $meta = get_post_meta( $parent_id, '', true );
195
196 if ( $meta ) {
197 foreach ( $meta as $key => $value ) {
198 if ( 0 === strpos( $key, 'visualizer' ) ) {
199 add_metadata( 'post', $revision_id, $key, maybe_unserialize( $value[0] ) );
200 }
201 }
202 }
203 }
204 }
205
206 /**
207 * Restore a revision.
208 */
209 public function restoreRevision( $post_id, $revision_id ) {
210 if ( Visualizer_Plugin::CPT_VISUALIZER === get_post_type( $post_id ) ) {
211 // get the meta information from the revision.
212 $meta = get_metadata( 'post', $revision_id, '', true );
213
214 // delete all meta information from the post before adding.
215 $post_meta = get_post_meta( $post_id, '', true );
216 if ( $post_meta ) {
217 foreach ( $meta as $key => $value ) {
218 if ( 0 === strpos( $key, 'visualizer' ) ) {
219 delete_post_meta( $post_id, $key );
220 }
221 }
222 }
223
224 if ( $meta ) {
225 foreach ( $meta as $key => $value ) {
226 if ( 0 === strpos( $key, 'visualizer' ) ) {
227 add_post_meta( $post_id, $key, maybe_unserialize( $value[0] ) );
228 }
229 }
230 }
231 }
232 }
233
234 /**
235 * Admin init.
236 *
237 * @access public
238 */
239 public function init() {
240 // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
241 if ( current_user_can( 'edit_posts' ) && current_user_can( 'edit_pages' ) && 'true' == get_user_option( 'rich_editing' ) ) {
242 $this->_addFilter( 'mce_external_languages', 'add_tinymce_lang', 10, 1 );
243 $this->_addFilter( 'mce_external_plugins', 'tinymce_plugin', 10, 1 );
244 $this->_addFilter( 'mce_buttons', 'register_mce_button', 10, 1 );
245 $this->_addFilter( 'tiny_mce_before_init', 'get_strings_for_block', 10, 1 );
246 }
247 }
248
249 /**
250 * Add the strings required for the TinyMCE buttons for the classic block (not the classic editor).
251 *
252 * @since ?
253 * @access friendly
254 */
255 function get_strings_for_block( $settings ) {
256 $class = new Visualizer_Module_Language();
257 $strings = $class->get_strings();
258 $array = array( 'visualizer_tinymce_plugin' => json_encode( $strings ) );
259 return array_merge( $settings, $array );
260 }
261
262 /**
263 * Load plugin translation for - TinyMCE API
264 *
265 * @access public
266 * @param array $arr The tinymce_lang array.
267 * @return array
268 */
269 public function add_tinymce_lang( $arr ) {
270 $ui_lang = VISUALIZER_ABSPATH . '/classes/Visualizer/Module/Language.php';
271 $ui_lang = apply_filters( 'visualizer_ui_lang_filter', $ui_lang );
272 $arr[] = $ui_lang;
273 return $arr;
274 }
275
276 /**
277 * Load custom js options - TinyMCE API
278 *
279 * @access public
280 * @param array $plugin_array The tinymce plugin array.
281 * @return array
282 */
283 public function tinymce_plugin( $plugin_array ) {
284 $plugin_array['visualizer_mce_button'] = VISUALIZER_ABSURL . 'js/mce.js';
285 return $plugin_array;
286 }
287
288 /**
289 * Register new button in the editor
290 *
291 * @access public
292 * @param array $buttons The tinymce buttons array.
293 * @return array
294 */
295 public function register_mce_button( $buttons ) {
296 array_push( $buttons, 'visualizer_mce_button' );
297 return $buttons;
298 }
299
300 /**
301 * Whether to show the feedback review or not.
302 *
303 * @access public
304 */
305 public function feedbackReviewTrigger( $dumb ) {
306 $query = new WP_Query(
307 array(
308 'posts_per_page' => 50,
309 'post_type' => Visualizer_Plugin::CPT_VISUALIZER,
310 'fields' => 'ids',
311 'update_post_meta_cache' => false,
312 'update_post_term_cache' => false,
313 )
314 );
315
316 if ( $query->have_posts() && $query->post_count > 0 ) {
317 return true;
318 }
319 return false;
320 }
321
322 /**
323 * Enqueues media scripts and styles.
324 *
325 * @since 1.0.0
326 * @uses wp_enqueue_style To enqueue style file.
327 * @uses wp_enqueue_script To enqueue script file.
328 *
329 * @access public
330 */
331 public function enqueueMediaScripts() {
332 global $typenow;
333 if ( post_type_supports( $typenow, 'editor' ) ) {
334 wp_enqueue_style( 'visualizer-media', VISUALIZER_ABSURL . 'css/media.css', array( 'media-views' ), Visualizer_Plugin::VERSION );
335
336 // Load all the assets for the different libraries we support.
337 $deps = array(
338 Visualizer_Render_Sidebar_Google::enqueue_assets( array( 'media-editor' ) ),
339 Visualizer_Render_Sidebar_Type_DataTable_Tabular::enqueue_assets( array( 'media-editor' ) ),
340 );
341
342 wp_enqueue_script( 'visualizer-media-model', VISUALIZER_ABSURL . 'js/media/model.js', $deps, Visualizer_Plugin::VERSION, true );
343 wp_enqueue_script( 'visualizer-media-collection', VISUALIZER_ABSURL . 'js/media/collection.js', array( 'visualizer-media-model' ), Visualizer_Plugin::VERSION, true );
344 wp_enqueue_script( 'visualizer-media-controller', VISUALIZER_ABSURL . 'js/media/controller.js', array( 'visualizer-media-collection' ), Visualizer_Plugin::VERSION, true );
345 wp_enqueue_script( 'visualizer-media-view', VISUALIZER_ABSURL . 'js/media/view.js', array( 'visualizer-media-controller' ), Visualizer_Plugin::VERSION, true );
346 wp_localize_script(
347 'visualizer-media-view',
348 'visualizer',
349 array(
350 'i10n' => array(
351 'insert' => __( 'Insert', 'visualizer' ),
352 ),
353 )
354 );
355 wp_enqueue_script( 'visualizer-media-toolbar', VISUALIZER_ABSURL . 'js/media/toolbar.js', array( 'visualizer-media-view' ), Visualizer_Plugin::VERSION, true );
356 wp_enqueue_script( 'visualizer-media', VISUALIZER_ABSURL . 'js/media.js', array( 'visualizer-media-toolbar' ), Visualizer_Plugin::VERSION, true );
357 }
358 }
359
360 /**
361 * Extends media view strings with visualizer strings.
362 *
363 * @since 1.0.0
364 *
365 * @access public
366 *
367 * @param array $strings The array of media view strings.
368 *
369 * @return array The extended array of media view strings.
370 */
371 public function setupMediaViewStrings( $strings ) {
372 $chart_types = self::_getChartTypesLocalized( true, true, true );
373 $strings['visualizer'] = array(
374 'actions' => array(
375 'get_charts' => Visualizer_Plugin::ACTION_GET_CHARTS,
376 'delete_chart' => Visualizer_Plugin::ACTION_DELETE_CHART,
377 ),
378 'controller' => array(
379 'title' => esc_html__( 'Visualizations', 'visualizer' ),
380 ),
381 'routers' => array(
382 'library' => esc_html__( 'From Library', 'visualizer' ),
383 'create' => esc_html__( 'Create New', 'visualizer' ),
384 ),
385 'library' => array(
386 'filters' => $chart_types,
387 'types' => array_keys( $chart_types ),
388 ),
389 'nonce' => wp_create_nonce(),
390 'buildurl' => esc_url( add_query_arg( 'action', Visualizer_Plugin::ACTION_CREATE_CHART, admin_url( 'admin-ajax.php' ) ) ),
391 );
392
393 return $strings;
394 }
395
396 /**
397 * Returns associated array of chart types and localized names.
398 *
399 * @since 1.0.0
400 *
401 * @static
402 * @access private
403 * @return array The associated array of chart types with localized names.
404 */
405 public static function _getChartTypesLocalized( $enabledOnly = false, $get2Darray = false, $add_select = false, $where = null ) {
406 $additional = array();
407 if ( $add_select ) {
408 $additional['select'] = array(
409 'name' => esc_html__( 'All', 'visualizer' ),
410 'enabled' => true,
411 );
412 }
413
414 $enabled = self::proFeaturesLocked();
415
416 $types = array_merge(
417 $additional,
418 array(
419 'tabular' => array(
420 'name' => esc_html__( 'Table', 'visualizer' ),
421 'enabled' => true,
422 'supports' => $enabled ? array( 'Google Charts', 'DataTable' ) : array( 'DataTable' ),
423 ),
424 'pie' => array(
425 'name' => esc_html__( 'Pie/Donut', 'visualizer' ),
426 'enabled' => true,
427 'supports' => array( 'Google Charts', 'ChartJS' ),
428 ),
429 'line' => array(
430 'name' => esc_html__( 'Line', 'visualizer' ),
431 'enabled' => true,
432 'supports' => array( 'Google Charts', 'ChartJS' ),
433 ),
434 'bar' => array(
435 'name' => esc_html__( 'Bar', 'visualizer' ),
436 'enabled' => true,
437 'supports' => $enabled ? array( 'Google Charts', 'ChartJS' ) : array( 'Google Charts' ),
438 ),
439 'area' => array(
440 'name' => esc_html__( 'Area', 'visualizer' ),
441 'enabled' => $enabled,
442 // in ChartJS, the fill option is used to make Line chart an area: https://www.chartjs.org/docs/latest/charts/area.html
443 'supports' => array( 'Google Charts' ),
444 ),
445 'geo' => array(
446 'name' => esc_html__( 'Geo', 'visualizer' ),
447 'enabled' => $enabled,
448 'supports' => array( 'Google Charts' ),
449 ),
450 'column' => array(
451 'name' => esc_html__( 'Column', 'visualizer' ),
452 'enabled' => $enabled,
453 'supports' => array( 'Google Charts', 'ChartJS' ),
454 ),
455 'bubble' => array(
456 'name' => esc_html__( 'Bubble', 'visualizer' ),
457 'enabled' => $enabled,
458 // chartjs' bubble is ugly looking (and it won't work off the default bubble.csv) so it is being excluded for the time being.
459 'supports' => array( 'Google Charts' ),
460 ),
461 'scatter' => array(
462 'name' => esc_html__( 'Scatter', 'visualizer' ),
463 'enabled' => $enabled,
464 'supports' => array( 'Google Charts' ),
465 ),
466 'gauge' => array(
467 'name' => esc_html__( 'Gauge', 'visualizer' ),
468 'enabled' => $enabled,
469 'supports' => array( 'Google Charts' ),
470 ),
471 'candlestick' => array(
472 'name' => esc_html__( 'Candlestick', 'visualizer' ),
473 'enabled' => $enabled,
474 'supports' => array( 'Google Charts' ),
475 ),
476 // pro types
477 'timeline' => array(
478 'name' => esc_html__( 'Timeline', 'visualizer' ),
479 'enabled' => false,
480 'supports' => array( 'Google Charts', 'ChartJS' ),
481 ),
482 'combo' => array(
483 'name' => esc_html__( 'Combo', 'visualizer' ),
484 'enabled' => false,
485 'supports' => array( 'Google Charts' ),
486 ),
487 'polarArea' => array(
488 'name' => esc_html__( 'Polar Area', 'visualizer' ),
489 'enabled' => false,
490 'supports' => array( 'ChartJS' ),
491 ),
492 'radar' => array(
493 'name' => esc_html__( 'Radar/Spider', 'visualizer' ),
494 'enabled' => false,
495 'supports' => array( 'ChartJS' ),
496 ),
497 )
498 );
499 $types = apply_filters( 'visualizer_pro_chart_types', $types );
500 if ( $enabledOnly ) {
501 $filtered = array();
502 foreach ( $types as $type => $array ) {
503 if ( ! is_array( $array ) ) {
504 // support for old pro
505 $array = array( 'enabled' => true, 'name' => $array );
506 }
507 // backward compatibility for PRO before v1.9.0
508 if ( ! array_key_exists( 'supports', $array ) ) {
509 $array['supports'] = array( 'Google Charts' );
510 }
511 if ( ! $array['enabled'] ) {
512 continue;
513 }
514 $filtered[ $type ] = $array;
515 }
516 $types = $filtered;
517 }
518 if ( $get2Darray ) {
519 $doubleD = array();
520 foreach ( $types as $type => $array ) {
521 if ( ! is_array( $array ) ) {
522 // support for old pro
523 $array = array( 'enabled' => true, 'name' => $array );
524 }
525 // backward compatibility for PRO before v1.9.0
526 if ( ! array_key_exists( 'supports', $array ) ) {
527 $array['supports'] = array( 'Google Charts' );
528 }
529 $doubleD[ $type ] = $array['name'];
530 }
531 $types = $doubleD;
532 }
533
534 return self::handleDeprecatedCharts( $types, $enabledOnly, $get2Darray, $where );
535 }
536
537 /**
538 * Handle (soon-to-be) deprecated charts.
539 */
540 private static function handleDeprecatedCharts( $types, $enabledOnly, $get2Darray, $where ) {
541 $deprecated = array();
542
543 switch ( $where ) {
544 case 'types':
545 // fall-through
546 case 'library':
547 // if a user has a Gauge/Candlestick chart, then let them keep using it.
548 if ( ! Visualizer_Module::is_pro() ) {
549 if ( ! self::hasChartType( 'gauge' ) ) {
550 if ( $get2Darray ) {
551 $deprecated[] = 'gauge';
552 } else {
553 $types['gauge']['enabled'] = false;
554 }
555 }
556 if ( ! self::hasChartType( 'candlestick' ) ) {
557 if ( $get2Darray ) {
558 $deprecated[] = 'candlestick';
559 } else {
560 $types['candlestick']['enabled'] = false;
561 }
562 }
563 }
564 break;
565 default:
566 // if a user has a Gauge/Candlestick chart, then let them keep using it.
567 if ( ! Visualizer_Module::is_pro() ) {
568 if ( ! self::hasChartType( 'gauge' ) ) {
569 if ( $get2Darray ) {
570 $deprecated[] = 'gauge';
571 } else {
572 $types['gauge']['enabled'] = false;
573 }
574 }
575 if ( ! self::hasChartType( 'candlestick' ) ) {
576 if ( $get2Darray ) {
577 $deprecated[] = 'candlestick';
578 } else {
579 $types['candlestick']['enabled'] = false;
580 }
581 }
582 }
583 }
584
585 if ( $deprecated ) {
586 foreach ( $deprecated as $type ) {
587 unset( $types[ $type ] );
588 }
589 }
590
591 return $types;
592 }
593
594 /**
595 * Renders templates to use in media popup.
596 *
597 * @since 1.0.0
598 * @global string $pagenow The name of the current page.
599 *
600 * @access public
601 */
602 public function renderTemplates() {
603 global $pagenow;
604 if ( 'post.php' !== $pagenow && 'post-new.php' !== $pagenow ) {
605 return;
606 }
607 $render = new Visualizer_Render_Templates();
608 $render->render();
609 }
610
611 /**
612 * Enqueues library scripts and styles.
613 *
614 * @since 1.0.0
615 * @uses wp_enqueue_style() To enqueue library stylesheet.
616 * @uses wp_enqueue_script() To enqueue javascript file.
617 * @uses wp_enqueue_media() To enqueue media stuff.
618 *
619 * @access public
620 *
621 * @param string $suffix The current page suffix.
622 */
623 public function enqueueLibraryScripts( $suffix ) {
624 if ( $suffix === $this->_libraryPage ) {
625 wp_enqueue_style( 'visualizer-library', VISUALIZER_ABSURL . 'css/library.css', array(), Visualizer_Plugin::VERSION );
626 $this->_addFilter( 'media_upload_tabs', 'setupVisualizerTab' );
627 wp_enqueue_media();
628 wp_enqueue_script(
629 'visualizer-library',
630 VISUALIZER_ABSURL . 'js/library.js',
631 array(
632 'jquery',
633 'media-views',
634 'clipboard',
635 ),
636 Visualizer_Plugin::VERSION,
637 true
638 );
639
640 wp_enqueue_script( 'visualizer-customization', $this->get_user_customization_js(), array(), null, true );
641
642 $query = $this->getQuery();
643 while ( $query->have_posts() ) {
644 $chart = $query->next_post();
645 $library = $this->load_chart_type( $chart->ID );
646 if ( is_null( $library ) ) {
647 continue;
648 }
649 wp_enqueue_script(
650 "visualizer-render-$library",
651 VISUALIZER_ABSURL . 'js/render-facade.js',
652 apply_filters( 'visualizer_assets_render', array( 'visualizer-library', 'visualizer-customization' ), true ),
653 Visualizer_Plugin::VERSION,
654 true
655 );
656 }
657 }
658 }
659
660 /**
661 * Adds visualizer tab for media upload tabs array.
662 *
663 * @since 1.0.0
664 *
665 * @access public
666 *
667 * @param array $tabs The array of media upload tabs.
668 *
669 * @return array Extended array of media upload tabs.
670 */
671 public function setupVisualizerTab( $tabs ) {
672 $tabs['visualizer'] = 'Visualizer';
673
674 return $tabs;
675 }
676
677 /**
678 * Registers admin menu for visualizer library.
679 *
680 * @since 1.0.0
681 *
682 * @access public
683 */
684 public function registerAdminMenu() {
685 $svg_base64_icon = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iNzdweCIgaGVpZ2h0PSI3N3B4IiB2aWV3Qm94PSIwIDAgNzcgNzciIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICA8IS0tIEdlbmVyYXRvcjogU2tldGNoIDUyLjYgKDY3NDkxKSAtIGh0dHA6Ly93d3cuYm9oZW1pYW5jb2RpbmcuY29tL3NrZXRjaCAtLT4KICAgIDx0aXRsZT5Db21iaW5lZCBTaGFwZTwvdGl0bGU+CiAgICA8ZGVzYz5DcmVhdGVkIHdpdGggU2tldGNoLjwvZGVzYz4KICAgIDxnIGlkPSJQcm9kdWN0LVBhZ2UiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPgogICAgICAgIDxnIGlkPSJXb3JkUHJlc3MtcGx1Z2lucyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTE5MC4wMDAwMDAsIC00MzUuMDAwMDAwKSIgZmlsbD0iIzM5QzNEMiI+CiAgICAgICAgICAgIDxwYXRoIGQ9Ik0yMjguNSw1MTIgQzIwNy4yMzcwMzcsNTEyIDE5MCw0OTQuNzYyOTYzIDE5MCw0NzMuNSBDMTkwLDQ1Mi4yMzcwMzcgMjA3LjIzNzAzNyw0MzUgMjI4LjUsNDM1IEMyNDkuNzYyOTYzLDQzNSAyNjcsNDUyLjIzNzAzNyAyNjcsNDczLjUgQzI2Nyw0OTQuNzYyOTYzIDI0OS43NjI5NjMsNTEyIDIyOC41LDUxMiBaIE0yNDYuODQzNzUsNDgzLjU5MjA1OSBMMjE1LjYyNSw0ODMuNTkyMDU5IEwyMTUuNjI1LDQ2MC44MjY1NDQgQzIxNS42MjUsNDYwLjE2NDU0NyAyMTUuMTA3NTc4LDQ1OS42MjgzNTkgMjE0LjQ2ODc1LDQ1OS42MjgzNTkgTDIxMi4xNTYyNSw0NTkuNjI4MzU5IEMyMTEuNTE3NDIyLDQ1OS42MjgzNTkgMjExLDQ2MC4xNjQ1NDcgMjExLDQ2MC44MjY1NDQgTDIxMSw0ODUuOTg4NDI5IEMyMTEsNDg3LjMxMTY3NCAyMTIuMDM1NTY2LDQ4OC4zODQ3OTggMjEzLjMxMjUsNDg4LjM4NDc5OCBMMjQ2Ljg0Mzc1LDQ4OC4zODQ3OTggQzI0Ny40ODI1NzgsNDg4LjM4NDc5OCAyNDgsNDg3Ljg0ODYxMSAyNDgsNDg3LjE4NjYxMyBMMjQ4LDQ4NC43OTAyNDQgQzI0OCw0ODQuMTI4MjQ2IDI0Ny40ODI1NzgsNDgzLjU5MjA1OSAyNDYuODQzNzUsNDgzLjU5MjA1OSBaIE0yNDQuNTMxMjUsNDYyLjAyNDcyOSBMMjM1Ljk5OTU3LDQ2Mi4wMjQ3MjkgQzIzNC40NTQ1MzEsNDYyLjAyNDcyOSAyMzMuNjgwNTY2LDQ2My45NjA1NDcgMjM0Ljc3MzIyMyw0NjUuMDkyODMyIEwyMzcuMTE0NjI5LDQ2Ny41MTkxNTYgTDIzMS44MTI1LDQ3My4wMTQzMzIgTDIyNi41MTAzNzEsNDY3LjUxOTkwNSBDMjI1LjYwNzA1MSw0NjYuNTgzODIzIDIyNC4xNDI5NDksNDY2LjU4MzgyMyAyMjMuMjQwMzUyLDQ2Ny41MTk5MDUgTDIxOC4yNzY0MjYsNDcyLjY2Mzg2MyBDMjE3LjgyNDc2Niw0NzMuMTMxOTA0IDIxNy44MjQ3NjYsNDczLjg5MDUwNSAyMTguMjc2NDI2LDQ3NC4zNTg1NDYgTDIxOS45MTEwNzQsNDc2LjA1MjQ4IEMyMjAuMzYyNzM0LDQ3Ni41MjA1MjEgMjIxLjA5NDc4NSw0NzYuNTIwNTIxIDIyMS41NDY0NDUsNDc2LjA1MjQ4IEwyMjQuODc1LDQ3Mi42MDI0NTYgTDIzMC4xNzcxMjksNDc4LjA5Njg4MyBDMjMxLjA4MDQ0OSw0NzkuMDMyOTY1IDIzMi41NDQ1NTEsNDc5LjAzMjk2NSAyMzMuNDQ3MTQ4LDQ3OC4wOTY4ODMgTDI0MC4zODQ2NDgsNDcwLjkwNzc3MyBMMjQyLjcyNjA1NSw0NzMuMzM0MDk4IEMyNDMuODE4NzExLDQ3NC40NjYzODIgMjQ1LjY4Njc3Nyw0NzMuNjY0MzQ3IDI0NS42ODY3NzcsNDcyLjA2MzI3MyBMMjQ1LjY4Njc3Nyw0NjMuMjIyOTE0IEMyNDUuNjg3NSw0NjIuNTYwOTE3IDI0NS4xNzAwNzgsNDYyLjAyNDcyOSAyNDQuNTMxMjUsNDYyLjAyNDcyOSBaIiBpZD0iQ29tYmluZWQtU2hhcGUiPjwvcGF0aD4KICAgICAgICA8L2c+CiAgICA8L2c+Cjwvc3ZnPg==';
686
687 $this->_libraryPage = add_menu_page( __( 'Visualizer', 'visualizer' ), __( 'Visualizer', 'visualizer' ), 'edit_posts', Visualizer_Plugin::NAME, array( $this, 'renderLibraryPage' ), $svg_base64_icon, 99.7666 );
688
689 add_submenu_page(
690 Visualizer_Plugin::NAME,
691 __( 'Chart Library', 'visualizer' ),
692 __( 'Chart Library', 'visualizer' ),
693 'edit_posts',
694 'admin.php?page=' . Visualizer_Plugin::NAME
695 );
696 add_submenu_page(
697 Visualizer_Plugin::NAME,
698 __( 'Add New Chart', 'visualizer' ),
699 __( 'Add New Chart', 'visualizer' ),
700 'edit_posts',
701 'admin.php?page=' . Visualizer_Plugin::NAME . '&vaction=addnew'
702 );
703 add_submenu_page(
704 Visualizer_Plugin::NAME,
705 __( 'Support', 'visualizer' ),
706 __( '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>',
707 'edit_posts',
708 'viz-support',
709 array( $this, 'renderSupportPage' )
710 );
711
712 remove_submenu_page( Visualizer_Plugin::NAME, Visualizer_Plugin::NAME );
713
714 add_action( "load-{$this->_libraryPage}", array( $this, 'addScreenOptions' ) );
715 add_action( 'admin_footer', array( $this, 'handleGetProSubMenu' ) );
716 }
717
718 /**
719 * Handle get pro plugin submenu.
720 */
721 public function handleGetProSubMenu() {
722 if ( ! Visualizer_Module::is_pro() ) {
723 ?>
724 <style type="text/css">
725 #toplevel_page_visualizer ul.wp-submenu li:last-child {
726 background: #FF7E65;
727 font-size: 14px;
728 font-weight: 600;
729 color: #fff;
730 }
731 #toplevel_page_visualizer ul.wp-submenu li:last-child > a {
732 color: #fff !important;
733 }
734 #toplevel_page_visualizer ul.wp-submenu li:last-child > a:hover {
735 box-shadow: inherit;
736 }
737 </style>
738 <?php
739 if ( get_option( 'visualizer_fresh_install', false ) ) {
740 ?>
741 <style type="text/css">
742 #toplevel_page_visualizer ul.wp-submenu li.wp-first-item + li + li + li {
743 display: none;
744 }
745 </style>
746 <?php
747 }
748 }
749 }
750
751 /**
752 * Adds the screen options for pagination.
753 */
754 function addScreenOptions() {
755 $screen = get_current_screen();
756
757 // bail if it's some other page.
758 if ( ! is_object( $screen ) || $screen->id !== $this->_libraryPage ) {
759 return;
760 }
761
762 $args = array(
763 'label' => __( 'Number of charts per page:', 'visualizer' ),
764 'default' => 6,
765 'option' => 'visualizer_library_per_page',
766 );
767 add_screen_option( 'per_page', $args );
768 }
769
770 /**
771 * Returns the screen option for pagination.
772 */
773 function setScreenOptions( $status, $option, $value ) {
774 if ( 'visualizer_library_per_page' === $option ) {
775 return $value;
776 }
777 }
778
779 /**
780 * Adds the display filters to be used in the meta_query while displaying the charts.
781 */
782 private function getDisplayFilters( &$query_args ) {
783 $query = array();
784 global $sitepress;
785 if ( Visualizer_Module::is_pro() && ( function_exists( 'icl_get_languages' ) && $sitepress instanceof \SitePress ) ) {
786 $current_lang = icl_get_current_language();
787 if ( in_array( $current_lang, array( 'all', icl_get_default_language() ), true ) ) {
788 $query[] = array(
789 'key' => 'chart_lang',
790 'compare' => 'NOT EXISTS',
791 );
792 } else {
793 $query[] = array(
794 'key' => 'chart_lang',
795 'value' => $current_lang,
796 'compare' => '=',
797 );
798 }
799 }
800
801 // add chart type filter to the query arguments
802 $type = filter_input( INPUT_GET, 'type' );
803 if ( $type && in_array( $type, Visualizer_Plugin::getChartTypes(), true ) ) {
804 $query[] = array(
805 'key' => Visualizer_Plugin::CF_CHART_TYPE,
806 'value' => $type,
807 'compare' => '=',
808 );
809 }
810
811 // add chart library filter to the query arguments
812 $library = filter_input( INPUT_GET, 'library' );
813 if ( $library ) {
814 $query[] = array(
815 'key' => Visualizer_Plugin::CF_CHART_LIBRARY,
816 'value' => $library,
817 'compare' => '=',
818 );
819 }
820
821 // add date filter to the query arguments
822 $date = filter_input( INPUT_GET, 'date' );
823 $possible = array_keys( Visualizer_Plugin::getSupportedDateFilter() );
824 if ( $date && in_array( $date, $possible, true ) ) {
825 $query_args['date_query'] = array(
826 'after' => "$date -1 day",
827 'inclusive' => true,
828 );
829 }
830
831 // add source filter to the query arguments
832 $source = filter_input( INPUT_GET, 'source' );
833 if ( $source ) {
834 $source = ucwords( $source );
835 $source = "Visualizer_Source_{$source}";
836 $query[] = array(
837 'key' => Visualizer_Plugin::CF_SOURCE,
838 'value' => $source,
839 'compare' => '=',
840 );
841 }
842
843 $query_args['meta_query'] = $query;
844
845 $orderby = filter_input( INPUT_GET, 'orderby' );
846 $order = filter_input( INPUT_GET, 'order' );
847 if ( $orderby ) {
848 $query_args['order_by'] = $orderby;
849 }
850 $query_args['order'] = empty( $order ) ? 'desc' : $order;
851 }
852
853 /**
854 * Get the instance of WP_Query that fetches the charts as per the given criteria.
855 */
856 private function getQuery() {
857 static $q;
858 if ( ! is_null( $q ) ) {
859 return $q;
860 }
861
862 // get current page
863 $page = filter_input(
864 INPUT_GET,
865 'vpage',
866 FILTER_VALIDATE_INT,
867 array(
868 'options' => array(
869 'min_range' => 1,
870 'default' => 1,
871 ),
872 )
873 );
874
875 $per_page = 6;
876 $screen = get_current_screen();
877 if ( $screen ) {
878 // retrieve the per_page option
879 $screen_option = $screen->get_option( 'per_page', 'option' );
880 // retrieve the value stored for the current user
881 $user = get_current_user_id();
882 $per_page = get_user_meta( $user, $screen_option, true );
883 if ( empty( $per_page ) || $per_page < 1 ) {
884 // nothing set, get the default value
885 $per_page = $screen->get_option( 'per_page', 'default' );
886 }
887 }
888
889 // the initial query arguments to fetch charts
890 $query_args = array(
891 'post_type' => Visualizer_Plugin::CPT_VISUALIZER,
892 'posts_per_page' => $per_page,
893 'paged' => $page,
894 );
895
896 $this->getDisplayFilters( $query_args );
897
898 // Added by Ash/Upwork
899 $filterByMeta = ! empty( $_GET['s'] ) ? sanitize_text_field( wp_unslash( $_GET['s'] ) ) : null; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
900 if ( $filterByMeta ) {
901 $query = array(
902 'key' => Visualizer_Plugin::CF_SETTINGS,
903 'value' => $filterByMeta,
904 'compare' => 'LIKE',
905 );
906 $meta = isset( $query_args['meta_query'] ) ? $query_args['meta_query'] : array();
907 $meta[] = $query;
908 $query_args['meta_query'] = $meta;
909 }
910 $q = new WP_Query( apply_filters( 'visualizer_query_args', $query_args ) );
911 return $q;
912 }
913
914 /**
915 * Renders support page.
916 *
917 * @since 3.3.0
918 *
919 * @access public
920 */
921 public function renderSupportPage() {
922 wp_enqueue_style( 'visualizer-upsell', VISUALIZER_ABSURL . 'css/upsell.css', array(), Visualizer_Plugin::VERSION );
923 $this->load_survey();
924 include_once VISUALIZER_ABSPATH . '/templates/support.php';
925 }
926
927 /**
928 * Renders visualizer library page.
929 *
930 * @since 1.0.0
931 *
932 * @access public
933 */
934 public function renderLibraryPage() {
935 $charts = array();
936 $query = $this->getQuery();
937
938 // get current page
939 $page = filter_input(
940 INPUT_GET,
941 'vpage',
942 FILTER_VALIDATE_INT,
943 array(
944 'options' => array(
945 'min_range' => 1,
946 'default' => 1,
947 ),
948 )
949 );
950 // add chart type filter to the query arguments
951 $filter = filter_input( INPUT_GET, 'type' );
952 if ( ! ( $filter && in_array( $filter, Visualizer_Plugin::getChartTypes(), true ) ) ) {
953 $filter = 'all';
954 }
955
956 $css = '';
957 while ( $query->have_posts() ) {
958 $chart = $query->next_post();
959
960 // 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.
961 $chart = $this->handleExistingRevisions( $chart->ID, $chart );
962 // refresh a "live" db query chart.
963 $chart = apply_filters( 'visualizer_schedule_refresh_chart', $chart, $chart->ID, false );
964
965 $type = get_post_meta( $chart->ID, Visualizer_Plugin::CF_CHART_TYPE, true );
966
967 // fetch and update settings
968 $settings = get_post_meta( $chart->ID, Visualizer_Plugin::CF_SETTINGS, true );
969
970 $settings = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_SETTINGS, $settings, $chart->ID, $type );
971 if ( ! empty( $atts['settings'] ) ) {
972 $settings = apply_filters( $atts['settings'], $settings, $chart->ID, $type );
973 }
974
975 if ( $settings ) {
976 unset( $settings['height'], $settings['width'], $settings['chartArea'] );
977 }
978
979 $series = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_SERIES, get_post_meta( $chart->ID, Visualizer_Plugin::CF_SERIES, true ), $chart->ID, $type );
980 $data = self::get_chart_data( $chart, $type );
981
982 // Set default setting series when add manual chart data - Only during first creation.
983 if ( isset( $settings['series'] ) && ! empty( $series ) ) {
984 $count_series = count( $series ) - count( $settings['series'] );
985 if ( $count_series > 1 ) {
986 $clone_last_series = end( $settings['series'] );
987 $clone_last_series = array_fill_keys( array_keys( $clone_last_series ), '' );
988 foreach ( range( 1, $count_series ) as $item ) {
989 $settings['series'][] = $clone_last_series;
990 }
991 }
992 }
993
994 $library = $this->load_chart_type( $chart->ID );
995
996 $id = 'visualizer-' . $chart->ID;
997 $arguments = $this->get_inline_custom_css( $id, $settings );
998 if ( ! empty( $arguments ) ) {
999 $css .= $arguments[0];
1000 $settings = $arguments[1];
1001 }
1002
1003 if ( isset( $settings['controls']['ui']['labelStacking'] ) ) {
1004 unset( $settings['controls']['ui']['labelStacking'] );
1005 }
1006 if ( isset( $settings['controls']['ui']['orientation'] ) ) {
1007 unset( $settings['controls']['ui']['orientation'] );
1008 }
1009
1010 // add chart to the array
1011 $charts[ $id ] = array(
1012 'id' => $chart->ID,
1013 'type' => $type,
1014 'series' => $series,
1015 'settings' => $settings,
1016 'data' => $data,
1017 'library' => $library,
1018 );
1019 }
1020 // enqueue charts array
1021 $ajaxurl = admin_url( 'admin-ajax.php' );
1022 wp_localize_script(
1023 'visualizer-library',
1024 'visualizer',
1025 array(
1026 'language' => $this->get_language(),
1027 'map_api_key' => get_option( 'visualizer-map-api-key' ),
1028 'charts' => $charts,
1029 'urls' => array(
1030 'base' => esc_url( add_query_arg( array( 'vpage' => false, 'vaction' => false ) ) ),
1031 'create' => esc_url(
1032 add_query_arg(
1033 array(
1034 'action' => Visualizer_Plugin::ACTION_CREATE_CHART,
1035 'library' => 'yes',
1036 'type' => isset( $_GET['type'] ) ? $_GET['type'] : '',
1037 'chart-library' => isset( $_GET['chart-library'] ) ? $_GET['chart-library'] : '',
1038 'vaction' => false,
1039 ),
1040 $ajaxurl
1041 )
1042 ),
1043 'edit' => esc_url(
1044 add_query_arg(
1045 array(
1046 'action' => Visualizer_Plugin::ACTION_EDIT_CHART,
1047 'library' => 'yes',
1048 'vaction' => false,
1049 ),
1050 $ajaxurl
1051 )
1052 ),
1053 ),
1054 'page_type' => 'library',
1055 'is_front' => false,
1056 'i10n' => array(
1057 'copied' => __( 'The shortcode has been copied to your clipboard. Hit Ctrl-V/Cmd-V to paste it.', 'visualizer' ),
1058 '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' ),
1059 ),
1060 'is_pro_user' => Visualizer_Module::is_pro(),
1061 )
1062 );
1063 // render library page
1064 $render = new Visualizer_Render_Library();
1065 $render->charts = $charts;
1066 $render->type = $filter;
1067 $render->types = self::_getChartTypesLocalized( false, false, false, true );
1068 $render->custom_css = $css;
1069 $render->pagination = paginate_links(
1070 array(
1071 'base' => add_query_arg( array( 'vpage' => '%#%', 'vaction' => false ) ),
1072 'format' => '',
1073 'current' => $page,
1074 'total' => $query->max_num_pages,
1075 'type' => 'array',
1076 )
1077 );
1078
1079 $this->load_survey();
1080
1081 $render->render();
1082 }
1083
1084 /**
1085 * Updates the plugin's action links, which will be rendered at the plugins table.
1086 *
1087 * @since 1.0.0
1088 *
1089 * @access public
1090 *
1091 * @param array $links The array of original action links.
1092 * @param string $file The plugin basename.
1093 *
1094 * @return array Updated array of action links.
1095 */
1096 public function getPluginActionLinks( $links, $file ) {
1097 if ( $file === plugin_basename( VISUALIZER_BASEFILE ) ) {
1098 array_unshift(
1099 $links,
1100 sprintf(
1101 '<a href="%s">%s</a>',
1102 admin_url( 'admin.php?page=' . Visualizer_Plugin::NAME ),
1103 esc_html__( 'Library', 'visualizer' )
1104 )
1105 );
1106 }
1107
1108 return $links;
1109 }
1110
1111 /**
1112 * Updates the plugin's meta links, which will be rendered at the plugins table.
1113 *
1114 * @since 1.0.0
1115 *
1116 * @access public
1117 *
1118 * @param array $plugin_meta The array of a plugin meta links.
1119 * @param string $plugin_file The plugin's basename.
1120 *
1121 * @return array Updated array of plugin meta links.
1122 */
1123 public function getPluginMetaLinks( $plugin_meta, $plugin_file ) {
1124 if ( $plugin_file === plugin_basename( VISUALIZER_BASEFILE ) ) {
1125 // knowledge base link
1126 $plugin_meta[] = sprintf(
1127 '<a href="' . VISUALIZER_MAIN_DOC . '" target="_blank">%s</a>',
1128 esc_html__( 'Docs', 'visualizer' )
1129 );
1130 // flattr link
1131 $plugin_meta[] = sprintf(
1132 '<a style="color:red" href="' . tsdk_utmify( Visualizer_Plugin::PRO_TEASER_URL, 'pluginrow' ) . '" target="_blank">%s</a>',
1133 esc_html__( 'Pro Addon', 'visualizer' )
1134 );
1135 }
1136
1137 return $plugin_meta;
1138 }
1139
1140 /**
1141 * If check is existing user.
1142 *
1143 * @return bool Default false
1144 */
1145 public static function proFeaturesLocked() {
1146 if ( Visualizer_Module::is_pro() ) {
1147 return true;
1148 }
1149 return 'yes' === get_option( 'visualizer-new-user', 'yes' ) ? false : true;
1150 }
1151
1152 /**
1153 * Multilingual Support.
1154 *
1155 * @param int $chart_id Chart ID.
1156 * @return bool Default false
1157 */
1158 public function addMultilingualSupport( $chart_id ) {
1159 global $sitepress;
1160 if ( Visualizer_Module::is_pro() ) {
1161 return;
1162 }
1163 if ( function_exists( 'icl_get_languages' ) && $sitepress instanceof \SitePress ) {
1164 $language = icl_get_languages();
1165 $current_lang = icl_get_current_language();
1166 $default_lang = icl_get_default_language();
1167 $post_info = wpml_get_language_information( null, $chart_id );
1168 $translations = array();
1169 if ( ! empty( $post_info ) && ( $default_lang === $post_info['language_code'] ) ) {
1170 $trid = $sitepress->get_element_trid( $chart_id, 'post_' . Visualizer_Plugin::CPT_VISUALIZER );
1171 $translations = $sitepress->get_element_translations( $trid );
1172 }
1173 if ( empty( $translations ) ) {
1174 return;
1175 }
1176 ?>
1177 <hr><div class="visualizer-languages-list only-pro">
1178 <?php
1179 foreach ( $language as $lang ) {
1180 $lang_code = $lang['code'];
1181 if ( $current_lang !== $lang_code ) {
1182 ?>
1183 <a href="javascript:;">
1184 <img src="<?php echo esc_url( $lang['country_flag_url'] ); ?>" alt="<?php echo esc_attr( $lang['translated_name'] ); ?>">
1185 </a>
1186 <?php
1187 }
1188 }
1189 ?>
1190 <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>
1191 </div>
1192 <?php
1193 }
1194 }
1195
1196 /**
1197 * Check chart is enabled or not.
1198 *
1199 * @param string $type Chart ID.
1200 *
1201 * @return bool Default false
1202 */
1203 public static function checkChartStatus( $type ) {
1204 $types = self::_getChartTypesLocalized( false, false, false, true );
1205 if ( isset( $types[ $type ] ) ) {
1206 return ! empty( $types[ $type ]['enabled'] );
1207 }
1208 return false;
1209 }
1210
1211 /**
1212 * Get the survey metadata.
1213 *
1214 * @return array The survey metadata.
1215 */
1216 private function get_survey_metadata() {
1217 $install_date = get_option( 'visualizer_install', false );
1218 $install_category = 0;
1219
1220 if ( false !== $install_date ) {
1221 $days_since_install = round( ( time() - $install_date ) / DAY_IN_SECONDS );
1222
1223 if ( 0 === $days_since_install || 1 === $days_since_install ) {
1224 $install_category = 0;
1225 } elseif ( 1 < $days_since_install && 8 > $days_since_install ) {
1226 $install_category = 7;
1227 } elseif ( 8 <= $days_since_install && 31 > $days_since_install ) {
1228 $install_category = 30;
1229 } elseif ( 30 < $days_since_install && 90 > $days_since_install ) {
1230 $install_category = 90;
1231 } elseif ( 90 <= $days_since_install ) {
1232 $install_category = 91;
1233 }
1234 }
1235
1236 $plugin_data = get_plugin_data( VISUALIZER_BASEFILE, false, false );
1237 $plugin_version = '';
1238 if ( ! empty( $plugin_data['Version'] ) ) {
1239 $plugin_version = $plugin_data['Version'];
1240 }
1241
1242 $user_id = 'visualizer_' . preg_replace( '/[^\w\d]*/', '', get_site_url() ); // Use a normalized version of the site URL as a user ID.
1243
1244 $license_data = get_option( 'visualizer_pro_license_data', false );
1245 if ( false !== $license_data && isset( $license_data->key ) ) {
1246 $user_id = 'visualizer_' . $license_data->key;
1247 }
1248
1249 return array(
1250 'userId' => $user_id,
1251 'attributes' => array(
1252 'days_since_install' => strval( $install_category ),
1253 'free_version' => $plugin_version,
1254 'pro_version' => defined( 'VISUALIZER_PRO_VERSION' ) ? VISUALIZER_PRO_VERSION : '',
1255 'license_status' => apply_filters( 'product_visualizer_license_status', 'invalid' ),
1256 ),
1257 );
1258 }
1259
1260 /**
1261 * Load the survey.
1262 */
1263 private function load_survey() {
1264
1265 if ( defined( 'TI_CYPRESS_TESTING' ) ) {
1266 return;
1267 }
1268
1269 $survey_handler = apply_filters( 'themeisle_sdk_dependency_script_handler', 'survey' );
1270
1271 if ( empty( $survey_handler ) ) {
1272 return;
1273 }
1274
1275 $metadata = $this->get_survey_metadata();
1276
1277 do_action( 'themeisle_sdk_dependency_enqueue_script', 'survey' );
1278 wp_enqueue_script( 'visualizer_chart_survey', VISUALIZER_ABSURL . 'js/survey.js', array( $survey_handler ), $metadata['attributes']['free_version'], true );
1279 wp_localize_script( 'visualizer_chart_survey', 'visualizerSurveyData', $metadata );
1280 }
1281 }
1282