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

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