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

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