PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.10.8
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.10.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 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.10.8, at classes/Visualizer/Module/Admin.php

1,261 lines 40.0 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 if ( defined( 'TI_CYPRESS_TESTING' ) ) {
80 $this->load_cypress_hooks();
81 }
82
83 }
84
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 /**
158 * No limits on revisions.
159 */
160 public function limitRevisions( $num, $post ) {
161 if ( Visualizer_Plugin::CPT_VISUALIZER === $post->post_type ) {
162 return -1;
163 }
164 return $num;
165 }
166
167 /**
168 * Add a revision.
169 */
170 public function addRevision( $revision_id ) {
171 $parent_id = wp_is_post_revision( $revision_id );
172 if ( Visualizer_Plugin::CPT_VISUALIZER === get_post_type( $parent_id ) ) {
173 // add the meta data to this revision.
174 $meta = get_post_meta( $parent_id, '', true );
175
176 if ( $meta ) {
177 foreach ( $meta as $key => $value ) {
178 if ( 0 === strpos( $key, 'visualizer' ) ) {
179 add_metadata( 'post', $revision_id, $key, maybe_unserialize( $value[0] ) );
180 }
181 }
182 }
183 }
184 }
185
186 /**
187 * Restore a revision.
188 */
189 public function restoreRevision( $post_id, $revision_id ) {
190 if ( Visualizer_Plugin::CPT_VISUALIZER === get_post_type( $post_id ) ) {
191 // get the meta information from the revision.
192 $meta = get_metadata( 'post', $revision_id, '', true );
193
194 // delete all meta information from the post before adding.
195 $post_meta = get_post_meta( $post_id, '', true );
196 if ( $post_meta ) {
197 foreach ( $meta as $key => $value ) {
198 if ( 0 === strpos( $key, 'visualizer' ) ) {
199 delete_post_meta( $post_id, $key );
200 }
201 }
202 }
203
204 if ( $meta ) {
205 foreach ( $meta as $key => $value ) {
206 if ( 0 === strpos( $key, 'visualizer' ) ) {
207 add_post_meta( $post_id, $key, maybe_unserialize( $value[0] ) );
208 }
209 }
210 }
211 }
212 }
213
214 /**
215 * Admin init.
216 *
217 * @access public
218 */
219 public function init() {
220 // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
221 if ( current_user_can( 'edit_posts' ) && current_user_can( 'edit_pages' ) && 'true' == get_user_option( 'rich_editing' ) ) {
222 $this->_addFilter( 'mce_external_languages', 'add_tinymce_lang', 10, 1 );
223 $this->_addFilter( 'mce_external_plugins', 'tinymce_plugin', 10, 1 );
224 $this->_addFilter( 'mce_buttons', 'register_mce_button', 10, 1 );
225 $this->_addFilter( 'tiny_mce_before_init', 'get_strings_for_block', 10, 1 );
226 }
227 }
228
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 /**
243 * Load plugin translation for - TinyMCE API
244 *
245 * @access public
246 * @param array $arr The tinymce_lang array.
247 * @return array
248 */
249 public function add_tinymce_lang( $arr ) {
250 $ui_lang = VISUALIZER_ABSPATH . '/classes/Visualizer/Module/Language.php';
251 $ui_lang = apply_filters( 'visualizer_ui_lang_filter', $ui_lang );
252 $arr[] = $ui_lang;
253 return $arr;
254 }
255
256 /**
257 * Load custom js options - TinyMCE API
258 *
259 * @access public
260 * @param array $plugin_array The tinymce plugin array.
261 * @return array
262 */
263 public function tinymce_plugin( $plugin_array ) {
264 $plugin_array['visualizer_mce_button'] = VISUALIZER_ABSURL . 'js/mce.js';
265 return $plugin_array;
266 }
267
268 /**
269 * Register new button in the editor
270 *
271 * @access public
272 * @param array $buttons The tinymce buttons array.
273 * @return array
274 */
275 public function register_mce_button( $buttons ) {
276 array_push( $buttons, 'visualizer_mce_button' );
277 return $buttons;
278 }
279
280 /**
281 * Whether to show the feedback review or not.
282 *
283 * @access public
284 */
285 public function feedbackReviewTrigger( $dumb ) {
286 $query = new WP_Query(
287 array(
288 'posts_per_page' => 50,
289 'post_type' => Visualizer_Plugin::CPT_VISUALIZER,
290 'fields' => 'ids',
291 'update_post_meta_cache' => false,
292 'update_post_term_cache' => false,
293 )
294 );
295
296 if ( $query->have_posts() && $query->post_count > 0 ) {
297 return true;
298 }
299 return false;
300 }
301
302 /**
303 * Enqueues media scripts and styles.
304 *
305 * @since 1.0.0
306 * @uses wp_enqueue_style To enqueue style file.
307 * @uses wp_enqueue_script To enqueue script file.
308 *
309 * @access public
310 */
311 public function enqueueMediaScripts() {
312 global $typenow;
313 if ( post_type_supports( $typenow, 'editor' ) ) {
314 wp_enqueue_style( 'visualizer-media', VISUALIZER_ABSURL . 'css/media.css', array( 'media-views' ), Visualizer_Plugin::VERSION );
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 );
323 wp_enqueue_script( 'visualizer-media-collection', VISUALIZER_ABSURL . 'js/media/collection.js', array( 'visualizer-media-model' ), Visualizer_Plugin::VERSION, true );
324 wp_enqueue_script( 'visualizer-media-controller', VISUALIZER_ABSURL . 'js/media/controller.js', array( 'visualizer-media-collection' ), Visualizer_Plugin::VERSION, true );
325 wp_enqueue_script( 'visualizer-media-view', VISUALIZER_ABSURL . 'js/media/view.js', array( 'visualizer-media-controller' ), Visualizer_Plugin::VERSION, true );
326 wp_localize_script(
327 'visualizer-media-view',
328 'visualizer',
329 array(
330 'i10n' => array(
331 'insert' => __( 'Insert', 'visualizer' ),
332 ),
333 )
334 );
335 wp_enqueue_script( 'visualizer-media-toolbar', VISUALIZER_ABSURL . 'js/media/toolbar.js', array( 'visualizer-media-view' ), Visualizer_Plugin::VERSION, true );
336 wp_enqueue_script( 'visualizer-media', VISUALIZER_ABSURL . 'js/media.js', array( 'visualizer-media-toolbar' ), Visualizer_Plugin::VERSION, true );
337 }
338 }
339
340 /**
341 * Extends media view strings with visualizer strings.
342 *
343 * @since 1.0.0
344 *
345 * @access public
346 *
347 * @param array $strings The array of media view strings.
348 *
349 * @return array The extended array of media view strings.
350 */
351 public function setupMediaViewStrings( $strings ) {
352 $chart_types = self::_getChartTypesLocalized( true, true, true );
353 $strings['visualizer'] = array(
354 'actions' => array(
355 'get_charts' => Visualizer_Plugin::ACTION_GET_CHARTS,
356 'delete_chart' => Visualizer_Plugin::ACTION_DELETE_CHART,
357 ),
358 'controller' => array(
359 'title' => esc_html__( 'Visualizations', 'visualizer' ),
360 ),
361 'routers' => array(
362 'library' => esc_html__( 'From Library', 'visualizer' ),
363 'create' => esc_html__( 'Create New', 'visualizer' ),
364 ),
365 'library' => array(
366 'filters' => $chart_types,
367 'types' => array_keys( $chart_types ),
368 ),
369 'nonce' => wp_create_nonce(),
370 'buildurl' => esc_url( add_query_arg( 'action', Visualizer_Plugin::ACTION_CREATE_CHART, admin_url( 'admin-ajax.php' ) ) ),
371 );
372
373 return $strings;
374 }
375
376 /**
377 * Returns associated array of chart types and localized names.
378 *
379 * @since 1.0.0
380 *
381 * @static
382 * @access private
383 * @return array The associated array of chart types with localized names.
384 */
385 public static function _getChartTypesLocalized( $enabledOnly = false, $get2Darray = false, $add_select = false, $where = null ) {
386 $additional = array();
387 if ( $add_select ) {
388 $additional['select'] = array(
389 'name' => esc_html__( 'All', 'visualizer' ),
390 'enabled' => true,
391 );
392 }
393
394 $enabled = self::proFeaturesLocked();
395
396 $types = array_merge(
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 ),
404 'pie' => array(
405 'name' => esc_html__( 'Pie/Donut', 'visualizer' ),
406 'enabled' => true,
407 'supports' => $enabled ? array( 'Google Charts', 'ChartJS' ) : array( 'Google Charts' ),
408 ),
409 'line' => array(
410 'name' => esc_html__( 'Line', 'visualizer' ),
411 'enabled' => true,
412 'supports' => $enabled ? array( 'Google Charts', 'ChartJS' ) : array( 'Google Charts' ),
413 ),
414 'bar' => array(
415 'name' => esc_html__( 'Bar', 'visualizer' ),
416 'enabled' => true,
417 'supports' => $enabled ? array( 'Google Charts', 'ChartJS' ) : array( 'Google Charts' ),
418 ),
419 'area' => array(
420 'name' => esc_html__( 'Area', 'visualizer' ),
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' ),
424 ),
425 'geo' => array(
426 'name' => esc_html__( 'Geo', 'visualizer' ),
427 'enabled' => $enabled,
428 'supports' => array( 'Google Charts' ),
429 ),
430 'column' => array(
431 'name' => esc_html__( 'Column', 'visualizer' ),
432 'enabled' => $enabled,
433 'supports' => array( 'Google Charts', 'ChartJS' ),
434 ),
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' ),
440 ),
441 'scatter' => array(
442 'name' => esc_html__( 'Scatter', 'visualizer' ),
443 'enabled' => $enabled,
444 'supports' => array( 'Google Charts' ),
445 ),
446 'gauge' => array(
447 'name' => esc_html__( 'Gauge', 'visualizer' ),
448 'enabled' => $enabled,
449 'supports' => array( 'Google Charts' ),
450 ),
451 'candlestick' => array(
452 'name' => esc_html__( 'Candlestick', 'visualizer' ),
453 'enabled' => $enabled,
454 'supports' => array( 'Google Charts' ),
455 ),
456 // pro types
457 'timeline' => array(
458 'name' => esc_html__( 'Timeline', 'visualizer' ),
459 'enabled' => false,
460 'supports' => array( 'Google Charts', 'ChartJS' ),
461 ),
462 'combo' => array(
463 'name' => esc_html__( 'Combo', 'visualizer' ),
464 'enabled' => false,
465 'supports' => array( 'Google Charts' ),
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 ),
477 )
478 );
479 $types = apply_filters( 'visualizer_pro_chart_types', $types );
480 if ( $enabledOnly ) {
481 $filtered = array();
482 foreach ( $types as $type => $array ) {
483 if ( ! is_array( $array ) ) {
484 // support for old pro
485 $array = array( 'enabled' => true, 'name' => $array );
486 }
487 // backward compatibility for PRO before v1.9.0
488 if ( ! array_key_exists( 'supports', $array ) ) {
489 $array['supports'] = array( 'Google Charts' );
490 }
491 if ( ! $array['enabled'] ) {
492 continue;
493 }
494 $filtered[ $type ] = $array;
495 }
496 $types = $filtered;
497 }
498 if ( $get2Darray ) {
499 $doubleD = array();
500 foreach ( $types as $type => $array ) {
501 if ( ! is_array( $array ) ) {
502 // support for old pro
503 $array = array( 'enabled' => true, 'name' => $array );
504 }
505 // backward compatibility for PRO before v1.9.0
506 if ( ! array_key_exists( 'supports', $array ) ) {
507 $array['supports'] = array( 'Google Charts' );
508 }
509 $doubleD[ $type ] = $array['name'];
510 }
511 $types = $doubleD;
512 }
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
571 return $types;
572 }
573
574 /**
575 * Renders templates to use in media popup.
576 *
577 * @since 1.0.0
578 * @global string $pagenow The name of the current page.
579 *
580 * @access public
581 */
582 public function renderTemplates() {
583 global $pagenow;
584 if ( 'post.php' !== $pagenow && 'post-new.php' !== $pagenow ) {
585 return;
586 }
587 $render = new Visualizer_Render_Templates();
588 $render->render();
589 }
590
591 /**
592 * Enqueues library scripts and styles.
593 *
594 * @since 1.0.0
595 * @uses wp_enqueue_style() To enqueue library stylesheet.
596 * @uses wp_enqueue_script() To enqueue javascript file.
597 * @uses wp_enqueue_media() To enqueue media stuff.
598 *
599 * @access public
600 *
601 * @param string $suffix The current page suffix.
602 */
603 public function enqueueLibraryScripts( $suffix ) {
604 if ( $suffix === $this->_libraryPage ) {
605 wp_enqueue_style( 'visualizer-library', VISUALIZER_ABSURL . 'css/library.css', array(), Visualizer_Plugin::VERSION );
606 $this->_addFilter( 'media_upload_tabs', 'setupVisualizerTab' );
607 wp_enqueue_media();
608 wp_enqueue_script(
609 'visualizer-library',
610 VISUALIZER_ABSURL . 'js/library.js',
611 array(
612 'jquery',
613 'media-views',
614 'clipboard',
615 ),
616 Visualizer_Plugin::VERSION,
617 true
618 );
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 }
637 }
638 }
639
640 /**
641 * Adds visualizer tab for media upload tabs array.
642 *
643 * @since 1.0.0
644 *
645 * @access public
646 *
647 * @param array $tabs The array of media upload tabs.
648 *
649 * @return array Extended array of media upload tabs.
650 */
651 public function setupVisualizerTab( $tabs ) {
652 $tabs['visualizer'] = 'Visualizer';
653
654 return $tabs;
655 }
656
657 /**
658 * Registers admin menu for visualizer library.
659 *
660 * @since 1.0.0
661 *
662 * @access public
663 */
664 public function registerAdminMenu() {
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.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.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 remove_submenu_page( Visualizer_Plugin::NAME, Visualizer_Plugin::NAME );
693
694 add_action( "load-{$this->_libraryPage}", array( $this, 'addScreenOptions' ) );
695 add_action( 'admin_footer', array( $this, 'handleGetProSubMenu' ) );
696 }
697
698 /**
699 * Handle get pro plugin submenu.
700 */
701 public function handleGetProSubMenu() {
702 if ( ! Visualizer_Module::is_pro() ) {
703 ?>
704 <style type="text/css">
705 #toplevel_page_visualizer ul.wp-submenu li:last-child {
706 background: #FF7E65;
707 font-size: 14px;
708 font-weight: 600;
709 color: #fff;
710 }
711 #toplevel_page_visualizer ul.wp-submenu li:last-child > a {
712 color: #fff !important;
713 }
714 #toplevel_page_visualizer ul.wp-submenu li:last-child > a:hover {
715 box-shadow: inherit;
716 }
717 </style>
718 <?php
719 if ( get_option( 'visualizer_fresh_install', false ) ) {
720 ?>
721 <style type="text/css">
722 #toplevel_page_visualizer ul.wp-submenu li.wp-first-item + li + li + li {
723 display: none;
724 }
725 </style>
726 <?php
727 }
728 }
729 }
730
731 /**
732 * Adds the screen options for pagination.
733 */
734 function addScreenOptions() {
735 $screen = get_current_screen();
736
737 // bail if it's some other page.
738 if ( ! is_object( $screen ) || $screen->id !== $this->_libraryPage ) {
739 return;
740 }
741
742 $args = array(
743 'label' => __( 'Number of charts per page:', 'visualizer' ),
744 'default' => 6,
745 'option' => 'visualizer_library_per_page',
746 );
747 add_screen_option( 'per_page', $args );
748 }
749
750 /**
751 * Returns the screen option for pagination.
752 */
753 function setScreenOptions( $status, $option, $value ) {
754 if ( 'visualizer_library_per_page' === $option ) {
755 return $value;
756 }
757 }
758
759 /**
760 * Adds the display filters to be used in the meta_query while displaying the charts.
761 */
762 private function getDisplayFilters( &$query_args ) {
763 $query = array();
764 global $sitepress;
765 if ( Visualizer_Module::is_pro() && ( function_exists( 'icl_get_languages' ) && $sitepress instanceof \SitePress ) ) {
766 $current_lang = icl_get_current_language();
767 if ( in_array( $current_lang, array( 'all', icl_get_default_language() ), true ) ) {
768 $query[] = array(
769 'key' => 'chart_lang',
770 'compare' => 'NOT EXISTS',
771 );
772 } else {
773 $query[] = array(
774 'key' => 'chart_lang',
775 'value' => $current_lang,
776 'compare' => '=',
777 );
778 }
779 }
780
781 // add chart type filter to the query arguments
782 $type = filter_input( INPUT_GET, 'type' );
783 if ( $type && in_array( $type, Visualizer_Plugin::getChartTypes(), true ) ) {
784 $query[] = array(
785 'key' => Visualizer_Plugin::CF_CHART_TYPE,
786 'value' => $type,
787 'compare' => '=',
788 );
789 }
790
791 // add chart library filter to the query arguments
792 $library = filter_input( INPUT_GET, 'library' );
793 if ( $library ) {
794 $query[] = array(
795 'key' => Visualizer_Plugin::CF_CHART_LIBRARY,
796 'value' => $library,
797 'compare' => '=',
798 );
799 }
800
801 // add date filter to the query arguments
802 $date = filter_input( INPUT_GET, 'date' );
803 $possible = array_keys( Visualizer_Plugin::getSupportedDateFilter() );
804 if ( $date && in_array( $date, $possible, true ) ) {
805 $query_args['date_query'] = array(
806 'after' => "$date -1 day",
807 'inclusive' => true,
808 );
809 }
810
811 // add source filter to the query arguments
812 $source = filter_input( INPUT_GET, 'source' );
813 if ( $source ) {
814 $source = ucwords( $source );
815 $source = "Visualizer_Source_{$source}";
816 $query[] = array(
817 'key' => Visualizer_Plugin::CF_SOURCE,
818 'value' => $source,
819 'compare' => '=',
820 );
821 }
822
823 $query_args['meta_query'] = $query;
824
825 $orderby = filter_input( INPUT_GET, 'orderby' );
826 $order = filter_input( INPUT_GET, 'order' );
827 if ( $orderby ) {
828 $query_args['order_by'] = $orderby;
829 }
830 $query_args['order'] = empty( $order ) ? 'desc' : $order;
831 }
832
833 /**
834 * Get the instance of WP_Query that fetches the charts as per the given criteria.
835 */
836 private function getQuery() {
837 static $q;
838 if ( ! is_null( $q ) ) {
839 return $q;
840 }
841
842 // get current page
843 $page = filter_input(
844 INPUT_GET,
845 'vpage',
846 FILTER_VALIDATE_INT,
847 array(
848 'options' => array(
849 'min_range' => 1,
850 'default' => 1,
851 ),
852 )
853 );
854
855 $per_page = 6;
856 $screen = get_current_screen();
857 if ( $screen ) {
858 // retrieve the per_page option
859 $screen_option = $screen->get_option( 'per_page', 'option' );
860 // retrieve the value stored for the current user
861 $user = get_current_user_id();
862 $per_page = get_user_meta( $user, $screen_option, true );
863 if ( empty( $per_page ) || $per_page < 1 ) {
864 // nothing set, get the default value
865 $per_page = $screen->get_option( 'per_page', 'default' );
866 }
867 }
868
869 // the initial query arguments to fetch charts
870 $query_args = array(
871 'post_type' => Visualizer_Plugin::CPT_VISUALIZER,
872 'posts_per_page' => $per_page,
873 'paged' => $page,
874 );
875
876 $this->getDisplayFilters( $query_args );
877
878 // Added by Ash/Upwork
879 $filterByMeta = ! empty( $_GET['s'] ) ? sanitize_text_field( wp_unslash( $_GET['s'] ) ) : null; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
880 if ( $filterByMeta ) {
881 $query = array(
882 'key' => Visualizer_Plugin::CF_SETTINGS,
883 'value' => $filterByMeta,
884 'compare' => 'LIKE',
885 );
886 $meta = isset( $query_args['meta_query'] ) ? $query_args['meta_query'] : array();
887 $meta[] = $query;
888 $query_args['meta_query'] = $meta;
889 }
890 $q = new WP_Query( apply_filters( 'visualizer_query_args', $query_args ) );
891 return $q;
892 }
893
894 /**
895 * Renders support page.
896 *
897 * @since 3.3.0
898 *
899 * @access public
900 */
901 public function renderSupportPage() {
902 wp_enqueue_style( 'visualizer-upsell', VISUALIZER_ABSURL . 'css/upsell.css', array(), Visualizer_Plugin::VERSION );
903 $this->load_survey();
904 include_once VISUALIZER_ABSPATH . '/templates/support.php';
905 }
906
907 /**
908 * Renders visualizer library page.
909 *
910 * @since 1.0.0
911 *
912 * @access public
913 */
914 public function renderLibraryPage() {
915 $charts = array();
916 $query = $this->getQuery();
917
918 // get current page
919 $page = filter_input(
920 INPUT_GET,
921 'vpage',
922 FILTER_VALIDATE_INT,
923 array(
924 'options' => array(
925 'min_range' => 1,
926 'default' => 1,
927 ),
928 )
929 );
930 // add chart type filter to the query arguments
931 $filter = filter_input( INPUT_GET, 'type' );
932 if ( ! ( $filter && in_array( $filter, Visualizer_Plugin::getChartTypes(), true ) ) ) {
933 $filter = 'all';
934 }
935
936 $css = '';
937 while ( $query->have_posts() ) {
938 $chart = $query->next_post();
939
940 // 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.
941 $chart = $this->handleExistingRevisions( $chart->ID, $chart );
942 // refresh a "live" db query chart.
943 $chart = apply_filters( 'visualizer_schedule_refresh_chart', $chart, $chart->ID, false );
944
945 $type = get_post_meta( $chart->ID, Visualizer_Plugin::CF_CHART_TYPE, true );
946
947 // fetch and update settings
948 $settings = get_post_meta( $chart->ID, Visualizer_Plugin::CF_SETTINGS, true );
949
950 $settings = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_SETTINGS, $settings, $chart->ID, $type );
951 if ( ! empty( $atts['settings'] ) ) {
952 $settings = apply_filters( $atts['settings'], $settings, $chart->ID, $type );
953 }
954
955 if ( $settings ) {
956 unset( $settings['height'], $settings['width'], $settings['chartArea'] );
957 }
958
959 $series = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_SERIES, get_post_meta( $chart->ID, Visualizer_Plugin::CF_SERIES, true ), $chart->ID, $type );
960 $data = self::get_chart_data( $chart, $type );
961
962 // Set default setting series when add manual chart data - Only during first creation.
963 if ( isset( $settings['series'] ) && ! empty( $series ) ) {
964 $count_series = count( $series ) - count( $settings['series'] );
965 if ( $count_series > 1 ) {
966 $clone_last_series = end( $settings['series'] );
967 $clone_last_series = array_fill_keys( array_keys( $clone_last_series ), '' );
968 foreach ( range( 1, $count_series ) as $item ) {
969 $settings['series'][] = $clone_last_series;
970 }
971 }
972 }
973
974 $library = $this->load_chart_type( $chart->ID );
975
976 $id = 'visualizer-' . $chart->ID;
977 $arguments = $this->get_inline_custom_css( $id, $settings );
978 if ( ! empty( $arguments ) ) {
979 $css .= $arguments[0];
980 $settings = $arguments[1];
981 }
982
983 if ( isset( $settings['controls']['ui']['labelStacking'] ) ) {
984 unset( $settings['controls']['ui']['labelStacking'] );
985 }
986 if ( isset( $settings['controls']['ui']['orientation'] ) ) {
987 unset( $settings['controls']['ui']['orientation'] );
988 }
989
990 // add chart to the array
991 $charts[ $id ] = array(
992 'id' => $chart->ID,
993 'type' => $type,
994 'series' => $series,
995 'settings' => $settings,
996 'data' => $data,
997 'library' => $library,
998 );
999 }
1000 // enqueue charts array
1001 $ajaxurl = admin_url( 'admin-ajax.php' );
1002 wp_localize_script(
1003 'visualizer-library',
1004 'visualizer',
1005 array(
1006 'language' => $this->get_language(),
1007 'map_api_key' => get_option( 'visualizer-map-api-key' ),
1008 'charts' => $charts,
1009 'urls' => array(
1010 'base' => esc_url( add_query_arg( array( 'vpage' => false, 'vaction' => false ) ) ),
1011 'create' => esc_url(
1012 add_query_arg(
1013 array(
1014 'action' => Visualizer_Plugin::ACTION_CREATE_CHART,
1015 'library' => 'yes',
1016 'type' => isset( $_GET['type'] ) ? $_GET['type'] : '',
1017 'chart-library' => isset( $_GET['chart-library'] ) ? $_GET['chart-library'] : '',
1018 'vaction' => false,
1019 ),
1020 $ajaxurl
1021 )
1022 ),
1023 'edit' => esc_url(
1024 add_query_arg(
1025 array(
1026 'action' => Visualizer_Plugin::ACTION_EDIT_CHART,
1027 'library' => 'yes',
1028 'vaction' => false,
1029 ),
1030 $ajaxurl
1031 )
1032 ),
1033 ),
1034 'page_type' => 'library',
1035 'is_front' => false,
1036 'i10n' => array(
1037 'copied' => __( 'The shortcode has been copied to your clipboard. Hit Ctrl-V/Cmd-V to paste it.', 'visualizer' ),
1038 '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' ),
1039 ),
1040 )
1041 );
1042 // render library page
1043 $render = new Visualizer_Render_Library();
1044 $render->charts = $charts;
1045 $render->type = $filter;
1046 $render->types = self::_getChartTypesLocalized( false, false, false, true );
1047 $render->custom_css = $css;
1048 $render->pagination = paginate_links(
1049 array(
1050 'base' => add_query_arg( array( 'vpage' => '%#%', 'vaction' => false ) ),
1051 'format' => '',
1052 'current' => $page,
1053 'total' => $query->max_num_pages,
1054 'type' => 'array',
1055 )
1056 );
1057
1058 $this->load_survey();
1059
1060 $render->render();
1061 }
1062
1063 /**
1064 * Updates the plugin's action links, which will be rendered at the plugins table.
1065 *
1066 * @since 1.0.0
1067 *
1068 * @access public
1069 *
1070 * @param array $links The array of original action links.
1071 * @param string $file The plugin basename.
1072 *
1073 * @return array Updated array of action links.
1074 */
1075 public function getPluginActionLinks( $links, $file ) {
1076 if ( $file === plugin_basename( VISUALIZER_BASEFILE ) ) {
1077 array_unshift(
1078 $links,
1079 sprintf(
1080 '<a href="%s">%s</a>',
1081 admin_url( 'admin.php?page=' . Visualizer_Plugin::NAME ),
1082 esc_html__( 'Library', 'visualizer' )
1083 )
1084 );
1085 }
1086
1087 return $links;
1088 }
1089
1090 /**
1091 * Updates the plugin's meta links, which will be rendered at the plugins table.
1092 *
1093 * @since 1.0.0
1094 *
1095 * @access public
1096 *
1097 * @param array $plugin_meta The array of a plugin meta links.
1098 * @param string $plugin_file The plugin's basename.
1099 *
1100 * @return array Updated array of plugin meta links.
1101 */
1102 public function getPluginMetaLinks( $plugin_meta, $plugin_file ) {
1103 if ( $plugin_file === plugin_basename( VISUALIZER_BASEFILE ) ) {
1104 // knowledge base link
1105 $plugin_meta[] = sprintf(
1106 '<a href="' . VISUALIZER_MAIN_DOC . '" target="_blank">%s</a>',
1107 esc_html__( 'Docs', 'visualizer' )
1108 );
1109 // flattr link
1110 $plugin_meta[] = sprintf(
1111 '<a style="color:red" href="' . tsdk_utmify( Visualizer_Plugin::PRO_TEASER_URL, 'pluginrow' ) . '" target="_blank">%s</a>',
1112 esc_html__( 'Pro Addon', 'visualizer' )
1113 );
1114 }
1115
1116 return $plugin_meta;
1117 }
1118
1119 /**
1120 * If check is existing user.
1121 *
1122 * @return bool Default false
1123 */
1124 public static function proFeaturesLocked() {
1125 if ( Visualizer_Module::is_pro() ) {
1126 return true;
1127 }
1128 return 'yes' === get_option( 'visualizer-new-user', 'yes' ) ? false : true;
1129 }
1130
1131 /**
1132 * Multilingual Support.
1133 *
1134 * @param int $chart_id Chart ID.
1135 * @return bool Default false
1136 */
1137 public function addMultilingualSupport( $chart_id ) {
1138 global $sitepress;
1139 if ( Visualizer_Module::is_pro() ) {
1140 return;
1141 }
1142 if ( function_exists( 'icl_get_languages' ) && $sitepress instanceof \SitePress ) {
1143 $language = icl_get_languages();
1144 $current_lang = icl_get_current_language();
1145 $default_lang = icl_get_default_language();
1146 $post_info = wpml_get_language_information( null, $chart_id );
1147 $translations = array();
1148 if ( ! empty( $post_info ) && ( $default_lang === $post_info['language_code'] ) ) {
1149 $trid = $sitepress->get_element_trid( $chart_id, 'post_' . Visualizer_Plugin::CPT_VISUALIZER );
1150 $translations = $sitepress->get_element_translations( $trid );
1151 }
1152 if ( empty( $translations ) ) {
1153 return;
1154 }
1155 ?>
1156 <hr><div class="visualizer-languages-list only-pro">
1157 <?php
1158 foreach ( $language as $lang ) {
1159 $lang_code = $lang['code'];
1160 if ( $current_lang !== $lang_code ) {
1161 ?>
1162 <a href="javascript:;">
1163 <img src="<?php echo esc_url( $lang['country_flag_url'] ); ?>" alt="<?php echo esc_attr( $lang['translated_name'] ); ?>">
1164 </a>
1165 <?php
1166 }
1167 }
1168 ?>
1169 <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>
1170 </div>
1171 <?php
1172 }
1173 }
1174
1175 /**
1176 * Check chart is enabled or not.
1177 *
1178 * @param string $type Chart ID.
1179 *
1180 * @return bool Default false
1181 */
1182 public static function checkChartStatus( $type ) {
1183 $types = self::_getChartTypesLocalized( false, false, false, true );
1184 if ( isset( $types[ $type ] ) ) {
1185 return ! empty( $types[ $type ]['enabled'] );
1186 }
1187 return false;
1188 }
1189
1190 /**
1191 * Get the survey metadata.
1192 *
1193 * @return array The survey metadata.
1194 */
1195 private function get_survey_metadata() {
1196 $install_date = get_option( 'visualizer_install', false );
1197 $install_category = 0;
1198
1199 if ( false !== $install_date ) {
1200 $days_since_install = round( ( time() - $install_date ) / DAY_IN_SECONDS );
1201
1202 if ( 0 === $days_since_install || 1 === $days_since_install ) {
1203 $install_category = 0;
1204 } elseif ( 1 < $days_since_install && 8 > $days_since_install ) {
1205 $install_category = 7;
1206 } elseif ( 8 <= $days_since_install && 31 > $days_since_install ) {
1207 $install_category = 30;
1208 } elseif ( 30 < $days_since_install && 90 > $days_since_install ) {
1209 $install_category = 90;
1210 } elseif ( 90 <= $days_since_install ) {
1211 $install_category = 91;
1212 }
1213 }
1214
1215 $plugin_data = get_plugin_data( VISUALIZER_BASEFILE, false, false );
1216 $plugin_version = '';
1217 if ( ! empty( $plugin_data['Version'] ) ) {
1218 $plugin_version = $plugin_data['Version'];
1219 }
1220
1221 $user_id = 'visualizer_' . preg_replace( '/[^\w\d]*/', '', get_site_url() ); // Use a normalized version of the site URL as a user ID.
1222
1223 $license_data = get_option( 'visualizer_pro_license_data', false );
1224 if ( false !== $license_data ) {
1225 $user_id = 'visualizer_' . $license_data->key;
1226 }
1227
1228 return array(
1229 'userId' => $user_id,
1230 'attributes' => array(
1231 'days_since_install' => $install_category,
1232 'free_version' => $plugin_version,
1233 'pro_version' => defined( 'VISUALIZER_PRO_VERSION' ) ? VISUALIZER_PRO_VERSION : '',
1234 'license_status' => apply_filters( 'product_visualizer_license_status', 'invalid' ),
1235 ),
1236 );
1237 }
1238
1239 /**
1240 * Load the survey.
1241 */
1242 private function load_survey() {
1243
1244 if ( defined( 'TI_CYPRESS_TESTING' ) ) {
1245 return;
1246 }
1247
1248 $survey_handler = apply_filters( 'themeisle_sdk_dependency_script_handler', 'survey' );
1249
1250 if ( empty( $survey_handler ) ) {
1251 return;
1252 }
1253
1254 $metadata = $this->get_survey_metadata();
1255
1256 do_action( 'themeisle_sdk_dependency_enqueue_script', 'survey' );
1257 wp_enqueue_script( 'visualizer_chart_survey', VISUALIZER_ABSURL . 'js/survey.js', array( $survey_handler ), $metadata['attributes']['free_version'], true );
1258 wp_localize_script( 'visualizer_chart_survey', 'visualizerSurveyData', $metadata );
1259 }
1260 }
1261