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

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

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