PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.4.2
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.4.2
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 +134 -829 4.0.83.4.2 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,24 +52,18 @@
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 - $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' );
57 + $this->_addAction( 'admin_enqueue_scripts', 'enqueueLibraryScripts', null, 8 );
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' );
63 + $this->_addFilter( 'visualizer_get_chart_counts', 'getChartCountsByTypeAndMeta' );
84 64 $this->_addFilter( 'visualizer_feedback_review_trigger', 'feedbackReviewTrigger' );
85 - $this->_addFilter( 'themeisle_sdk_blackfriday_data', 'add_black_friday_data' );
86 65
87 - // screen pagination
88 - $this->_addFilter( 'set-screen-option', 'setScreenOptions', 10, 3 );
89 -
90 66 // revision support.
91 67 $this->_addFilter( 'wp_revisions_to_keep', 'limitRevisions', null, 10, 2 );
92 68 $this->_addAction( '_wp_put_post_revision', 'addRevision', null, 10, 1 );
93 69 $this->_addAction( 'wp_restore_post_revision', 'restoreRevision', null, 10, 2 );
@@ -95,47 +71,14 @@
95 71 $this->_addAction( 'visualizer_chart_schedules_spl', 'addSplChartSchedules', null, 10, 3 );
96 72
97 73 $this->_addAction( 'admin_init', 'init' );
98 74
99 - $this->_addAction( 'visualizer_chart_languages', 'addMultilingualSupport' );
100 -
101 - $this->_addFilter( 'admin_footer_text', 'render_review_notice' );
102 -
103 - if ( ! defined( 'TI_E2E_TESTING' ) ) {
104 - $this->_addFilter( 'themeisle-sdk/survey/' . VISUALIZER_DIRNAME, 'get_survey_metadata', 10, 2 );
105 - }
106 -
107 - if ( defined( 'TI_E2E_TESTING' ) ) {
75 + if ( defined( 'TI_CYPRESS_TESTING' ) ) {
108 76 $this->load_cypress_hooks();
109 77 }
110 - }
111 - /**
112 - * Display review notice.
113 - */
114 - public function render_review_notice( $footer_text ) {
115 - $current_screen = get_current_screen();
116 78
117 - $visualizer_page_ids = array( 'toplevel_page_visualizer', 'visualizer_page_viz-support', 'visualizer_page_ti-about-visualizer' );
118 -
119 - if ( ! empty( $current_screen ) && isset( $current_screen->id ) ) {
120 - foreach ( $visualizer_page_ids as $page_to_check ) {
121 - if ( strpos( $current_screen->id, $page_to_check ) !== false ) {
122 - $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 - __( 'Enjoying %1$s? %2$s %3$s rating. Thank you for being so supportive!', 'visualizer' ),
125 - '<b>Visualizer</b>',
126 - 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>'
128 - );
129 - break;
130 - }
131 - }
132 - }
133 -
134 - return $footer_text;
135 79 }
136 80
137 -
138 81 /**
139 82 * Define the hooks that are needed for cypress.
140 83 *
141 84 * @since 3.4.0
@@ -143,9 +86,9 @@
143 86 */
144 87 private function load_cypress_hooks() {
145 88 // all charts should load on the same page without pagination.
146 89 add_filter(
147 - 'visualizer_query_args', function ( $args ) {
90 + 'visualizer_query_args', function( $args ) {
148 91 $args['posts_per_page'] = 20;
149 92 return $args;
150 93 }, 10, 1
151 94 );
@@ -166,16 +109,23 @@
166 109 if ( apply_filters( 'visualizer_is_business', false ) ) {
167 110 return;
168 111 }
169 112
170 - $is_new_personal = apply_filters( 'visualizer_is_new_personal', false );
113 + $license = __( 'PRO', 'visualizer' );
114 + if ( Visualizer_Module::is_pro() ) {
115 + switch ( $plan ) {
116 + case 1:
117 + $license = __( 'Developer', 'visualizer' );
118 + break;
119 + }
120 + }
171 121
172 122 $hours = array(
173 - '0.16' => __( '10 minutes', 'visualizer' ),
174 - '1' => __( 'Each hour', 'visualizer' ),
175 - '12' => __( 'Each 12 hours', 'visualizer' ),
176 - '24' => __( 'Each day', 'visualizer' ),
177 - '72' => __( 'Each 3 days', 'visualizer' ),
123 + '0' => __( 'Live', 'visualizer' ),
124 + '1' => __( 'Each hour', 'visualizer' ),
125 + '12' => __( 'Each 12 hours', 'visualizer' ),
126 + '24' => __( 'Each day', 'visualizer' ),
127 + '72' => __( 'Each 3 days', 'visualizer' ),
178 128 );
179 129
180 130 switch ( $feature ) {
181 131 case 'json':
@@ -180,9 +130,9 @@
180 130 switch ( $feature ) {
181 131 case 'json':
182 132 case 'csv':
183 133 // no more schedules if pro is already active.
184 - if ( Visualizer_Module::is_pro() && ! $is_new_personal ) {
134 + if ( Visualizer_Module::is_pro() ) {
185 135 return;
186 136 }
187 137 break;
188 138 case 'wp':
@@ -192,9 +142,9 @@
192 142 default:
193 143 return;
194 144 }
195 145
196 - echo '<optgroup disabled label="' . __( 'Upgrade required', 'visualizer' ) . '">';
146 + echo '<optgroup disabled label="' . sprintf( __( 'More in the %s version', 'visualizer' ), $license ) . '">';
197 147 foreach ( $hours as $hour => $desc ) {
198 148 echo '<option disabled>' . $desc . '</option>';
199 149 }
200 150 echo '</optgroup>';
@@ -221,9 +171,9 @@
221 171
222 172 if ( $meta ) {
223 173 foreach ( $meta as $key => $value ) {
224 174 if ( 0 === strpos( $key, 'visualizer' ) ) {
225 - add_metadata( 'post', $revision_id, $key, self::maybe_decode_content( $value[0] ) );
175 + add_metadata( 'post', $revision_id, $key, maybe_unserialize( $value[0] ) );
226 176 }
227 177 }
228 178 }
229 179 }
@@ -249,9 +199,9 @@
249 199
250 200 if ( $meta ) {
251 201 foreach ( $meta as $key => $value ) {
252 202 if ( 0 === strpos( $key, 'visualizer' ) ) {
253 - add_post_meta( $post_id, $key, self::maybe_decode_content( $value[0] ) );
203 + add_post_meta( $post_id, $key, maybe_unserialize( $value[0] ) );
254 204 }
255 205 }
256 206 }
257 207 }
@@ -262,9 +212,10 @@
262 212 *
263 213 * @access public
264 214 */
265 215 public function init() {
266 - if ( current_user_can( 'edit_posts' ) && current_user_can( 'edit_pages' ) && 'true' === get_user_option( 'rich_editing' ) ) {
216 + // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
217 + if ( current_user_can( 'edit_posts' ) && current_user_can( 'edit_pages' ) && 'true' == get_user_option( 'rich_editing' ) ) {
267 218 $this->_addFilter( 'mce_external_languages', 'add_tinymce_lang', 10, 1 );
268 219 $this->_addFilter( 'mce_external_plugins', 'tinymce_plugin', 10, 1 );
269 220 $this->_addFilter( 'mce_buttons', 'register_mce_button', 10, 1 );
270 221 $this->_addFilter( 'tiny_mce_before_init', 'get_strings_for_block', 10, 1 );
@@ -276,9 +227,9 @@
276 227 *
277 228 * @since ?
278 229 * @access friendly
279 230 */
280 - public function get_strings_for_block( $settings ) {
231 + function get_strings_for_block( $settings ) {
281 232 $class = new Visualizer_Module_Language();
282 233 $strings = $class->get_strings();
283 234 $array = array( 'visualizer_tinymce_plugin' => json_encode( $strings ) );
284 235 return array_merge( $settings, $array );
@@ -354,40 +305,15 @@
354 305 * @access public
355 306 */
356 307 public function enqueueMediaScripts() {
357 308 global $typenow;
358 - global $current_screen;
359 -
360 - if ( post_type_supports( $typenow, 'editor' ) || $current_screen->id === 'widgets' || $current_screen->id === 'customize' ) {
309 + if ( post_type_supports( $typenow, 'editor' ) ) {
361 310 wp_enqueue_style( 'visualizer-media', VISUALIZER_ABSURL . 'css/media.css', array( 'media-views' ), Visualizer_Plugin::VERSION );
362 311
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 312 // Load all the assets for the different libraries we support.
387 313 $deps = array(
388 314 Visualizer_Render_Sidebar_Google::enqueue_assets( array( 'media-editor' ) ),
389 - Visualizer_Render_Sidebar_Type_DataTable_Tabular::enqueue_assets( array( 'media-editor' ) ),
315 + Visualizer_Render_Sidebar_Type_DataTable_DataTable::enqueue_assets( array( 'media-editor' ) ),
390 316 );
391 317
392 318 wp_enqueue_script( 'visualizer-media-model', VISUALIZER_ABSURL . 'js/media/model.js', $deps, Visualizer_Plugin::VERSION, true );
393 319 wp_enqueue_script( 'visualizer-media-collection', VISUALIZER_ABSURL . 'js/media/collection.js', array( 'visualizer-media-model' ), Visualizer_Plugin::VERSION, true );
@@ -397,9 +323,9 @@
397 323 'visualizer-media-view',
398 324 'visualizer',
399 325 array(
400 326 'i10n' => array(
401 - 'insert' => __( 'Insert Chart', 'visualizer' ),
327 + 'insert' => __( 'Insert', 'visualizer' ),
402 328 ),
403 329 )
404 330 );
405 331 wp_enqueue_script( 'visualizer-media-toolbar', VISUALIZER_ABSURL . 'js/media/toolbar.js', array( 'visualizer-media-view' ), Visualizer_Plugin::VERSION, true );
@@ -428,9 +354,9 @@
428 354 'controller' => array(
429 355 'title' => esc_html__( 'Visualizations', 'visualizer' ),
430 356 ),
431 357 'routers' => array(
432 - 'library' => esc_html__( 'Insert from Library', 'visualizer' ),
358 + 'library' => esc_html__( 'From Library', 'visualizer' ),
433 359 'create' => esc_html__( 'Create New', 'visualizer' ),
434 360 ),
435 361 'library' => array(
436 362 'filters' => $chart_types,
@@ -435,10 +361,10 @@
435 361 'library' => array(
436 362 'filters' => $chart_types,
437 363 'types' => array_keys( $chart_types ),
438 364 ),
439 - 'nonce' => wp_create_nonce( Visualizer_Plugin::ACTION_GET_CHARTS ),
440 - 'buildurl' => esc_url( add_query_arg( 'action', Visualizer_Plugin::ACTION_CREATE_CHART, admin_url( 'admin-ajax.php' ) ) ),
365 + 'nonce' => wp_create_nonce(),
366 + 'buildurl' => add_query_arg( 'action', Visualizer_Plugin::ACTION_CREATE_CHART, admin_url( 'admin-ajax.php' ) ),
441 367 );
442 368
443 369 return $strings;
444 370 }
@@ -460,17 +386,15 @@
460 386 'enabled' => true,
461 387 );
462 388 }
463 389
464 - $enabled = self::proFeaturesEnabled();
465 -
466 390 $types = array_merge(
467 391 $additional,
468 392 array(
469 - 'tabular' => array(
393 + 'dataTable' => array(
470 394 'name' => esc_html__( 'Table', 'visualizer' ),
471 395 'enabled' => true,
472 - 'supports' => $enabled ? array( 'Google Charts', 'DataTable' ) : array( 'DataTable' ),
396 + 'supports' => array( 'DataTable' ),
473 397 ),
474 398 'pie' => array(
475 399 'name' => esc_html__( 'Pie/Donut', 'visualizer' ),
476 400 'enabled' => true,
@@ -480,81 +404,75 @@
480 404 'name' => esc_html__( 'Line', 'visualizer' ),
481 405 'enabled' => true,
482 406 'supports' => array( 'Google Charts', 'ChartJS' ),
483 407 ),
484 - 'bar' => array(
485 - 'name' => esc_html__( 'Bar', 'visualizer' ),
486 - 'enabled' => true,
487 - 'supports' => $enabled ? array( 'Google Charts', 'ChartJS' ) : array( 'Google Charts' ),
488 - ),
489 408 'area' => array(
490 409 'name' => esc_html__( 'Area', 'visualizer' ),
491 - 'enabled' => $enabled,
410 + 'enabled' => true,
492 411 // in ChartJS, the fill option is used to make Line chart an area: https://www.chartjs.org/docs/latest/charts/area.html
493 412 'supports' => array( 'Google Charts' ),
494 - 'demo_url' => 'https://demo.themeisle.com/visualizer/area-chart/',
495 413 ),
496 414 'geo' => array(
497 415 'name' => esc_html__( 'Geo', 'visualizer' ),
498 - 'enabled' => $enabled,
416 + 'enabled' => true,
499 417 'supports' => array( 'Google Charts' ),
500 - 'demo_url' => 'https://demo.themeisle.com/visualizer/geo-chart/',
501 418 ),
419 + 'bar' => array(
420 + 'name' => esc_html__( 'Bar', 'visualizer' ),
421 + 'enabled' => true,
422 + 'supports' => array( 'Google Charts', 'ChartJS' ),
423 + ),
502 424 'column' => array(
503 425 'name' => esc_html__( 'Column', 'visualizer' ),
504 - 'enabled' => $enabled,
426 + 'enabled' => true,
505 427 'supports' => array( 'Google Charts', 'ChartJS' ),
506 - 'demo_url' => 'https://demo.themeisle.com/visualizer/column-chart/',
507 428 ),
508 429 'bubble' => array(
509 430 'name' => esc_html__( 'Bubble', 'visualizer' ),
510 - 'enabled' => $enabled,
431 + 'enabled' => true,
511 432 // 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 433 'supports' => array( 'Google Charts' ),
513 - 'demo_url' => 'https://demo.themeisle.com/visualizer/bubble-chart/',
514 434 ),
515 435 'scatter' => array(
516 436 'name' => esc_html__( 'Scatter', 'visualizer' ),
517 - 'enabled' => $enabled,
437 + 'enabled' => true,
518 438 'supports' => array( 'Google Charts' ),
519 - 'demo_url' => 'https://demo.themeisle.com/visualizer/scatter-chart/',
520 439 ),
521 440 'gauge' => array(
522 441 'name' => esc_html__( 'Gauge', 'visualizer' ),
523 - 'enabled' => $enabled,
442 + 'enabled' => true,
524 443 'supports' => array( 'Google Charts' ),
525 - 'demo_url' => 'https://demo.themeisle.com/visualizer/gauge-chart/',
526 444 ),
527 445 'candlestick' => array(
528 446 'name' => esc_html__( 'Candlestick', 'visualizer' ),
529 - 'enabled' => $enabled,
447 + 'enabled' => true,
530 448 'supports' => array( 'Google Charts' ),
531 - 'demo_url' => 'https://demo.themeisle.com/visualizer/candlestick-chart/',
532 449 ),
533 450 // pro types
451 + 'table' => array(
452 + 'name' => esc_html__( 'Table (Deprecated)', 'visualizer' ),
453 + 'enabled' => false,
454 + 'supports' => array( 'Google Charts' ),
455 + ),
534 456 'timeline' => array(
535 457 'name' => esc_html__( 'Timeline', 'visualizer' ),
536 458 'enabled' => false,
537 459 'supports' => array( 'Google Charts', 'ChartJS' ),
538 - 'demo_url' => 'https://demo.themeisle.com/visualizer/timeline-chart/',
539 460 ),
540 461 'combo' => array(
541 462 'name' => esc_html__( 'Combo', 'visualizer' ),
542 463 'enabled' => false,
543 464 'supports' => array( 'Google Charts' ),
544 - 'demo_url' => 'https://demo.themeisle.com/visualizer/combo-chart/',
545 465 ),
546 466 'polarArea' => array(
547 467 'name' => esc_html__( 'Polar Area', 'visualizer' ),
548 468 'enabled' => false,
549 469 'supports' => array( 'ChartJS' ),
550 - 'demo_url' => 'https://demo.themeisle.com/visualizer/polar-area-chart/',
551 470 ),
552 471 'radar' => array(
553 472 'name' => esc_html__( 'Radar/Spider', 'visualizer' ),
554 473 'enabled' => false,
555 474 'supports' => array( 'ChartJS' ),
556 - 'demo_url' => 'https://demo.themeisle.com/visualizer/radar-spider-chart/',
557 475 ),
558 476 )
559 477 );
560 478 $types = apply_filters( 'visualizer_pro_chart_types', $types );
@@ -604,8 +522,18 @@
604 522 switch ( $where ) {
605 523 case 'types':
606 524 // fall-through
607 525 case 'library':
526 + // if the user has a Google Table chart, show it as deprecated otherwise remove the option from the library.
527 + if ( ! self::hasChartType( 'table' ) ) {
528 + $deprecated[] = 'table';
529 + if ( $get2Darray ) {
530 + $types['dataTable'] = esc_html__( 'Table', 'visualizer' );
531 + } else {
532 + $types['dataTable']['name'] = esc_html__( 'Table', 'visualizer' );
533 + }
534 + }
535 +
608 536 // if a user has a Gauge/Candlestick chart, then let them keep using it.
609 537 if ( ! Visualizer_Module::is_pro() ) {
610 538 if ( ! self::hasChartType( 'gauge' ) ) {
611 539 if ( $get2Darray ) {
@@ -623,8 +551,18 @@
623 551 }
624 552 }
625 553 break;
626 554 default:
555 + // remove the option to create a Google Table chart.
556 + $deprecated[] = 'table';
557 +
558 + // rename the new table chart type.
559 + if ( $get2Darray ) {
560 + $types['dataTable'] = esc_html__( 'Table', 'visualizer' );
561 + } else {
562 + $types['dataTable']['name'] = esc_html__( 'Table', 'visualizer' );
563 + }
564 +
627 565 // if a user has a Gauge/Candlestick chart, then let them keep using it.
628 566 if ( ! Visualizer_Module::is_pro() ) {
629 567 if ( ! self::hasChartType( 'gauge' ) ) {
630 568 if ( $get2Darray ) {
@@ -681,159 +619,44 @@
681 619 *
682 620 * @param string $suffix The current page suffix.
683 621 */
684 622 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 - }
623 + if ( $suffix === $this->_libraryPage ) {
624 + wp_enqueue_style( 'visualizer-library', VISUALIZER_ABSURL . 'css/library.css', array(), Visualizer_Plugin::VERSION );
625 + $this->_addFilter( 'media_upload_tabs', 'setupVisualizerTab' );
626 + wp_enqueue_media();
714 627 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 ),
628 + 'visualizer-library',
629 + VISUALIZER_ABSURL . 'js/library.js',
630 + array(
631 + 'jquery',
632 + 'media-views',
633 + ),
718 634 Visualizer_Plugin::VERSION,
719 635 true
720 636 );
721 - if ( 'd3' === $library ) {
722 - $has_d3 = true;
723 - }
724 - }
725 637
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 - }
638 + wp_enqueue_script( 'visualizer-customization', $this->get_user_customization_js(), array(), null, true );
752 639
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,
640 + $query = $this->getQuery();
641 + while ( $query->have_posts() ) {
642 + $chart = $query->next_post();
643 + $library = $this->load_chart_type( $chart->ID );
644 + if ( is_null( $library ) ) {
645 + continue;
646 + }
647 + wp_enqueue_script(
648 + "visualizer-render-$library",
649 + VISUALIZER_ABSURL . 'js/render-facade.js',
650 + apply_filters( 'visualizer_assets_render', array( 'visualizer-library', 'visualizer-customization' ), true ),
651 + Visualizer_Plugin::VERSION,
768 652 true
769 653 );
770 654 }
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 655 }
819 -
820 - do_action( 'themeisle_internal_page', VISUALIZER_DIRNAME, 'library' );
821 656 }
822 657
823 658 /**
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 659 * Adds visualizer tab for media upload tabs array.
837 660 *
838 661 * @since 1.0.0
839 662 *
@@ -865,9 +688,9 @@
865 688 Visualizer_Plugin::NAME,
866 689 __( 'Chart Library', 'visualizer' ),
867 690 __( 'Chart Library', 'visualizer' ),
868 691 'edit_posts',
869 - 'admin.php?page=' . Visualizer_Plugin::NAME
692 + admin_url( 'admin.php?page=' . Visualizer_Plugin::NAME )
870 693 );
871 694 add_submenu_page(
872 695 Visualizer_Plugin::NAME,
873 696 __( 'Add New Chart', 'visualizer' ),
@@ -872,22 +695,12 @@
872 695 Visualizer_Plugin::NAME,
873 696 __( 'Add New Chart', 'visualizer' ),
874 697 __( 'Add New Chart', 'visualizer' ),
875 698 'edit_posts',
876 - 'admin.php?page=' . Visualizer_Plugin::NAME . '&vaction=addnew'
699 + admin_url( 'admin.php?page=' . Visualizer_Plugin::NAME . '&vaction=addnew' )
877 700 );
878 -
879 - $this->_settingsPage = add_submenu_page(
701 + add_submenu_page(
880 702 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 703 __( 'Support', 'visualizer' ),
891 704 __( '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 705 'edit_posts',
893 706 'viz-support',
@@ -892,151 +705,12 @@
892 705 'edit_posts',
893 706 'viz-support',
894 707 array( $this, 'renderSupportPage' )
895 708 );
896 -
897 709 remove_submenu_page( Visualizer_Plugin::NAME, Visualizer_Plugin::NAME );
898 -
899 - add_action( "load-{$this->_libraryPage}", array( $this, 'addScreenOptions' ) );
900 - add_action( 'admin_footer', array( $this, 'handleGetProSubMenu' ) );
901 710 }
902 711
903 712 /**
904 - * Handle get pro plugin submenu.
905 - */
906 - public function handleGetProSubMenu() {
907 - if ( ! Visualizer_Module::is_pro() ) {
908 - ?>
909 - <style type="text/css">
910 - #toplevel_page_visualizer ul.wp-submenu li:last-child {
911 - background: #FF7E65;
912 - font-size: 14px;
913 - font-weight: 600;
914 - color: #fff;
915 - }
916 - #toplevel_page_visualizer ul.wp-submenu li:last-child > a > span {
917 - color: #fff !important;
918 - }
919 - #toplevel_page_visualizer ul.wp-submenu li:last-child > a:hover {
920 - box-shadow: inherit;
921 - }
922 - </style>
923 - <?php
924 - if ( get_option( 'visualizer_fresh_install', false ) ) {
925 - ?>
926 - <style type="text/css">
927 - #toplevel_page_visualizer ul.wp-submenu li.wp-first-item + li + li + li {
928 - display: none;
929 - }
930 - </style>
931 - <?php
932 - }
933 - }
934 - }
935 -
936 - /**
937 - * Adds the screen options for pagination.
938 - */
939 - public function addScreenOptions() {
940 - $screen = get_current_screen();
941 -
942 - // bail if it's some other page.
943 - if ( ! is_object( $screen ) || $screen->id !== $this->_libraryPage ) {
944 - return;
945 - }
946 -
947 - $args = array(
948 - 'label' => __( 'Number of charts per page:', 'visualizer' ),
949 - 'default' => 6,
950 - 'option' => 'visualizer_library_per_page',
951 - );
952 - add_screen_option( 'per_page', $args );
953 - }
954 -
955 - /**
956 - * Returns the screen option for pagination.
957 - */
958 - public function setScreenOptions( $status, $option, $value ) {
959 - if ( 'visualizer_library_per_page' === $option ) {
960 - return $value;
961 - }
962 - }
963 -
964 - /**
965 - * Adds the display filters to be used in the meta_query while displaying the charts.
966 - */
967 - private function getDisplayFilters( &$query_args ) {
968 - $query = array();
969 - global $sitepress;
970 - if ( Visualizer_Module::is_pro() && ( function_exists( 'icl_get_languages' ) && $sitepress instanceof \SitePress ) ) {
971 - $current_lang = icl_get_current_language();
972 - if ( in_array( $current_lang, array( 'all', icl_get_default_language() ), true ) ) {
973 - $query[] = array(
974 - 'key' => 'chart_lang',
975 - 'compare' => 'NOT EXISTS',
976 - );
977 - } else {
978 - $query[] = array(
979 - 'key' => 'chart_lang',
980 - 'value' => $current_lang,
981 - 'compare' => '=',
982 - );
983 - }
984 - }
985 -
986 - // add chart type filter to the query arguments
987 - $type = filter_input( INPUT_GET, 'type' );
988 - if ( $type && in_array( $type, Visualizer_Plugin::getChartTypes(), true ) ) {
989 - $query[] = array(
990 - 'key' => Visualizer_Plugin::CF_CHART_TYPE,
991 - 'value' => $type,
992 - 'compare' => '=',
993 - );
994 - }
995 -
996 - // add chart library filter to the query arguments
997 - $library = filter_input( INPUT_GET, 'library' );
998 - if ( $library ) {
999 - $query[] = array(
1000 - 'key' => Visualizer_Plugin::CF_CHART_LIBRARY,
1001 - 'value' => $library,
1002 - 'compare' => '=',
1003 - );
1004 - }
1005 -
1006 - // add date filter to the query arguments
1007 - $date = filter_input( INPUT_GET, 'date' );
1008 - $possible = array_keys( Visualizer_Plugin::getSupportedDateFilter() );
1009 - if ( $date && in_array( $date, $possible, true ) ) {
1010 - $query_args['date_query'] = array(
1011 - 'after' => "$date -1 day",
1012 - 'inclusive' => true,
1013 - );
1014 - }
1015 -
1016 - // add source filter to the query arguments
1017 - $source = filter_input( INPUT_GET, 'source' );
1018 - if ( $source ) {
1019 - $source = ucwords( $source );
1020 - $source = "Visualizer_Source_{$source}";
1021 - $query[] = array(
1022 - 'key' => Visualizer_Plugin::CF_SOURCE,
1023 - 'value' => $source,
1024 - 'compare' => '=',
1025 - );
1026 - }
1027 -
1028 - $query_args['meta_query'] = $query;
1029 -
1030 - $orderby = filter_input( INPUT_GET, 'orderby' );
1031 - $order = filter_input( INPUT_GET, 'order' );
1032 - if ( $orderby ) {
1033 - $query_args['order_by'] = $orderby;
1034 - }
1035 - $query_args['order'] = empty( $order ) ? 'desc' : $order;
1036 - }
1037 -
1038 - /**
1039 713 * Get the instance of WP_Query that fetches the charts as per the given criteria.
1040 714 */
1041 715 private function getQuery() {
1042 716 static $q;
@@ -1055,34 +729,29 @@
1055 729 'default' => 1,
1056 730 ),
1057 731 )
1058 732 );
1059 -
1060 - $per_page = 6;
1061 - $screen = get_current_screen();
1062 - if ( $screen ) {
1063 - // retrieve the per_page option
1064 - $screen_option = $screen->get_option( 'per_page', 'option' );
1065 - // retrieve the value stored for the current user
1066 - $user = get_current_user_id();
1067 - $per_page = get_user_meta( $user, $screen_option, true );
1068 - if ( empty( $per_page ) || $per_page < 1 ) {
1069 - // nothing set, get the default value
1070 - $per_page = $screen->get_option( 'per_page', 'default' );
1071 - }
1072 - }
1073 -
1074 733 // the initial query arguments to fetch charts
1075 734 $query_args = array(
1076 735 'post_type' => Visualizer_Plugin::CPT_VISUALIZER,
1077 - 'posts_per_page' => $per_page,
736 + 'posts_per_page' => 6,
1078 737 'paged' => $page,
1079 738 );
1080 -
1081 - $this->getDisplayFilters( $query_args );
1082 -
739 + // add chart type filter to the query arguments
740 + $filter = filter_input( INPUT_GET, 'type' );
741 + if ( $filter && in_array( $filter, Visualizer_Plugin::getChartTypes(), true ) ) {
742 + $query_args['meta_query'] = array(
743 + array(
744 + 'key' => Visualizer_Plugin::CF_CHART_TYPE,
745 + 'value' => $filter,
746 + 'compare' => '=',
747 + ),
748 + );
749 + } else {
750 + $filter = 'all';
751 + }
1083 752 // Added by Ash/Upwork
1084 - $filterByMeta = ! empty( $_GET['s'] ) ? sanitize_text_field( wp_unslash( $_GET['s'] ) ) : null; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
753 + $filterByMeta = filter_input( INPUT_GET, 's', FILTER_SANITIZE_STRING );
1085 754 if ( $filterByMeta ) {
1086 755 $query = array(
1087 756 'key' => Visualizer_Plugin::CF_SETTINGS,
1088 757 'value' => $filterByMeta,
@@ -1108,91 +777,8 @@
1108 777 include_once VISUALIZER_ABSPATH . '/templates/support.php';
1109 778 }
1110 779
1111 780 /**
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 781 * Renders visualizer library page.
1196 782 *
1197 783 * @since 1.0.0
1198 784 *
@@ -1243,22 +829,10 @@
1243 829 unset( $settings['height'], $settings['width'], $settings['chartArea'] );
1244 830 }
1245 831
1246 832 $series = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_SERIES, get_post_meta( $chart->ID, Visualizer_Plugin::CF_SERIES, true ), $chart->ID, $type );
1247 - $data = self::get_chart_data( $chart, $type );
833 + $data = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_DATA, unserialize( html_entity_decode( $chart->post_content ) ), $chart->ID, $type );
1248 834
1249 - // Set default setting series when add manual chart data - Only during first creation.
1250 - if ( isset( $settings['series'] ) && ! empty( $series ) ) {
1251 - $count_series = count( $series ) - count( $settings['series'] );
1252 - if ( $count_series > 1 ) {
1253 - $clone_last_series = end( $settings['series'] );
1254 - $clone_last_series = array_fill_keys( array_keys( $clone_last_series ), '' );
1255 - foreach ( range( 1, $count_series ) as $item ) {
1256 - $settings['series'][] = $clone_last_series;
1257 - }
1258 - }
1259 - }
1260 -
1261 835 $library = $this->load_chart_type( $chart->ID );
1262 836
1263 837 $id = 'visualizer-' . $chart->ID;
1264 838 $arguments = $this->get_inline_custom_css( $id, $settings );
@@ -1266,19 +840,11 @@
1266 840 $css .= $arguments[0];
1267 841 $settings = $arguments[1];
1268 842 }
1269 843
1270 - if ( isset( $settings['controls']['ui']['labelStacking'] ) ) {
1271 - unset( $settings['controls']['ui']['labelStacking'] );
1272 - }
1273 - if ( isset( $settings['controls']['ui']['orientation'] ) ) {
1274 - unset( $settings['controls']['ui']['orientation'] );
1275 - }
1276 -
1277 844 // add chart to the array
1278 845 $charts[ $id ] = array(
1279 846 'id' => $chart->ID,
1280 - 'title' => $chart->post_title,
1281 847 'type' => $type,
1282 848 'series' => $series,
1283 849 'settings' => $settings,
1284 850 'data' => $data,
@@ -1283,15 +849,11 @@
1283 849 'settings' => $settings,
1284 850 'data' => $data,
1285 851 'library' => $library,
1286 852 );
1287 - if ( 'd3' === $library ) {
1288 - $charts[ $id ]['code'] = get_post_meta( $chart->ID, Visualizer_Module_AIBuilder::CF_D3_CODE, true );
1289 - }
1290 853 }
1291 854 // enqueue charts array
1292 855 $ajaxurl = admin_url( 'admin-ajax.php' );
1293 -
1294 856 wp_localize_script(
1295 857 'visualizer-library',
1296 858 'visualizer',
1297 859 array(
@@ -1298,39 +860,30 @@
1298 860 'language' => $this->get_language(),
1299 861 'map_api_key' => get_option( 'visualizer-map-api-key' ),
1300 862 'charts' => $charts,
1301 863 'urls' => array(
1302 - 'base' => esc_url( add_query_arg( array( 'vpage' => false, 'vaction' => false ) ) ),
1303 - 'create' => esc_url(
1304 - add_query_arg(
1305 - array(
1306 - 'action' => Visualizer_Plugin::ACTION_CREATE_CHART,
1307 - 'library' => 'yes',
1308 - 'type' => isset( $_GET['type'] ) ? $_GET['type'] : '',
1309 - 'chart-library' => isset( $_GET['chart-library'] ) ? $_GET['chart-library'] : '',
1310 - 'vaction' => false,
1311 - ),
1312 - $ajaxurl
1313 - )
864 + 'base' => add_query_arg( array( 'vpage' => false, 'vaction' => false ) ),
865 + 'create' => add_query_arg(
866 + array(
867 + 'action' => Visualizer_Plugin::ACTION_CREATE_CHART,
868 + 'library' => 'yes',
869 + 'type' => isset( $_GET['type'] ) ? $_GET['type'] : '',
870 + 'chart-library' => isset( $_GET['chart-library'] ) ? $_GET['chart-library'] : '',
871 + 'vaction' => false,
872 + ),
873 + $ajaxurl
1314 874 ),
1315 - 'edit' => esc_url(
1316 - add_query_arg(
1317 - array(
1318 - 'action' => Visualizer_Plugin::ACTION_EDIT_CHART,
1319 - 'library' => 'yes',
1320 - 'vaction' => false,
1321 - ),
1322 - $ajaxurl
1323 - )
875 + 'edit' => add_query_arg(
876 + array(
877 + 'action' => Visualizer_Plugin::ACTION_EDIT_CHART,
878 + 'library' => 'yes',
879 + 'vaction' => false,
880 + ),
881 + $ajaxurl
1324 882 ),
1325 883 ),
1326 884 'page_type' => 'library',
1327 885 'is_front' => false,
1328 - 'i10n' => array(
1329 - 'copied' => __( 'The shortcode has been copied to your clipboard. Hit Ctrl-V/Cmd-V to paste it.', 'visualizer' ),
1330 - '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' ),
1331 - ),
1332 - 'is_pro_user' => Visualizer_Module::is_pro(),
1333 886 )
1334 887 );
1335 888 // render library page
1336 889 $render = new Visualizer_Render_Library();
@@ -1346,9 +899,8 @@
1346 899 'total' => $query->max_num_pages,
1347 900 'type' => 'array',
1348 901 )
1349 902 );
1350 -
1351 903 $render->render();
1352 904 }
1353 905
1354 906 /**
@@ -1390,268 +942,21 @@
1390 942 *
1391 943 * @return array Updated array of plugin meta links.
1392 944 */
1393 945 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 946 if ( $plugin_file === plugin_basename( VISUALIZER_BASEFILE ) ) {
1409 - $is_black_friday = apply_filters( 'themeisle_sdk_is_black_friday_sale', false );
1410 947 // knowledge base link
1411 948 $plugin_meta[] = sprintf(
1412 949 '<a href="' . VISUALIZER_MAIN_DOC . '" target="_blank">%s</a>',
1413 950 esc_html__( 'Docs', 'visualizer' )
1414 951 );
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 - }
952 + // flattr link
953 + $plugin_meta[] = sprintf(
954 + '<a style="color:red" href="' . Visualizer_Plugin::PRO_TEASER_URL . '" target="_blank">%s</a>',
955 + esc_html__( 'Pro Addon', 'visualizer' )
956 + );
1422 957 }
1423 958
1424 959 return $plugin_meta;
1425 960 }
1426 961
1427 - /**
1428 - * Returns true when premium chart types should be enabled for the current user.
1429 - *
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
1439 - */
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 ) {
1445 - return true;
1446 - }
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;
1459 - }
1460 -
1461 - /**
1462 - * Multilingual Support.
1463 - *
1464 - * @param int $chart_id Chart ID.
1465 - * @return bool Default false
1466 - */
1467 - public function addMultilingualSupport( $chart_id ) {
1468 - global $sitepress;
1469 - if ( Visualizer_Module::is_pro() ) {
1470 - return;
1471 - }
1472 - if ( function_exists( 'icl_get_languages' ) && $sitepress instanceof \SitePress ) {
1473 - $language = icl_get_languages();
1474 - $current_lang = icl_get_current_language();
1475 - $default_lang = icl_get_default_language();
1476 - $post_info = wpml_get_language_information( null, $chart_id );
1477 - $translations = array();
1478 - if ( ! empty( $post_info ) && ( $default_lang === $post_info['language_code'] ) ) {
1479 - $trid = $sitepress->get_element_trid( $chart_id, 'post_' . Visualizer_Plugin::CPT_VISUALIZER );
1480 - $translations = $sitepress->get_element_translations( $trid );
1481 - }
1482 - if ( empty( $translations ) ) {
1483 - return;
1484 - }
1485 - ?>
1486 - <hr><div class="visualizer-languages-list only-pro">
1487 - <?php
1488 - foreach ( $language as $lang ) {
1489 - $lang_code = $lang['code'];
1490 - if ( $current_lang !== $lang_code ) {
1491 - ?>
1492 - <a href="javascript:;">
1493 - <img src="<?php echo esc_url( $lang['country_flag_url'] ); ?>" alt="<?php echo esc_attr( $lang['translated_name'] ); ?>">
1494 - </a>
1495 - <?php
1496 - }
1497 - }
1498 - ?>
1499 - <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>
1500 - </div>
1501 - <?php
1502 - }
1503 - }
1504 -
1505 - /**
1506 - * Check chart is enabled or not.
1507 - *
1508 - * @param string $type Chart ID.
1509 - *
1510 - * @return bool Default false
1511 - */
1512 - public static function checkChartStatus( $type ) {
1513 - $types = self::_getChartTypesLocalized( false, false, false, true );
1514 - if ( isset( $types[ $type ] ) ) {
1515 - return ! empty( $types[ $type ]['enabled'] );
1516 - }
1517 - return false;
1518 - }
1519 -
1520 - /**
1521 - * Get the survey metadata.
1522 - *
1523 - * @param array $data The data for survey in Formbricks format.
1524 - * @param string $page_slug The slug of the loaded page.
1525 - *
1526 - * @return array The survey metadata.
1527 - */
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 );
1531 -
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 );
1535 -
1536 - $plugin_data = get_plugin_data( VISUALIZER_BASEFILE, false, false );
1537 - $plugin_version = '';
1538 -
1539 - if ( ! empty( $plugin_data['Version'] ) ) {
1540 - $plugin_version = $plugin_data['Version'];
1541 - }
1542 -
1543 - $count_charts_cache_key = 'visualizer_count_charts';
1544 - $charts_number = get_transient( $count_charts_cache_key );
1545 -
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 );
1551 - }
1552 -
1553 - $data = array(
1554 - 'environmentId' => 'cltef8cut1s7wyyfxy3rlxzs5',
1555 - '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,
1561 - ),
1562 - );
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 - }
1574 -
1575 - /**
1576 - * Count the charts.
1577 - *
1578 - * @param int $limit The count limit (optional).
1579 - *
1580 - * @return int The number of charts.
1581 - */
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 - );
1589 -
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%' );
1633 - }
1634 -
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 - );
1640 -
1641 - if ( ( $is_pro || $is_expired ) && ! empty( $pro_product_slug ) ) {
1642 - $config['plugin_meta_targets'] = array( $pro_product_slug );
1643 - }
1644 -
1645 - $config['message'] = $message;
1646 - $config['cta_label'] = $cta_label;
1647 -
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;
1656 - }
1657 962 }