PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.11.1
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.11.1
4.0.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 All 149 releases
← All changes | classes/Visualizer/Module/Admin.php +96 -472 4.0.83.11.1 View file →
@@ -29,10 +29,8 @@
29 29 class Visualizer_Module_Admin extends Visualizer_Module {
30 30
31 31 const NAME = __CLASS__;
32 32
33 - const OPTION_GLOBAL_SETTINGS = 'visualizer_global_settings';
34 -
35 33 /**
36 34 * Library page suffix.
37 35 *
38 36 * @since 1.0.0
@@ -42,24 +40,8 @@
42 40 */
43 41 private $_libraryPage;
44 42
45 43 /**
46 - * Support page suffix.
47 - *
48 - * @access private
49 - * @var string
50 - */
51 - private $_supportPage;
52 -
53 - /**
54 - * Settings page suffix.
55 - *
56 - * @access private
57 - * @var string
58 - */
59 - private $_settingsPage;
60 -
61 - /**
62 44 * Constructor.
63 45 *
64 46 * @since 1.0.0
65 47 *
@@ -70,20 +52,16 @@
70 52 public function __construct( Visualizer_Plugin $plugin ) {
71 53 parent::__construct( $plugin );
72 54 $this->_addAction( 'load-post.php', 'enqueueMediaScripts' );
73 55 $this->_addAction( 'load-post-new.php', 'enqueueMediaScripts' );
74 - $this->_addAction( 'enqueue_block_editor_assets', 'enqueueMediaScripts' );
75 56 $this->_addAction( 'admin_footer', 'renderTemplates' );
76 57 $this->_addAction( 'admin_enqueue_scripts', 'enqueueLibraryScripts', null, 0 );
77 - $this->_addAction( 'admin_enqueue_scripts', 'enqueue_support_page' );
78 - $this->_addAction( 'admin_enqueue_scripts', 'enqueueSettingsScripts' );
79 - $this->_addAction( 'admin_post_visualizer_save_global_settings', 'saveGlobalSettings' );
80 58 $this->_addAction( 'admin_menu', 'registerAdminMenu' );
81 59 $this->_addFilter( 'media_view_strings', 'setupMediaViewStrings' );
82 60 $this->_addFilter( 'plugin_action_links', 'getPluginActionLinks', 10, 2 );
83 61 $this->_addFilter( 'plugin_row_meta', 'getPluginMetaLinks', 10, 2 );
62 + $this->_addFilter( 'visualizer_logger_data', 'getLoggerData' );
84 63 $this->_addFilter( 'visualizer_feedback_review_trigger', 'feedbackReviewTrigger' );
85 - $this->_addFilter( 'themeisle_sdk_blackfriday_data', 'add_black_friday_data' );
86 64
87 65 // screen pagination
88 66 $this->_addFilter( 'set-screen-option', 'setScreenOptions', 10, 3 );
89 67
@@ -99,15 +77,12 @@
99 77 $this->_addAction( 'visualizer_chart_languages', 'addMultilingualSupport' );
100 78
101 79 $this->_addFilter( 'admin_footer_text', 'render_review_notice' );
102 80
103 - if ( ! defined( 'TI_E2E_TESTING' ) ) {
104 - $this->_addFilter( 'themeisle-sdk/survey/' . VISUALIZER_DIRNAME, 'get_survey_metadata', 10, 2 );
81 + if ( defined( 'TI_CYPRESS_TESTING' ) ) {
82 + $this->load_cypress_hooks();
105 83 }
106 84
107 - if ( defined( 'TI_E2E_TESTING' ) ) {
108 - $this->load_cypress_hooks();
109 - }
110 85 }
111 86 /**
112 87 * Display review notice.
113 88 */
@@ -113,19 +88,18 @@
113 88 */
114 89 public function render_review_notice( $footer_text ) {
115 90 $current_screen = get_current_screen();
116 91
117 - $visualizer_page_ids = array( 'toplevel_page_visualizer', 'visualizer_page_viz-support', 'visualizer_page_ti-about-visualizer' );
92 + $visualizer_page_ids = ['toplevel_page_visualizer', 'visualizer_page_viz-support', 'visualizer_page_ti-about-visualizer' ];
118 93
119 94 if ( ! empty( $current_screen ) && isset( $current_screen->id ) ) {
120 95 foreach ( $visualizer_page_ids as $page_to_check ) {
121 96 if ( strpos( $current_screen->id, $page_to_check ) !== false ) {
122 97 $footer_text = sprintf(
123 - // translators: %1$s - the name of the plugin (Visualizer), %2$s - message (You can help us by leaving a), %3$s - HTML entity code.
124 98 __( 'Enjoying %1$s? %2$s %3$s rating. Thank you for being so supportive!', 'visualizer' ),
125 99 '<b>Visualizer</b>',
126 100 esc_html__( 'You can help us by leaving a', 'visualizer' ),
127 - '<a href="https://wordpress.org/support/plugin/visualizer/reviews/#new-post" target="_blank">&#9733;&#9733;&#9733;&#9733;&#9733;</a>'
101 + '<a href="https://wordpress.org/support/plugin/visualizer/reviews/" target="_blank">&#9733;&#9733;&#9733;&#9733;&#9733;</a>'
128 102 );
129 103 break;
130 104 }
131 105 }
@@ -143,9 +117,9 @@
143 117 */
144 118 private function load_cypress_hooks() {
145 119 // all charts should load on the same page without pagination.
146 120 add_filter(
147 - 'visualizer_query_args', function ( $args ) {
121 + 'visualizer_query_args', function( $args ) {
148 122 $args['posts_per_page'] = 20;
149 123 return $args;
150 124 }, 10, 1
151 125 );
@@ -221,9 +195,9 @@
221 195
222 196 if ( $meta ) {
223 197 foreach ( $meta as $key => $value ) {
224 198 if ( 0 === strpos( $key, 'visualizer' ) ) {
225 - add_metadata( 'post', $revision_id, $key, self::maybe_decode_content( $value[0] ) );
199 + add_metadata( 'post', $revision_id, $key, maybe_unserialize( $value[0] ) );
226 200 }
227 201 }
228 202 }
229 203 }
@@ -249,9 +223,9 @@
249 223
250 224 if ( $meta ) {
251 225 foreach ( $meta as $key => $value ) {
252 226 if ( 0 === strpos( $key, 'visualizer' ) ) {
253 - add_post_meta( $post_id, $key, self::maybe_decode_content( $value[0] ) );
227 + add_post_meta( $post_id, $key, maybe_unserialize( $value[0] ) );
254 228 }
255 229 }
256 230 }
257 231 }
@@ -262,9 +236,10 @@
262 236 *
263 237 * @access public
264 238 */
265 239 public function init() {
266 - if ( current_user_can( 'edit_posts' ) && current_user_can( 'edit_pages' ) && 'true' === get_user_option( 'rich_editing' ) ) {
240 + // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
241 + if ( current_user_can( 'edit_posts' ) && current_user_can( 'edit_pages' ) && 'true' == get_user_option( 'rich_editing' ) ) {
267 242 $this->_addFilter( 'mce_external_languages', 'add_tinymce_lang', 10, 1 );
268 243 $this->_addFilter( 'mce_external_plugins', 'tinymce_plugin', 10, 1 );
269 244 $this->_addFilter( 'mce_buttons', 'register_mce_button', 10, 1 );
270 245 $this->_addFilter( 'tiny_mce_before_init', 'get_strings_for_block', 10, 1 );
@@ -276,9 +251,9 @@
276 251 *
277 252 * @since ?
278 253 * @access friendly
279 254 */
280 - public function get_strings_for_block( $settings ) {
255 + function get_strings_for_block( $settings ) {
281 256 $class = new Visualizer_Module_Language();
282 257 $strings = $class->get_strings();
283 258 $array = array( 'visualizer_tinymce_plugin' => json_encode( $strings ) );
284 259 return array_merge( $settings, $array );
@@ -354,36 +329,11 @@
354 329 * @access public
355 330 */
356 331 public function enqueueMediaScripts() {
357 332 global $typenow;
358 - global $current_screen;
359 -
360 - if ( post_type_supports( $typenow, 'editor' ) || $current_screen->id === 'widgets' || $current_screen->id === 'customize' ) {
333 + if ( post_type_supports( $typenow, 'editor' ) ) {
361 334 wp_enqueue_style( 'visualizer-media', VISUALIZER_ABSURL . 'css/media.css', array( 'media-views' ), Visualizer_Plugin::VERSION );
362 335
363 - $d3_renderer_asset = VISUALIZER_ABSPATH . '/classes/Visualizer/D3Renderer/build/index.asset.php';
364 - if ( file_exists( $d3_renderer_asset ) && ! wp_script_is( 'visualizer-d3-renderer', 'registered' ) ) {
365 - // @phpstan-ignore-next-line
366 - $d3_asset = include $d3_renderer_asset;
367 - wp_register_script(
368 - 'visualizer-d3-renderer',
369 - VISUALIZER_ABSURL . 'classes/Visualizer/D3Renderer/build/index.js',
370 - array_merge( $d3_asset['dependencies'], array( 'jquery' ) ),
371 - $d3_asset['version'],
372 - true
373 - );
374 - }
375 - if ( wp_script_is( 'visualizer-d3-renderer', 'registered' ) ) {
376 - wp_enqueue_script( 'visualizer-d3-renderer' );
377 - wp_localize_script(
378 - 'visualizer-d3-renderer',
379 - 'vizD3Renderer',
380 - array(
381 - 'iframeJsUrl' => VISUALIZER_ABSURL . 'classes/Visualizer/D3Renderer/build/iframe.js',
382 - )
383 - );
384 - }
385 -
386 336 // Load all the assets for the different libraries we support.
387 337 $deps = array(
388 338 Visualizer_Render_Sidebar_Google::enqueue_assets( array( 'media-editor' ) ),
389 339 Visualizer_Render_Sidebar_Type_DataTable_Tabular::enqueue_assets( array( 'media-editor' ) ),
@@ -397,9 +347,9 @@
397 347 'visualizer-media-view',
398 348 'visualizer',
399 349 array(
400 350 'i10n' => array(
401 - 'insert' => __( 'Insert Chart', 'visualizer' ),
351 + 'insert' => __( 'Insert', 'visualizer' ),
402 352 ),
403 353 )
404 354 );
405 355 wp_enqueue_script( 'visualizer-media-toolbar', VISUALIZER_ABSURL . 'js/media/toolbar.js', array( 'visualizer-media-view' ), Visualizer_Plugin::VERSION, true );
@@ -428,9 +378,9 @@
428 378 'controller' => array(
429 379 'title' => esc_html__( 'Visualizations', 'visualizer' ),
430 380 ),
431 381 'routers' => array(
432 - 'library' => esc_html__( 'Insert from Library', 'visualizer' ),
382 + 'library' => esc_html__( 'From Library', 'visualizer' ),
433 383 'create' => esc_html__( 'Create New', 'visualizer' ),
434 384 ),
435 385 'library' => array(
436 386 'filters' => $chart_types,
@@ -435,9 +385,9 @@
435 385 'library' => array(
436 386 'filters' => $chart_types,
437 387 'types' => array_keys( $chart_types ),
438 388 ),
439 - 'nonce' => wp_create_nonce( Visualizer_Plugin::ACTION_GET_CHARTS ),
389 + 'nonce' => wp_create_nonce(),
440 390 'buildurl' => esc_url( add_query_arg( 'action', Visualizer_Plugin::ACTION_CREATE_CHART, admin_url( 'admin-ajax.php' ) ) ),
441 391 );
442 392
443 393 return $strings;
@@ -460,9 +410,9 @@
460 410 'enabled' => true,
461 411 );
462 412 }
463 413
464 - $enabled = self::proFeaturesEnabled();
414 + $enabled = self::proFeaturesLocked();
465 415
466 416 $types = array_merge(
467 417 $additional,
468 418 array(
@@ -490,21 +440,18 @@
490 440 'name' => esc_html__( 'Area', 'visualizer' ),
491 441 'enabled' => $enabled,
492 442 // in ChartJS, the fill option is used to make Line chart an area: https://www.chartjs.org/docs/latest/charts/area.html
493 443 'supports' => array( 'Google Charts' ),
494 - 'demo_url' => 'https://demo.themeisle.com/visualizer/area-chart/',
495 444 ),
496 445 'geo' => array(
497 446 'name' => esc_html__( 'Geo', 'visualizer' ),
498 447 'enabled' => $enabled,
499 448 'supports' => array( 'Google Charts' ),
500 - 'demo_url' => 'https://demo.themeisle.com/visualizer/geo-chart/',
501 449 ),
502 450 'column' => array(
503 451 'name' => esc_html__( 'Column', 'visualizer' ),
504 452 'enabled' => $enabled,
505 453 'supports' => array( 'Google Charts', 'ChartJS' ),
506 - 'demo_url' => 'https://demo.themeisle.com/visualizer/column-chart/',
507 454 ),
508 455 'bubble' => array(
509 456 'name' => esc_html__( 'Bubble', 'visualizer' ),
510 457 'enabled' => $enabled,
@@ -509,27 +456,23 @@
509 456 'name' => esc_html__( 'Bubble', 'visualizer' ),
510 457 'enabled' => $enabled,
511 458 // chartjs' bubble is ugly looking (and it won't work off the default bubble.csv) so it is being excluded for the time being.
512 459 'supports' => array( 'Google Charts' ),
513 - 'demo_url' => 'https://demo.themeisle.com/visualizer/bubble-chart/',
514 460 ),
515 461 'scatter' => array(
516 462 'name' => esc_html__( 'Scatter', 'visualizer' ),
517 463 'enabled' => $enabled,
518 464 'supports' => array( 'Google Charts' ),
519 - 'demo_url' => 'https://demo.themeisle.com/visualizer/scatter-chart/',
520 465 ),
521 466 'gauge' => array(
522 467 'name' => esc_html__( 'Gauge', 'visualizer' ),
523 468 'enabled' => $enabled,
524 469 'supports' => array( 'Google Charts' ),
525 - 'demo_url' => 'https://demo.themeisle.com/visualizer/gauge-chart/',
526 470 ),
527 471 'candlestick' => array(
528 472 'name' => esc_html__( 'Candlestick', 'visualizer' ),
529 473 'enabled' => $enabled,
530 474 'supports' => array( 'Google Charts' ),
531 - 'demo_url' => 'https://demo.themeisle.com/visualizer/candlestick-chart/',
532 475 ),
533 476 // pro types
534 477 'timeline' => array(
535 478 'name' => esc_html__( 'Timeline', 'visualizer' ),
@@ -534,27 +477,23 @@
534 477 'timeline' => array(
535 478 'name' => esc_html__( 'Timeline', 'visualizer' ),
536 479 'enabled' => false,
537 480 'supports' => array( 'Google Charts', 'ChartJS' ),
538 - 'demo_url' => 'https://demo.themeisle.com/visualizer/timeline-chart/',
539 481 ),
540 482 'combo' => array(
541 483 'name' => esc_html__( 'Combo', 'visualizer' ),
542 484 'enabled' => false,
543 485 'supports' => array( 'Google Charts' ),
544 - 'demo_url' => 'https://demo.themeisle.com/visualizer/combo-chart/',
545 486 ),
546 487 'polarArea' => array(
547 488 'name' => esc_html__( 'Polar Area', 'visualizer' ),
548 489 'enabled' => false,
549 490 'supports' => array( 'ChartJS' ),
550 - 'demo_url' => 'https://demo.themeisle.com/visualizer/polar-area-chart/',
551 491 ),
552 492 'radar' => array(
553 493 'name' => esc_html__( 'Radar/Spider', 'visualizer' ),
554 494 'enabled' => false,
555 495 'supports' => array( 'ChartJS' ),
556 - 'demo_url' => 'https://demo.themeisle.com/visualizer/radar-spider-chart/',
557 496 ),
558 497 )
559 498 );
560 499 $types = apply_filters( 'visualizer_pro_chart_types', $types );
@@ -681,159 +620,45 @@
681 620 *
682 621 * @param string $suffix The current page suffix.
683 622 */
684 623 public function enqueueLibraryScripts( $suffix ) {
685 - if ( $suffix !== $this->_libraryPage ) {
686 - return;
687 - }
688 -
689 - wp_enqueue_style( 'visualizer-library', VISUALIZER_ABSURL . 'css/library.css', array(), Visualizer_Plugin::VERSION );
690 - $this->_addFilter( 'media_upload_tabs', 'setupVisualizerTab' );
691 - wp_enqueue_media();
692 - wp_enqueue_script(
693 - 'visualizer-library',
694 - VISUALIZER_ABSURL . 'js/library.js',
695 - array(
696 - 'jquery',
697 - 'media-views',
698 - 'clipboard',
699 - ),
700 - Visualizer_Plugin::VERSION,
701 - true
702 - );
703 -
704 - wp_enqueue_script( 'visualizer-customization', $this->get_user_customization_js(), array(), null, true );
705 -
706 - $has_d3 = false;
707 - $query = $this->getQuery();
708 - while ( $query->have_posts() ) {
709 - $chart = $query->next_post();
710 - $library = $this->load_chart_type( $chart->ID );
711 - if ( is_null( $library ) ) {
712 - continue;
713 - }
624 + if ( $suffix === $this->_libraryPage ) {
625 + wp_enqueue_style( 'visualizer-library', VISUALIZER_ABSURL . 'css/library.css', array(), Visualizer_Plugin::VERSION );
626 + $this->_addFilter( 'media_upload_tabs', 'setupVisualizerTab' );
627 + wp_enqueue_media();
714 628 wp_enqueue_script(
715 - "visualizer-render-$library",
716 - VISUALIZER_ABSURL . 'js/render-facade.js',
717 - apply_filters( 'visualizer_assets_render', array( 'visualizer-library', 'visualizer-customization' ), true ),
629 + 'visualizer-library',
630 + VISUALIZER_ABSURL . 'js/library.js',
631 + array(
632 + 'jquery',
633 + 'media-views',
634 + 'clipboard',
635 + ),
718 636 Visualizer_Plugin::VERSION,
719 637 true
720 638 );
721 - if ( 'd3' === $library ) {
722 - $has_d3 = true;
723 - }
724 - }
725 639
726 - if ( $has_d3 ) {
727 - $d3_renderer_asset = VISUALIZER_ABSPATH . '/classes/Visualizer/D3Renderer/build/index.asset.php';
728 - if ( file_exists( $d3_renderer_asset ) && ! wp_script_is( 'visualizer-d3-renderer', 'registered' ) ) {
729 - /**
730 - * Ignore missing build asset in source checkout.
731 - *
732 - * @phpstan-ignore-next-line
733 - */
734 - $d3_asset = include $d3_renderer_asset;
735 - wp_register_script(
736 - 'visualizer-d3-renderer',
737 - VISUALIZER_ABSURL . 'classes/Visualizer/D3Renderer/build/index.js',
738 - array_merge( $d3_asset['dependencies'], array( 'jquery' ) ),
739 - $d3_asset['version'],
740 - true
741 - );
742 - wp_enqueue_script( 'visualizer-d3-renderer' );
743 - }
744 - wp_localize_script(
745 - 'visualizer-d3-renderer',
746 - 'vizD3Renderer',
747 - array(
748 - 'iframeJsUrl' => VISUALIZER_ABSURL . 'classes/Visualizer/D3Renderer/build/iframe.js',
749 - )
750 - );
751 - }
640 + wp_enqueue_script( 'visualizer-customization', $this->get_user_customization_js(), array(), null, true );
752 641
753 - $chart_builder_asset = VISUALIZER_ABSPATH . '/classes/Visualizer/ChartBuilder/build/index.asset.php';
754 - if ( file_exists( $chart_builder_asset ) ) {
755 - /**
756 - * Ignore missing build asset in source checkout.
757 - *
758 - * @phpstan-ignore-next-line
759 - */
760 - $asset = include $chart_builder_asset;
761 - $chart_builder_deps = $asset['dependencies'];
762 - if ( ! wp_script_is( 'visualizer-handsontable', 'registered' ) && defined( 'Visualizer_Pro_ABSURL' ) && defined( 'VISUALIZER_PRO_VERSION' ) ) {
763 - wp_register_script(
764 - 'visualizer-handsontable',
765 - Visualizer_Pro_ABSURL . 'vendor/handsontable/dist/handsontable.full.min.js',
766 - array(),
767 - VISUALIZER_PRO_VERSION,
642 + $query = $this->getQuery();
643 + while ( $query->have_posts() ) {
644 + $chart = $query->next_post();
645 + $library = $this->load_chart_type( $chart->ID );
646 + if ( is_null( $library ) ) {
647 + continue;
648 + }
649 + wp_enqueue_script(
650 + "visualizer-render-$library",
651 + VISUALIZER_ABSURL . 'js/render-facade.js',
652 + apply_filters( 'visualizer_assets_render', array( 'visualizer-library', 'visualizer-customization' ), true ),
653 + Visualizer_Plugin::VERSION,
768 654 true
769 655 );
770 656 }
771 - if ( ! wp_style_is( 'visualizer-handsontable', 'registered' ) && defined( 'Visualizer_Pro_ABSURL' ) && defined( 'VISUALIZER_PRO_VERSION' ) ) {
772 - wp_register_style(
773 - 'visualizer-handsontable',
774 - Visualizer_Pro_ABSURL . 'vendor/handsontable/dist/handsontable.full.min.css',
775 - array(),
776 - VISUALIZER_PRO_VERSION
777 - );
778 - }
779 - if ( wp_script_is( 'visualizer-handsontable', 'registered' ) ) {
780 - wp_enqueue_script( 'visualizer-handsontable' );
781 - $chart_builder_deps = array_unique( array_merge( $chart_builder_deps, array( 'visualizer-handsontable' ) ) );
782 - }
783 - if ( wp_style_is( 'visualizer-handsontable', 'registered' ) ) {
784 - wp_enqueue_style( 'visualizer-handsontable' );
785 - }
786 - wp_enqueue_script(
787 - 'visualizer-chart-builder',
788 - VISUALIZER_ABSURL . 'classes/Visualizer/ChartBuilder/build/index.js',
789 - $chart_builder_deps,
790 - $asset['version'],
791 - true
792 - );
793 - wp_enqueue_style(
794 - 'visualizer-chart-builder',
795 - VISUALIZER_ABSURL . 'classes/Visualizer/ChartBuilder/build/style-index.css',
796 - array(),
797 - $asset['version']
798 - );
799 - $chart_builder_css = VISUALIZER_ABSPATH . '/classes/Visualizer/ChartBuilder/build/index.css';
800 - if ( file_exists( $chart_builder_css ) ) {
801 - wp_enqueue_style(
802 - 'visualizer-chart-builder-runtime',
803 - VISUALIZER_ABSURL . 'classes/Visualizer/ChartBuilder/build/index.css',
804 - array( 'visualizer-chart-builder' ),
805 - $asset['version']
806 - );
807 - }
808 - wp_localize_script(
809 - 'visualizer-chart-builder',
810 - 'vizAIBuilder',
811 - array(
812 - 'ajaxUrl' => admin_url( 'admin-ajax.php' ),
813 - 'nonce' => wp_create_nonce( 'visualizer-ai-builder' ),
814 - 'isPro' => Visualizer_Module::is_pro(),
815 - 'upgradeUrl' => tsdk_utmify( Visualizer_Plugin::PRO_TEASER_URL, 'aiBuilderUpgrade', 'dataSource' ),
816 - )
817 - );
818 657 }
819 -
820 - do_action( 'themeisle_internal_page', VISUALIZER_DIRNAME, 'library' );
821 658 }
822 659
823 660 /**
824 - * Enqueue script for support page.
825 - *
826 - * @param string $hook_suffix Current hook.
827 - */
828 - public function enqueue_support_page( $hook_suffix ) {
829 - if ( $this->_supportPage !== $hook_suffix ) {
830 - return;
831 - }
832 - do_action( 'themeisle_internal_page', VISUALIZER_DIRNAME, 'support' );
833 - }
834 -
835 - /**
836 661 * Adds visualizer tab for media upload tabs array.
837 662 *
838 663 * @since 1.0.0
839 664 *
@@ -874,20 +699,10 @@
874 699 __( 'Add New Chart', 'visualizer' ),
875 700 'edit_posts',
876 701 'admin.php?page=' . Visualizer_Plugin::NAME . '&vaction=addnew'
877 702 );
878 -
879 - $this->_settingsPage = add_submenu_page(
703 + add_submenu_page(
880 704 Visualizer_Plugin::NAME,
881 - __( 'Settings', 'visualizer' ),
882 - __( 'Settings', 'visualizer' ),
883 - 'manage_options',
884 - 'viz-settings',
885 - array( $this, 'renderSettingsPage' )
886 - );
887 -
888 - $this->_supportPage = add_submenu_page(
889 - Visualizer_Plugin::NAME,
890 705 __( 'Support', 'visualizer' ),
891 706 __( 'Support', 'visualizer' ) . '<span class="dashicons dashicons-editor-help more-features-icon" style="width: 17px; height: 17px; margin-left: 4px; color: #ffca54; font-size: 17px; vertical-align: -3px;"></span>',
892 707 'edit_posts',
893 708 'viz-support',
@@ -912,9 +727,9 @@
912 727 font-size: 14px;
913 728 font-weight: 600;
914 729 color: #fff;
915 730 }
916 - #toplevel_page_visualizer ul.wp-submenu li:last-child > a > span {
731 + #toplevel_page_visualizer ul.wp-submenu li:last-child > a {
917 732 color: #fff !important;
918 733 }
919 734 #toplevel_page_visualizer ul.wp-submenu li:last-child > a:hover {
920 735 box-shadow: inherit;
@@ -935,9 +750,9 @@
935 750
936 751 /**
937 752 * Adds the screen options for pagination.
938 753 */
939 - public function addScreenOptions() {
754 + function addScreenOptions() {
940 755 $screen = get_current_screen();
941 756
942 757 // bail if it's some other page.
943 758 if ( ! is_object( $screen ) || $screen->id !== $this->_libraryPage ) {
@@ -954,9 +769,9 @@
954 769
955 770 /**
956 771 * Returns the screen option for pagination.
957 772 */
958 - public function setScreenOptions( $status, $option, $value ) {
773 + function setScreenOptions( $status, $option, $value ) {
959 774 if ( 'visualizer_library_per_page' === $option ) {
960 775 return $value;
961 776 }
962 777 }
@@ -1104,95 +919,13 @@
1104 919 * @access public
1105 920 */
1106 921 public function renderSupportPage() {
1107 922 wp_enqueue_style( 'visualizer-upsell', VISUALIZER_ABSURL . 'css/upsell.css', array(), Visualizer_Plugin::VERSION );
923 + $this->load_survey();
1108 924 include_once VISUALIZER_ABSPATH . '/templates/support.php';
1109 925 }
1110 926
1111 927 /**
1112 - * Enqueues scripts/styles for the Settings page.
1113 - *
1114 - * @access public
1115 - */
1116 - public function enqueueSettingsScripts( string $hook_suffix ): void {
1117 - if ( $this->_settingsPage !== $hook_suffix ) {
1118 - return;
1119 - }
1120 - wp_enqueue_style( 'wp-color-picker' );
1121 - wp_enqueue_script( 'wp-color-picker' );
1122 - }
1123 -
1124 - /**
1125 - * Renders the global style settings page.
1126 - *
1127 - * @access public
1128 - */
1129 - public function renderSettingsPage(): void {
1130 - if ( ! current_user_can( 'manage_options' ) ) {
1131 - wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'visualizer' ) );
1132 - }
1133 - $settings = self::getGlobalSettings();
1134 - include_once VISUALIZER_ABSPATH . '/templates/global-settings.php';
1135 - }
1136 -
1137 - /**
1138 - * Returns the global style settings option.
1139 - *
1140 - * @return array<string, string>
1141 - * @access public
1142 - * @static
1143 - */
1144 - public static function getGlobalSettings(): array {
1145 - $defaults = array(
1146 - 'color_primary' => '',
1147 - 'color_secondary' => '',
1148 - 'apply_existing' => '0',
1149 - );
1150 - $saved = get_option( self::OPTION_GLOBAL_SETTINGS, array() );
1151 - return wp_parse_args( $saved, $defaults );
1152 - }
1153 -
1154 - /**
1155 - * Handles saving of the global style settings.
1156 - *
1157 - * @access public
1158 - */
1159 - public function saveGlobalSettings(): void {
1160 - if ( ! current_user_can( 'manage_options' ) ) {
1161 - wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'visualizer' ) );
1162 - }
1163 -
1164 - check_admin_referer( 'visualizer_save_global_settings' );
1165 -
1166 - $color_primary = sanitize_hex_color( wp_unslash( $_POST['visualizer_color_primary'] ?? '' ) );
1167 - $color_secondary = sanitize_hex_color( wp_unslash( $_POST['visualizer_color_secondary'] ?? '' ) );
1168 - $apply_existing = ! empty( $_POST['visualizer_apply_existing'] ) ? '1' : '0';
1169 - $clear = ! empty( $_POST['visualizer_clear_settings'] );
1170 -
1171 - if ( $clear ) {
1172 - delete_option( self::OPTION_GLOBAL_SETTINGS );
1173 - } else {
1174 - $settings = array(
1175 - 'color_primary' => $color_primary ? $color_primary : '',
1176 - 'color_secondary' => $color_secondary ? $color_secondary : '',
1177 - 'apply_existing' => $apply_existing,
1178 - );
1179 - update_option( self::OPTION_GLOBAL_SETTINGS, $settings );
1180 - }
1181 -
1182 - wp_safe_redirect(
1183 - add_query_arg(
1184 - array(
1185 - 'page' => 'viz-settings',
1186 - 'updated' => $clear ? 'cleared' : 'true',
1187 - ),
1188 - admin_url( 'admin.php' )
1189 - )
1190 - );
1191 - exit;
1192 - }
1193 -
1194 - /**
1195 928 * Renders visualizer library page.
1196 929 *
1197 930 * @since 1.0.0
1198 931 *
@@ -1276,9 +1009,8 @@
1276 1009
1277 1010 // add chart to the array
1278 1011 $charts[ $id ] = array(
1279 1012 'id' => $chart->ID,
1280 - 'title' => $chart->post_title,
1281 1013 'type' => $type,
1282 1014 'series' => $series,
1283 1015 'settings' => $settings,
1284 1016 'data' => $data,
@@ -1283,15 +1015,11 @@
1283 1015 'settings' => $settings,
1284 1016 'data' => $data,
1285 1017 'library' => $library,
1286 1018 );
1287 - if ( 'd3' === $library ) {
1288 - $charts[ $id ]['code'] = get_post_meta( $chart->ID, Visualizer_Module_AIBuilder::CF_D3_CODE, true );
1289 - }
1290 1019 }
1291 1020 // enqueue charts array
1292 1021 $ajaxurl = admin_url( 'admin-ajax.php' );
1293 -
1294 1022 wp_localize_script(
1295 1023 'visualizer-library',
1296 1024 'visualizer',
1297 1025 array(
@@ -1347,8 +1075,10 @@
1347 1075 'type' => 'array',
1348 1076 )
1349 1077 );
1350 1078
1079 + $this->load_survey();
1080 +
1351 1081 $render->render();
1352 1082 }
1353 1083
1354 1084 /**
@@ -1390,36 +1120,19 @@
1390 1120 *
1391 1121 * @return array Updated array of plugin meta links.
1392 1122 */
1393 1123 public function getPluginMetaLinks( $plugin_meta, $plugin_file ) {
1394 - if ( Visualizer_Module::is_pro() ) {
1395 - return $plugin_meta;
1396 - }
1397 -
1398 - // Also suppress the upsell when Pro is installed but not currently active.
1399 - if ( ! function_exists( 'get_plugins' ) ) {
1400 - require_once ABSPATH . 'wp-admin/includes/plugin.php';
1401 - }
1402 - foreach ( array_keys( get_plugins() ) as $installed_plugin ) {
1403 - if ( false !== strpos( $installed_plugin, 'visualizer-pro' ) ) {
1404 - return $plugin_meta;
1405 - }
1406 - }
1407 -
1408 1124 if ( $plugin_file === plugin_basename( VISUALIZER_BASEFILE ) ) {
1409 - $is_black_friday = apply_filters( 'themeisle_sdk_is_black_friday_sale', false );
1410 1125 // knowledge base link
1411 1126 $plugin_meta[] = sprintf(
1412 1127 '<a href="' . VISUALIZER_MAIN_DOC . '" target="_blank">%s</a>',
1413 1128 esc_html__( 'Docs', 'visualizer' )
1414 1129 );
1415 - if ( ! $is_black_friday ) {
1416 - // flattr link
1417 - $plugin_meta[] = sprintf(
1418 - '<a style="color:red" href="' . tsdk_utmify( Visualizer_Plugin::PRO_TEASER_URL, 'pluginrow' ) . '" target="_blank">%s</a>',
1419 - esc_html__( 'Get Visualizer Pro', 'visualizer' )
1420 - );
1421 - }
1130 + // flattr link
1131 + $plugin_meta[] = sprintf(
1132 + '<a style="color:red" href="' . tsdk_utmify( Visualizer_Plugin::PRO_TEASER_URL, 'pluginrow' ) . '" target="_blank">%s</a>',
1133 + esc_html__( 'Pro Addon', 'visualizer' )
1134 + );
1422 1135 }
1423 1136
1424 1137 return $plugin_meta;
1425 1138 }
@@ -1424,39 +1137,17 @@
1424 1137 return $plugin_meta;
1425 1138 }
1426 1139
1427 1140 /**
1428 - * Returns true when premium chart types should be enabled for the current user.
1141 + * If check is existing user.
1429 1142 *
1430 - * Pro 1.9.0+ hooks the 'visualizer_is_pro' filter and returns true only when
1431 - * the license is valid. Pre-1.9.0 Pro defined a Visualizer_Pro class instead;
1432 - * we detect that as a fallback so those legacy installs still work.
1433 - *
1434 - * Passing false as the filter default ensures the constant VISUALIZER_PRO
1435 - * (which is set to true whenever the Pro class exists, regardless of license
1436 - * state) cannot bypass the license check.
1437 - *
1438 - * @return bool
1143 + * @return bool Default false
1439 1144 */
1440 - public static function proFeaturesEnabled() {
1441 - $is_pro_filter = apply_filters( 'visualizer_is_pro', false );
1442 -
1443 - // Pro 1.9.0+: filter is hooked and returns true only with a valid license.
1444 - if ( $is_pro_filter ) {
1145 + public static function proFeaturesLocked() {
1146 + if ( Visualizer_Module::is_pro() ) {
1445 1147 return true;
1446 1148 }
1447 -
1448 - // Pro is installed (active) but the license check above did not pass.
1449 - // Do NOT fall through to the legacy "old user" path — that path exists
1450 - // only for sites that never had Pro installed. If Pro is present but
1451 - // the license is inactive we should lock, regardless of chart history.
1452 - if ( class_exists( 'Visualizer_Pro', false ) ) {
1453 - return false;
1454 - }
1455 -
1456 - // No Pro installed at all: grant legacy access to existing users so
1457 - // their charts are not suddenly broken when they upgrade the free plugin.
1458 - return 'yes' === get_option( 'visualizer-new-user' ) ? false : true;
1149 + return 'yes' === get_option( 'visualizer-new-user', 'yes' ) ? false : true;
1459 1150 }
1460 1151
1461 1152 /**
1462 1153 * Multilingual Support.
@@ -1519,139 +1210,72 @@
1519 1210
1520 1211 /**
1521 1212 * Get the survey metadata.
1522 1213 *
1523 - * @param array $data The data for survey in Formbricks format.
1524 - * @param string $page_slug The slug of the loaded page.
1525 - *
1526 1214 * @return array The survey metadata.
1527 1215 */
1528 - public function get_survey_metadata( $data, $page_slug ) {
1529 - $install_date = get_option( 'visualizer_install', time() );
1530 - $install_days_number = intval( ( time() - $install_date ) / DAY_IN_SECONDS );
1216 + private function get_survey_metadata() {
1217 + $install_date = get_option( 'visualizer_install', false );
1218 + $install_category = 0;
1531 1219
1532 - $license_status = apply_filters( 'product_visualizer_license_status', 'invalid' );
1533 - $license_plan = apply_filters( 'product_visualizer_license_plan', false );
1534 - $license_key = apply_filters( 'product_visualizer_license_key', false );
1220 + if ( false !== $install_date ) {
1221 + $days_since_install = round( ( time() - $install_date ) / DAY_IN_SECONDS );
1535 1222
1223 + if ( 0 === $days_since_install || 1 === $days_since_install ) {
1224 + $install_category = 0;
1225 + } elseif ( 1 < $days_since_install && 8 > $days_since_install ) {
1226 + $install_category = 7;
1227 + } elseif ( 8 <= $days_since_install && 31 > $days_since_install ) {
1228 + $install_category = 30;
1229 + } elseif ( 30 < $days_since_install && 90 > $days_since_install ) {
1230 + $install_category = 90;
1231 + } elseif ( 90 <= $days_since_install ) {
1232 + $install_category = 91;
1233 + }
1234 + }
1235 +
1536 1236 $plugin_data = get_plugin_data( VISUALIZER_BASEFILE, false, false );
1537 1237 $plugin_version = '';
1538 -
1539 1238 if ( ! empty( $plugin_data['Version'] ) ) {
1540 1239 $plugin_version = $plugin_data['Version'];
1541 1240 }
1542 1241
1543 - $count_charts_cache_key = 'visualizer_count_charts';
1544 - $charts_number = get_transient( $count_charts_cache_key );
1242 + $user_id = 'visualizer_' . preg_replace( '/[^\w\d]*/', '', get_site_url() ); // Use a normalized version of the site URL as a user ID.
1545 1243
1546 - if ( false === $charts_number ) {
1547 - $charts_number = $this->count_charts( 100 );
1548 - set_transient( $count_charts_cache_key, $charts_number, 100 === $charts_number ? WEEK_IN_SECONDS : 6 * HOUR_IN_SECONDS );
1549 - } else {
1550 - $charts_number = strval( $charts_number );
1244 + $license_data = get_option( 'visualizer_pro_license_data', false );
1245 + if ( false !== $license_data && isset( $license_data->key ) ) {
1246 + $user_id = 'visualizer_' . $license_data->key;
1551 1247 }
1552 1248
1553 - $data = array(
1554 - 'environmentId' => 'cltef8cut1s7wyyfxy3rlxzs5',
1249 + return array(
1250 + 'userId' => $user_id,
1555 1251 'attributes' => array(
1556 - 'free_version' => $plugin_version,
1557 - 'pro_version' => defined( 'VISUALIZER_PRO_VERSION' ) ? VISUALIZER_PRO_VERSION : '',
1558 - 'license_status' => $license_status,
1559 - 'install_days_number' => $install_days_number,
1560 - 'charts_number' => $charts_number,
1252 + 'days_since_install' => strval( $install_category ),
1253 + 'free_version' => $plugin_version,
1254 + 'pro_version' => defined( 'VISUALIZER_PRO_VERSION' ) ? VISUALIZER_PRO_VERSION : '',
1255 + 'license_status' => apply_filters( 'product_visualizer_license_status', 'invalid' ),
1561 1256 ),
1562 1257 );
1563 -
1564 - if ( ! empty( $license_plan ) ) {
1565 - $data['attributes']['plan'] = $license_plan;
1566 - }
1567 -
1568 - if ( ! empty( $license_key ) ) {
1569 - $data['attributes']['license_key'] = apply_filters( 'themeisle_sdk_secret_masking', $license_key );
1570 - }
1571 -
1572 - return $data;
1573 1258 }
1574 1259
1575 1260 /**
1576 - * Count the charts.
1577 - *
1578 - * @param int $limit The count limit (optional).
1579 - *
1580 - * @return int The number of charts.
1261 + * Load the survey.
1581 1262 */
1582 - public function count_charts( $limit = -1 ) {
1583 - $args = array(
1584 - 'post_type' => Visualizer_Plugin::CPT_VISUALIZER,
1585 - 'post_status' => 'publish',
1586 - 'posts_per_page' => $limit,
1587 - 'fields' => 'ids',
1588 - );
1263 + private function load_survey() {
1589 1264
1590 - $query = new WP_Query( $args);
1591 - return $query->post_count;
1592 - }
1593 -
1594 - /**
1595 - * Set the black friday data.
1596 - *
1597 - * @param array $configs The configuration array for the loaded products.
1598 - * @return array
1599 - */
1600 - public function add_black_friday_data( $configs ) {
1601 - $config = $configs['default'];
1602 -
1603 - $message = __( 'Database queries, private charts, auto-sync. Go beyond basic charts. Exclusively for existing Visualizer users.', 'visualizer' );
1604 - $cta_label = __( 'Get Visualizer Pro', 'visualizer' );
1605 -
1606 - $plan = apply_filters( 'product_visualizer_license_plan', 0 );
1607 - $license = apply_filters( 'product_visualizer_license_key', false );
1608 - $status = apply_filters( 'product_visualizer_license_status', false );
1609 - $pro_product_slug = defined( 'VISUALIZER_PRO_BASEFILE' ) ? basename( dirname( VISUALIZER_PRO_BASEFILE ) ) : '';
1610 -
1611 - $is_pro = 'valid' === $status;
1612 - $is_expired = 'expired' === $status || 'active-expired' === $status;
1613 -
1614 - if ( $is_pro ) {
1615 - // translators: %s is the discount percentage.
1616 - $config['plugin_meta_message'] = sprintf( __( 'Black Friday Sale - up to %s off', 'visualizer' ), '30%' );
1617 - // translators: %1$s - discount, %2$s - discount.
1618 - $message = sprintf( __( 'Upgrade your Visualizer Pro plan: %1$s off this week. Already on the plan you need? Renew early and save up to %2$s.', 'visualizer' ), '30%', '20%' );
1619 - $cta_label = __( 'See your options', 'visualizer' );
1620 - } elseif ( $is_expired ) {
1621 - // translators: %s is the discount percentage.
1622 - $config['upgrade_menu_text'] = sprintf( __( 'BF Sale - %s off', 'visualizer' ), '50%' );
1623 - // translators: %s is the discount percentage.
1624 - $config['plugin_meta_message'] = sprintf( __( 'Black Friday Sale - %s off', 'visualizer' ), '50%' );
1625 - $message = __( 'Your Visualizer Pro features are still here, just locked. Renew at a reduced rate this week.', 'visualizer' );
1626 - $cta_label = __( 'Reactivate now', 'visualizer' );
1627 - } else {
1628 - // translators: %s is the discount percentage.
1629 - $config['plugin_meta_message'] = sprintf( __( 'Black Friday Sale - %s off', 'visualizer' ), '60%' );
1630 - $config['title'] = __( 'Visualizer Pro: 60% off this week', 'visualizer' );
1631 - // translators: %s is the discount percentage.
1632 - $config['upgrade_menu_text'] = sprintf( __( 'BF Sale - %s off', 'visualizer' ), '60%' );
1265 + if ( defined( 'TI_CYPRESS_TESTING' ) ) {
1266 + return;
1633 1267 }
1634 1268
1635 - $url_params = array(
1636 - 'utm_term' => $is_pro ? 'plan-' . $plan : 'free',
1637 - 'lkey' => ! empty( $license ) ? $license : false,
1638 - 'expired' => $is_expired ? '1' : false,
1639 - );
1269 + $survey_handler = apply_filters( 'themeisle_sdk_dependency_script_handler', 'survey' );
1640 1270
1641 - if ( ( $is_pro || $is_expired ) && ! empty( $pro_product_slug ) ) {
1642 - $config['plugin_meta_targets'] = array( $pro_product_slug );
1271 + if ( empty( $survey_handler ) ) {
1272 + return;
1643 1273 }
1644 1274
1645 - $config['message'] = $message;
1646 - $config['cta_label'] = $cta_label;
1275 + $metadata = $this->get_survey_metadata();
1647 1276
1648 - $config['sale_url'] = add_query_arg(
1649 - $url_params,
1650 - tsdk_translate_link( tsdk_utmify( 'https://themeisle.link/vizualizer-bf', 'bfcm', 'visualizer' ) )
1651 - );
1652 -
1653 - $configs[ VISUALIZER_DIRNAME ] = $config;
1654 -
1655 - return $configs;
1277 + do_action( 'themeisle_sdk_dependency_enqueue_script', 'survey' );
1278 + wp_enqueue_script( 'visualizer_chart_survey', VISUALIZER_ABSURL . 'js/survey.js', array( $survey_handler ), $metadata['attributes']['free_version'], true );
1279 + wp_localize_script( 'visualizer_chart_survey', 'visualizerSurveyData', $metadata );
1656 1280 }
1657 1281 }