PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 4.0.8
Visualizer – Tables & Charts Manager with Built-in AI Generator v4.0.8
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 +1142 -108 3.0.84.0.8 View file →
@@ -29,8 +29,10 @@
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 +
33 35 /**
34 36 * Library page suffix.
35 37 *
36 38 * @since 1.0.0
@@ -40,8 +42,24 @@
40 42 */
41 43 private $_libraryPage;
42 44
43 45 /**
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 + /**
44 62 * Constructor.
45 63 *
46 64 * @since 1.0.0
47 65 *
@@ -52,26 +70,138 @@
52 70 public function __construct( Visualizer_Plugin $plugin ) {
53 71 parent::__construct( $plugin );
54 72 $this->_addAction( 'load-post.php', 'enqueueMediaScripts' );
55 73 $this->_addAction( 'load-post-new.php', 'enqueueMediaScripts' );
56 - $this->_addAction( 'admin_footer', 'renderTempaltes' );
57 - $this->_addAction( 'admin_enqueue_scripts', 'enqueueLibraryScripts', null, 8 );
74 + $this->_addAction( 'enqueue_block_editor_assets', 'enqueueMediaScripts' );
75 + $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' );
58 80 $this->_addAction( 'admin_menu', 'registerAdminMenu' );
59 81 $this->_addFilter( 'media_view_strings', 'setupMediaViewStrings' );
60 82 $this->_addFilter( 'plugin_action_links', 'getPluginActionLinks', 10, 2 );
61 - $this->_addFilter( 'visualizer_logger_data', 'getLoggerData' );
62 - $this->_addFilter( 'visualizer_get_chart_counts', 'getChartCountsByTypeAndMeta' );
83 + $this->_addFilter( 'plugin_row_meta', 'getPluginMetaLinks', 10, 2 );
63 84 $this->_addFilter( 'visualizer_feedback_review_trigger', 'feedbackReviewTrigger' );
85 + $this->_addFilter( 'themeisle_sdk_blackfriday_data', 'add_black_friday_data' );
64 86
87 + // screen pagination
88 + $this->_addFilter( 'set-screen-option', 'setScreenOptions', 10, 3 );
89 +
65 90 // revision support.
66 91 $this->_addFilter( 'wp_revisions_to_keep', 'limitRevisions', null, 10, 2 );
67 92 $this->_addAction( '_wp_put_post_revision', 'addRevision', null, 10, 1 );
68 93 $this->_addAction( 'wp_restore_post_revision', 'restoreRevision', null, 10, 2 );
69 94
95 + $this->_addAction( 'visualizer_chart_schedules_spl', 'addSplChartSchedules', null, 10, 3 );
96 +
70 97 $this->_addAction( 'admin_init', 'init' );
98 +
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' ) ) {
108 + $this->load_cypress_hooks();
109 + }
71 110 }
111 + /**
112 + * Display review notice.
113 + */
114 + public function render_review_notice( $footer_text ) {
115 + $current_screen = get_current_screen();
72 116
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 + }
136 +
137 +
73 138 /**
139 + * Define the hooks that are needed for cypress.
140 + *
141 + * @since 3.4.0
142 + * @access private
143 + */
144 + private function load_cypress_hooks() {
145 + // all charts should load on the same page without pagination.
146 + add_filter(
147 + 'visualizer_query_args', function ( $args ) {
148 + $args['posts_per_page'] = 20;
149 + return $args;
150 + }, 10, 1
151 + );
152 + }
153 +
154 + /**
155 + * Add disabled `optgroup` schedules to the drop downs.
156 + *
157 + * @since ?
158 + *
159 + * @access public
160 + *
161 + * @param string $feature The feature for which to add schedules.
162 + * @param int $chart_id The chart ID.
163 + * @param int $plan The plan number.
164 + */
165 + public function addSplChartSchedules( $feature, $chart_id, $plan ) {
166 + if ( apply_filters( 'visualizer_is_business', false ) ) {
167 + return;
168 + }
169 +
170 + $is_new_personal = apply_filters( 'visualizer_is_new_personal', false );
171 +
172 + $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' ),
178 + );
179 +
180 + switch ( $feature ) {
181 + case 'json':
182 + case 'csv':
183 + // no more schedules if pro is already active.
184 + if ( Visualizer_Module::is_pro() && ! $is_new_personal ) {
185 + return;
186 + }
187 + break;
188 + case 'wp':
189 + // fall-through.
190 + case 'db':
191 + break;
192 + default:
193 + return;
194 + }
195 +
196 + echo '<optgroup disabled label="' . __( 'Upgrade required', 'visualizer' ) . '">';
197 + foreach ( $hours as $hour => $desc ) {
198 + echo '<option disabled>' . $desc . '</option>';
199 + }
200 + echo '</optgroup>';
201 + }
202 +
203 + /**
74 204 * No limits on revisions.
75 205 */
76 206 public function limitRevisions( $num, $post ) {
77 207 if ( Visualizer_Plugin::CPT_VISUALIZER === $post->post_type ) {
@@ -91,9 +221,9 @@
91 221
92 222 if ( $meta ) {
93 223 foreach ( $meta as $key => $value ) {
94 224 if ( 0 === strpos( $key, 'visualizer' ) ) {
95 - add_metadata( 'post', $revision_id, $key, maybe_unserialize( $value[0] ) );
225 + add_metadata( 'post', $revision_id, $key, self::maybe_decode_content( $value[0] ) );
96 226 }
97 227 }
98 228 }
99 229 }
@@ -119,9 +249,9 @@
119 249
120 250 if ( $meta ) {
121 251 foreach ( $meta as $key => $value ) {
122 252 if ( 0 === strpos( $key, 'visualizer' ) ) {
123 - add_post_meta( $post_id, $key, maybe_unserialize( $value[0] ) );
253 + add_post_meta( $post_id, $key, self::maybe_decode_content( $value[0] ) );
124 254 }
125 255 }
126 256 }
127 257 }
@@ -132,16 +262,30 @@
132 262 *
133 263 * @access public
134 264 */
135 265 public function init() {
136 - if ( current_user_can( 'edit_posts' ) && current_user_can( 'edit_pages' ) && 'true' == get_user_option( 'rich_editing' ) ) {
266 + if ( current_user_can( 'edit_posts' ) && current_user_can( 'edit_pages' ) && 'true' === get_user_option( 'rich_editing' ) ) {
137 267 $this->_addFilter( 'mce_external_languages', 'add_tinymce_lang', 10, 1 );
138 268 $this->_addFilter( 'mce_external_plugins', 'tinymce_plugin', 10, 1 );
139 269 $this->_addFilter( 'mce_buttons', 'register_mce_button', 10, 1 );
270 + $this->_addFilter( 'tiny_mce_before_init', 'get_strings_for_block', 10, 1 );
140 271 }
141 272 }
142 273
143 274 /**
275 + * Add the strings required for the TinyMCE buttons for the classic block (not the classic editor).
276 + *
277 + * @since ?
278 + * @access friendly
279 + */
280 + public function get_strings_for_block( $settings ) {
281 + $class = new Visualizer_Module_Language();
282 + $strings = $class->get_strings();
283 + $array = array( 'visualizer_tinymce_plugin' => json_encode( $strings ) );
284 + return array_merge( $settings, $array );
285 + }
286 +
287 + /**
144 288 * Load plugin translation for - TinyMCE API
145 289 *
146 290 * @access public
147 291 * @param array $arr The tinymce_lang array.
@@ -210,20 +354,52 @@
210 354 * @access public
211 355 */
212 356 public function enqueueMediaScripts() {
213 357 global $typenow;
214 - if ( post_type_supports( $typenow, 'editor' ) ) {
358 + global $current_screen;
359 +
360 + if ( post_type_supports( $typenow, 'editor' ) || $current_screen->id === 'widgets' || $current_screen->id === 'customize' ) {
215 361 wp_enqueue_style( 'visualizer-media', VISUALIZER_ABSURL . 'css/media.css', array( 'media-views' ), Visualizer_Plugin::VERSION );
216 - wp_enqueue_script( 'visualizer-google-jsapi-new', '//www.gstatic.com/charts/loader.js', array( 'media-editor' ), null, true );
217 - wp_enqueue_script( 'visualizer-google-jsapi-old', '//www.google.com/jsapi', array( 'visualizer-google-jsapi-new' ), null, true );
218 - wp_enqueue_script( 'visualizer-media-model', VISUALIZER_ABSURL . 'js/media/model.js', array( 'visualizer-google-jsapi-old' ), Visualizer_Plugin::VERSION, true );
362 +
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 + // Load all the assets for the different libraries we support.
387 + $deps = array(
388 + Visualizer_Render_Sidebar_Google::enqueue_assets( array( 'media-editor' ) ),
389 + Visualizer_Render_Sidebar_Type_DataTable_Tabular::enqueue_assets( array( 'media-editor' ) ),
390 + );
391 +
392 + wp_enqueue_script( 'visualizer-media-model', VISUALIZER_ABSURL . 'js/media/model.js', $deps, Visualizer_Plugin::VERSION, true );
219 393 wp_enqueue_script( 'visualizer-media-collection', VISUALIZER_ABSURL . 'js/media/collection.js', array( 'visualizer-media-model' ), Visualizer_Plugin::VERSION, true );
220 394 wp_enqueue_script( 'visualizer-media-controller', VISUALIZER_ABSURL . 'js/media/controller.js', array( 'visualizer-media-collection' ), Visualizer_Plugin::VERSION, true );
221 395 wp_enqueue_script( 'visualizer-media-view', VISUALIZER_ABSURL . 'js/media/view.js', array( 'visualizer-media-controller' ), Visualizer_Plugin::VERSION, true );
222 396 wp_localize_script(
223 - 'visualizer-media-view', 'visualizer', array(
397 + 'visualizer-media-view',
398 + 'visualizer',
399 + array(
224 400 'i10n' => array(
225 - 'insert' => __( 'Insert', 'visualizer' ),
401 + 'insert' => __( 'Insert Chart', 'visualizer' ),
226 402 ),
227 403 )
228 404 );
229 405 wp_enqueue_script( 'visualizer-media-toolbar', VISUALIZER_ABSURL . 'js/media/toolbar.js', array( 'visualizer-media-view' ), Visualizer_Plugin::VERSION, true );
@@ -252,9 +428,9 @@
252 428 'controller' => array(
253 429 'title' => esc_html__( 'Visualizations', 'visualizer' ),
254 430 ),
255 431 'routers' => array(
256 - 'library' => esc_html__( 'From Library', 'visualizer' ),
432 + 'library' => esc_html__( 'Insert from Library', 'visualizer' ),
257 433 'create' => esc_html__( 'Create New', 'visualizer' ),
258 434 ),
259 435 'library' => array(
260 436 'filters' => $chart_types,
@@ -259,10 +435,10 @@
259 435 'library' => array(
260 436 'filters' => $chart_types,
261 437 'types' => array_keys( $chart_types ),
262 438 ),
263 - 'nonce' => wp_create_nonce(),
264 - 'buildurl' => add_query_arg( 'action', Visualizer_Plugin::ACTION_CREATE_CHART, admin_url( 'admin-ajax.php' ) ),
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' ) ) ),
265 441 );
266 442
267 443 return $strings;
268 444 }
@@ -275,9 +451,9 @@
275 451 * @static
276 452 * @access private
277 453 * @return array The associated array of chart types with localized names.
278 454 */
279 - public static function _getChartTypesLocalized( $enabledOnly = false, $get2Darray = false, $add_select = false ) {
455 + public static function _getChartTypesLocalized( $enabledOnly = false, $get2Darray = false, $add_select = false, $where = null ) {
280 456 $additional = array();
281 457 if ( $add_select ) {
282 458 $additional['select'] = array(
283 459 'name' => esc_html__( 'All', 'visualizer' ),
@@ -284,59 +460,102 @@
284 460 'enabled' => true,
285 461 );
286 462 }
287 463
464 + $enabled = self::proFeaturesEnabled();
465 +
288 466 $types = array_merge(
289 - $additional, array(
467 + $additional,
468 + array(
469 + 'tabular' => array(
470 + 'name' => esc_html__( 'Table', 'visualizer' ),
471 + 'enabled' => true,
472 + 'supports' => $enabled ? array( 'Google Charts', 'DataTable' ) : array( 'DataTable' ),
473 + ),
290 474 'pie' => array(
291 - 'name' => esc_html__( 'Pie', 'visualizer' ),
475 + 'name' => esc_html__( 'Pie/Donut', 'visualizer' ),
292 476 'enabled' => true,
477 + 'supports' => array( 'Google Charts', 'ChartJS' ),
293 478 ),
294 479 'line' => array(
295 480 'name' => esc_html__( 'Line', 'visualizer' ),
296 481 'enabled' => true,
482 + 'supports' => array( 'Google Charts', 'ChartJS' ),
297 483 ),
484 + 'bar' => array(
485 + 'name' => esc_html__( 'Bar', 'visualizer' ),
486 + 'enabled' => true,
487 + 'supports' => $enabled ? array( 'Google Charts', 'ChartJS' ) : array( 'Google Charts' ),
488 + ),
298 489 'area' => array(
299 490 'name' => esc_html__( 'Area', 'visualizer' ),
300 - 'enabled' => true,
491 + 'enabled' => $enabled,
492 + // in ChartJS, the fill option is used to make Line chart an area: https://www.chartjs.org/docs/latest/charts/area.html
493 + 'supports' => array( 'Google Charts' ),
494 + 'demo_url' => 'https://demo.themeisle.com/visualizer/area-chart/',
301 495 ),
302 496 'geo' => array(
303 497 'name' => esc_html__( 'Geo', 'visualizer' ),
304 - 'enabled' => true,
498 + 'enabled' => $enabled,
499 + 'supports' => array( 'Google Charts' ),
500 + 'demo_url' => 'https://demo.themeisle.com/visualizer/geo-chart/',
305 501 ),
306 - 'bar' => array(
307 - 'name' => esc_html__( 'Bar', 'visualizer' ),
308 - 'enabled' => true,
309 - ),
310 502 'column' => array(
311 503 'name' => esc_html__( 'Column', 'visualizer' ),
312 - 'enabled' => true,
504 + 'enabled' => $enabled,
505 + 'supports' => array( 'Google Charts', 'ChartJS' ),
506 + 'demo_url' => 'https://demo.themeisle.com/visualizer/column-chart/',
313 507 ),
314 - 'gauge' => array(
315 - 'name' => esc_html__( 'Gauge', 'visualizer' ),
316 - 'enabled' => true,
508 + 'bubble' => array(
509 + 'name' => esc_html__( 'Bubble', 'visualizer' ),
510 + 'enabled' => $enabled,
511 + // 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 + 'supports' => array( 'Google Charts' ),
513 + 'demo_url' => 'https://demo.themeisle.com/visualizer/bubble-chart/',
317 514 ),
318 515 'scatter' => array(
319 516 'name' => esc_html__( 'Scatter', 'visualizer' ),
320 - 'enabled' => true,
517 + 'enabled' => $enabled,
518 + 'supports' => array( 'Google Charts' ),
519 + 'demo_url' => 'https://demo.themeisle.com/visualizer/scatter-chart/',
321 520 ),
521 + 'gauge' => array(
522 + 'name' => esc_html__( 'Gauge', 'visualizer' ),
523 + 'enabled' => $enabled,
524 + 'supports' => array( 'Google Charts' ),
525 + 'demo_url' => 'https://demo.themeisle.com/visualizer/gauge-chart/',
526 + ),
322 527 'candlestick' => array(
323 528 'name' => esc_html__( 'Candlestick', 'visualizer' ),
324 - 'enabled' => true,
529 + 'enabled' => $enabled,
530 + 'supports' => array( 'Google Charts' ),
531 + 'demo_url' => 'https://demo.themeisle.com/visualizer/candlestick-chart/',
325 532 ),
326 533 // pro types
327 - 'table' => array(
328 - 'name' => esc_html__( 'Table', 'visualizer' ),
329 - 'enabled' => false,
330 - ),
331 534 'timeline' => array(
332 535 'name' => esc_html__( 'Timeline', 'visualizer' ),
333 536 'enabled' => false,
537 + 'supports' => array( 'Google Charts', 'ChartJS' ),
538 + 'demo_url' => 'https://demo.themeisle.com/visualizer/timeline-chart/',
334 539 ),
335 540 'combo' => array(
336 541 'name' => esc_html__( 'Combo', 'visualizer' ),
337 542 'enabled' => false,
543 + 'supports' => array( 'Google Charts' ),
544 + 'demo_url' => 'https://demo.themeisle.com/visualizer/combo-chart/',
338 545 ),
546 + 'polarArea' => array(
547 + 'name' => esc_html__( 'Polar Area', 'visualizer' ),
548 + 'enabled' => false,
549 + 'supports' => array( 'ChartJS' ),
550 + 'demo_url' => 'https://demo.themeisle.com/visualizer/polar-area-chart/',
551 + ),
552 + 'radar' => array(
553 + 'name' => esc_html__( 'Radar/Spider', 'visualizer' ),
554 + 'enabled' => false,
555 + 'supports' => array( 'ChartJS' ),
556 + 'demo_url' => 'https://demo.themeisle.com/visualizer/radar-spider-chart/',
557 + ),
339 558 )
340 559 );
341 560 $types = apply_filters( 'visualizer_pro_chart_types', $types );
342 561 if ( $enabledOnly ) {
@@ -345,8 +564,12 @@
345 564 if ( ! is_array( $array ) ) {
346 565 // support for old pro
347 566 $array = array( 'enabled' => true, 'name' => $array );
348 567 }
568 + // backward compatibility for PRO before v1.9.0
569 + if ( ! array_key_exists( 'supports', $array ) ) {
570 + $array['supports'] = array( 'Google Charts' );
571 + }
349 572 if ( ! $array['enabled'] ) {
350 573 continue;
351 574 }
352 575 $filtered[ $type ] = $array;
@@ -359,13 +582,74 @@
359 582 if ( ! is_array( $array ) ) {
360 583 // support for old pro
361 584 $array = array( 'enabled' => true, 'name' => $array );
362 585 }
586 + // backward compatibility for PRO before v1.9.0
587 + if ( ! array_key_exists( 'supports', $array ) ) {
588 + $array['supports'] = array( 'Google Charts' );
589 + }
363 590 $doubleD[ $type ] = $array['name'];
364 591 }
365 592 $types = $doubleD;
366 593 }
367 594
595 + return self::handleDeprecatedCharts( $types, $enabledOnly, $get2Darray, $where );
596 + }
597 +
598 + /**
599 + * Handle (soon-to-be) deprecated charts.
600 + */
601 + private static function handleDeprecatedCharts( $types, $enabledOnly, $get2Darray, $where ) {
602 + $deprecated = array();
603 +
604 + switch ( $where ) {
605 + case 'types':
606 + // fall-through
607 + case 'library':
608 + // if a user has a Gauge/Candlestick chart, then let them keep using it.
609 + if ( ! Visualizer_Module::is_pro() ) {
610 + if ( ! self::hasChartType( 'gauge' ) ) {
611 + if ( $get2Darray ) {
612 + $deprecated[] = 'gauge';
613 + } else {
614 + $types['gauge']['enabled'] = false;
615 + }
616 + }
617 + if ( ! self::hasChartType( 'candlestick' ) ) {
618 + if ( $get2Darray ) {
619 + $deprecated[] = 'candlestick';
620 + } else {
621 + $types['candlestick']['enabled'] = false;
622 + }
623 + }
624 + }
625 + break;
626 + default:
627 + // if a user has a Gauge/Candlestick chart, then let them keep using it.
628 + if ( ! Visualizer_Module::is_pro() ) {
629 + if ( ! self::hasChartType( 'gauge' ) ) {
630 + if ( $get2Darray ) {
631 + $deprecated[] = 'gauge';
632 + } else {
633 + $types['gauge']['enabled'] = false;
634 + }
635 + }
636 + if ( ! self::hasChartType( 'candlestick' ) ) {
637 + if ( $get2Darray ) {
638 + $deprecated[] = 'candlestick';
639 + } else {
640 + $types['candlestick']['enabled'] = false;
641 + }
642 + }
643 + }
644 + }
645 +
646 + if ( $deprecated ) {
647 + foreach ( $deprecated as $type ) {
648 + unset( $types[ $type ] );
649 + }
650 + }
651 +
368 652 return $types;
369 653 }
370 654
371 655 /**
@@ -375,11 +659,11 @@
375 659 * @global string $pagenow The name of the current page.
376 660 *
377 661 * @access public
378 662 */
379 - public function renderTempaltes() {
663 + public function renderTemplates() {
380 664 global $pagenow;
381 - if ( 'post.php' != $pagenow && 'post-new.php' != $pagenow ) {
665 + if ( 'post.php' !== $pagenow && 'post-new.php' !== $pagenow ) {
382 666 return;
383 667 }
384 668 $render = new Visualizer_Render_Templates();
385 669 $render->render();
@@ -397,30 +681,159 @@
397 681 *
398 682 * @param string $suffix The current page suffix.
399 683 */
400 684 public function enqueueLibraryScripts( $suffix ) {
401 - if ( $suffix == $this->_libraryPage ) {
402 - wp_enqueue_style( 'visualizer-library', VISUALIZER_ABSURL . 'css/library.css', array(), Visualizer_Plugin::VERSION );
403 - $this->_addFilter( 'media_upload_tabs', 'setupVisualizerTab' );
404 - wp_enqueue_media();
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 + }
405 714 wp_enqueue_script(
406 - 'visualizer-library', VISUALIZER_ABSURL . 'js/library.js', array(
407 - 'jquery',
408 - 'media-views',
409 - ), Visualizer_Plugin::VERSION, true
715 + "visualizer-render-$library",
716 + VISUALIZER_ABSURL . 'js/render-facade.js',
717 + apply_filters( 'visualizer_assets_render', array( 'visualizer-library', 'visualizer-customization' ), true ),
718 + Visualizer_Plugin::VERSION,
719 + true
410 720 );
411 - wp_enqueue_script( 'google-jsapi-new', '//www.gstatic.com/charts/loader.js', array(), null, true );
412 - wp_enqueue_script( 'google-jsapi-old', '//www.google.com/jsapi', array( 'google-jsapi-new' ), null, true );
721 + if ( 'd3' === $library ) {
722 + $has_d3 = true;
723 + }
724 + }
725 +
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 + }
752 +
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,
768 + true
769 + );
770 + }
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 + }
413 786 wp_enqueue_script(
414 - 'visualizer-render', VISUALIZER_ABSURL . 'js/render.js', array(
415 - 'google-jsapi-old',
416 - 'visualizer-library',
417 - ), Visualizer_Plugin::VERSION, true
787 + 'visualizer-chart-builder',
788 + VISUALIZER_ABSURL . 'classes/Visualizer/ChartBuilder/build/index.js',
789 + $chart_builder_deps,
790 + $asset['version'],
791 + true
418 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 + );
419 818 }
819 +
820 + do_action( 'themeisle_internal_page', VISUALIZER_DIRNAME, 'library' );
420 821 }
421 822
422 823 /**
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 + /**
423 836 * Adds visualizer tab for media upload tabs array.
424 837 *
425 838 * @since 1.0.0
426 839 *
@@ -443,24 +856,201 @@
443 856 *
444 857 * @access public
445 858 */
446 859 public function registerAdminMenu() {
447 - $title = esc_html__( 'Visualizer Library', 'visualizer' );
448 - $callback = array( $this, 'renderLibraryPage' );
449 - $this->_libraryPage = add_submenu_page( 'upload.php', $title, $title, 'edit_posts', Visualizer_Plugin::NAME, $callback );
860 + $svg_base64_icon = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iNzdweCIgaGVpZ2h0PSI3N3B4IiB2aWV3Qm94PSIwIDAgNzcgNzciIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICA8IS0tIEdlbmVyYXRvcjogU2tldGNoIDUyLjYgKDY3NDkxKSAtIGh0dHA6Ly93d3cuYm9oZW1pYW5jb2RpbmcuY29tL3NrZXRjaCAtLT4KICAgIDx0aXRsZT5Db21iaW5lZCBTaGFwZTwvdGl0bGU+CiAgICA8ZGVzYz5DcmVhdGVkIHdpdGggU2tldGNoLjwvZGVzYz4KICAgIDxnIGlkPSJQcm9kdWN0LVBhZ2UiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPgogICAgICAgIDxnIGlkPSJXb3JkUHJlc3MtcGx1Z2lucyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTE5MC4wMDAwMDAsIC00MzUuMDAwMDAwKSIgZmlsbD0iIzM5QzNEMiI+CiAgICAgICAgICAgIDxwYXRoIGQ9Ik0yMjguNSw1MTIgQzIwNy4yMzcwMzcsNTEyIDE5MCw0OTQuNzYyOTYzIDE5MCw0NzMuNSBDMTkwLDQ1Mi4yMzcwMzcgMjA3LjIzNzAzNyw0MzUgMjI4LjUsNDM1IEMyNDkuNzYyOTYzLDQzNSAyNjcsNDUyLjIzNzAzNyAyNjcsNDczLjUgQzI2Nyw0OTQuNzYyOTYzIDI0OS43NjI5NjMsNTEyIDIyOC41LDUxMiBaIE0yNDYuODQzNzUsNDgzLjU5MjA1OSBMMjE1LjYyNSw0ODMuNTkyMDU5IEwyMTUuNjI1LDQ2MC44MjY1NDQgQzIxNS42MjUsNDYwLjE2NDU0NyAyMTUuMTA3NTc4LDQ1OS42MjgzNTkgMjE0LjQ2ODc1LDQ1OS42MjgzNTkgTDIxMi4xNTYyNSw0NTkuNjI4MzU5IEMyMTEuNTE3NDIyLDQ1OS42MjgzNTkgMjExLDQ2MC4xNjQ1NDcgMjExLDQ2MC44MjY1NDQgTDIxMSw0ODUuOTg4NDI5IEMyMTEsNDg3LjMxMTY3NCAyMTIuMDM1NTY2LDQ4OC4zODQ3OTggMjEzLjMxMjUsNDg4LjM4NDc5OCBMMjQ2Ljg0Mzc1LDQ4OC4zODQ3OTggQzI0Ny40ODI1NzgsNDg4LjM4NDc5OCAyNDgsNDg3Ljg0ODYxMSAyNDgsNDg3LjE4NjYxMyBMMjQ4LDQ4NC43OTAyNDQgQzI0OCw0ODQuMTI4MjQ2IDI0Ny40ODI1NzgsNDgzLjU5MjA1OSAyNDYuODQzNzUsNDgzLjU5MjA1OSBaIE0yNDQuNTMxMjUsNDYyLjAyNDcyOSBMMjM1Ljk5OTU3LDQ2Mi4wMjQ3MjkgQzIzNC40NTQ1MzEsNDYyLjAyNDcyOSAyMzMuNjgwNTY2LDQ2My45NjA1NDcgMjM0Ljc3MzIyMyw0NjUuMDkyODMyIEwyMzcuMTE0NjI5LDQ2Ny41MTkxNTYgTDIzMS44MTI1LDQ3My4wMTQzMzIgTDIyNi41MTAzNzEsNDY3LjUxOTkwNSBDMjI1LjYwNzA1MSw0NjYuNTgzODIzIDIyNC4xNDI5NDksNDY2LjU4MzgyMyAyMjMuMjQwMzUyLDQ2Ny41MTk5MDUgTDIxOC4yNzY0MjYsNDcyLjY2Mzg2MyBDMjE3LjgyNDc2Niw0NzMuMTMxOTA0IDIxNy44MjQ3NjYsNDczLjg5MDUwNSAyMTguMjc2NDI2LDQ3NC4zNTg1NDYgTDIxOS45MTEwNzQsNDc2LjA1MjQ4IEMyMjAuMzYyNzM0LDQ3Ni41MjA1MjEgMjIxLjA5NDc4NSw0NzYuNTIwNTIxIDIyMS41NDY0NDUsNDc2LjA1MjQ4IEwyMjQuODc1LDQ3Mi42MDI0NTYgTDIzMC4xNzcxMjksNDc4LjA5Njg4MyBDMjMxLjA4MDQ0OSw0NzkuMDMyOTY1IDIzMi41NDQ1NTEsNDc5LjAzMjk2NSAyMzMuNDQ3MTQ4LDQ3OC4wOTY4ODMgTDI0MC4zODQ2NDgsNDcwLjkwNzc3MyBMMjQyLjcyNjA1NSw0NzMuMzM0MDk4IEMyNDMuODE4NzExLDQ3NC40NjYzODIgMjQ1LjY4Njc3Nyw0NzMuNjY0MzQ3IDI0NS42ODY3NzcsNDcyLjA2MzI3MyBMMjQ1LjY4Njc3Nyw0NjMuMjIyOTE0IEMyNDUuNjg3NSw0NjIuNTYwOTE3IDI0NS4xNzAwNzgsNDYyLjAyNDcyOSAyNDQuNTMxMjUsNDYyLjAyNDcyOSBaIiBpZD0iQ29tYmluZWQtU2hhcGUiPjwvcGF0aD4KICAgICAgICA8L2c+CiAgICA8L2c+Cjwvc3ZnPg==';
861 +
862 + $this->_libraryPage = add_menu_page( __( 'Visualizer', 'visualizer' ), __( 'Visualizer', 'visualizer' ), 'edit_posts', Visualizer_Plugin::NAME, array( $this, 'renderLibraryPage' ), $svg_base64_icon, 99.7666 );
863 +
864 + add_submenu_page(
865 + Visualizer_Plugin::NAME,
866 + __( 'Chart Library', 'visualizer' ),
867 + __( 'Chart Library', 'visualizer' ),
868 + 'edit_posts',
869 + 'admin.php?page=' . Visualizer_Plugin::NAME
870 + );
871 + add_submenu_page(
872 + Visualizer_Plugin::NAME,
873 + __( 'Add New Chart', 'visualizer' ),
874 + __( 'Add New Chart', 'visualizer' ),
875 + 'edit_posts',
876 + 'admin.php?page=' . Visualizer_Plugin::NAME . '&vaction=addnew'
877 + );
878 +
879 + $this->_settingsPage = add_submenu_page(
880 + 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 + __( 'Support', 'visualizer' ),
891 + __( '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 + 'edit_posts',
893 + 'viz-support',
894 + array( $this, 'renderSupportPage' )
895 + );
896 +
897 + 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' ) );
450 901 }
451 902
452 903 /**
453 - * Renders visualizer library page.
454 - *
455 - * @since 1.0.0
456 - *
457 - * @access public
904 + * Handle get pro plugin submenu.
458 905 */
459 - public function renderLibraryPage() {
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 + * Get the instance of WP_Query that fetches the charts as per the given criteria.
1040 + */
1041 + private function getQuery() {
1042 + static $q;
1043 + if ( ! is_null( $q ) ) {
1044 + return $q;
1045 + }
1046 +
460 1047 // get current page
461 1048 $page = filter_input(
462 - INPUT_GET, 'vpage', FILTER_VALIDATE_INT, array(
1049 + INPUT_GET,
1050 + 'vpage',
1051 + FILTER_VALIDATE_INT,
1052 + array(
463 1053 'options' => array(
464 1054 'min_range' => 1,
465 1055 'default' => 1,
466 1056 ),
@@ -465,29 +1055,34 @@
465 1055 'default' => 1,
466 1056 ),
467 1057 )
468 1058 );
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 +
469 1074 // the initial query arguments to fetch charts
470 1075 $query_args = array(
471 1076 'post_type' => Visualizer_Plugin::CPT_VISUALIZER,
472 - 'posts_per_page' => 6,
1077 + 'posts_per_page' => $per_page,
473 1078 'paged' => $page,
474 1079 );
475 - // add chart type filter to the query arguments
476 - $filter = filter_input( INPUT_GET, 'type' );
477 - if ( $filter && in_array( $filter, Visualizer_Plugin::getChartTypes() ) ) {
478 - $query_args['meta_query'] = array(
479 - array(
480 - 'key' => Visualizer_Plugin::CF_CHART_TYPE,
481 - 'value' => $filter,
482 - 'compare' => '=',
483 - ),
484 - );
485 - } else {
486 - $filter = 'all';
487 - }
1080 +
1081 + $this->getDisplayFilters( $query_args );
1082 +
488 1083 // Added by Ash/Upwork
489 - $filterByMeta = filter_input( INPUT_GET, 's', FILTER_SANITIZE_STRING );
1084 + $filterByMeta = ! empty( $_GET['s'] ) ? sanitize_text_field( wp_unslash( $_GET['s'] ) ) : null; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
490 1085 if ( $filterByMeta ) {
491 1086 $query = array(
492 1087 'key' => Visualizer_Plugin::CF_SETTINGS,
493 1088 'value' => $filterByMeta,
@@ -496,56 +1091,246 @@
496 1091 $meta = isset( $query_args['meta_query'] ) ? $query_args['meta_query'] : array();
497 1092 $meta[] = $query;
498 1093 $query_args['meta_query'] = $meta;
499 1094 }
500 - // Added by Ash/Upwork
501 - // fetch charts
1095 + $q = new WP_Query( apply_filters( 'visualizer_query_args', $query_args ) );
1096 + return $q;
1097 + }
1098 +
1099 + /**
1100 + * Renders support page.
1101 + *
1102 + * @since 3.3.0
1103 + *
1104 + * @access public
1105 + */
1106 + public function renderSupportPage() {
1107 + wp_enqueue_style( 'visualizer-upsell', VISUALIZER_ABSURL . 'css/upsell.css', array(), Visualizer_Plugin::VERSION );
1108 + include_once VISUALIZER_ABSPATH . '/templates/support.php';
1109 + }
1110 +
1111 + /**
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 + * Renders visualizer library page.
1196 + *
1197 + * @since 1.0.0
1198 + *
1199 + * @access public
1200 + */
1201 + public function renderLibraryPage() {
502 1202 $charts = array();
503 - $query = new WP_Query( $query_args );
1203 + $query = $this->getQuery();
1204 +
1205 + // get current page
1206 + $page = filter_input(
1207 + INPUT_GET,
1208 + 'vpage',
1209 + FILTER_VALIDATE_INT,
1210 + array(
1211 + 'options' => array(
1212 + 'min_range' => 1,
1213 + 'default' => 1,
1214 + ),
1215 + )
1216 + );
1217 + // add chart type filter to the query arguments
1218 + $filter = filter_input( INPUT_GET, 'type' );
1219 + if ( ! ( $filter && in_array( $filter, Visualizer_Plugin::getChartTypes(), true ) ) ) {
1220 + $filter = 'all';
1221 + }
1222 +
1223 + $css = '';
504 1224 while ( $query->have_posts() ) {
505 1225 $chart = $query->next_post();
506 1226
507 1227 // 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.
508 1228 $chart = $this->handleExistingRevisions( $chart->ID, $chart );
1229 + // refresh a "live" db query chart.
1230 + $chart = apply_filters( 'visualizer_schedule_refresh_chart', $chart, $chart->ID, false );
509 1231
1232 + $type = get_post_meta( $chart->ID, Visualizer_Plugin::CF_CHART_TYPE, true );
1233 +
510 1234 // fetch and update settings
511 1235 $settings = get_post_meta( $chart->ID, Visualizer_Plugin::CF_SETTINGS, true );
512 - unset( $settings['height'], $settings['width'] );
513 - $type = get_post_meta( $chart->ID, Visualizer_Plugin::CF_CHART_TYPE, true );
1236 +
1237 + $settings = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_SETTINGS, $settings, $chart->ID, $type );
1238 + if ( ! empty( $atts['settings'] ) ) {
1239 + $settings = apply_filters( $atts['settings'], $settings, $chart->ID, $type );
1240 + }
1241 +
1242 + if ( $settings ) {
1243 + unset( $settings['height'], $settings['width'], $settings['chartArea'] );
1244 + }
1245 +
514 1246 $series = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_SERIES, get_post_meta( $chart->ID, Visualizer_Plugin::CF_SERIES, true ), $chart->ID, $type );
515 - $data = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_DATA, unserialize( html_entity_decode( $chart->post_content ) ), $chart->ID, $type );
1247 + $data = self::get_chart_data( $chart, $type );
1248 +
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 + $library = $this->load_chart_type( $chart->ID );
1262 +
1263 + $id = 'visualizer-' . $chart->ID;
1264 + $arguments = $this->get_inline_custom_css( $id, $settings );
1265 + if ( ! empty( $arguments ) ) {
1266 + $css .= $arguments[0];
1267 + $settings = $arguments[1];
1268 + }
1269 +
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 +
516 1277 // add chart to the array
517 - $charts[ 'visualizer-' . $chart->ID ] = array(
1278 + $charts[ $id ] = array(
518 1279 'id' => $chart->ID,
1280 + 'title' => $chart->post_title,
519 1281 'type' => $type,
520 1282 'series' => $series,
521 1283 'settings' => $settings,
522 1284 'data' => $data,
1285 + 'library' => $library,
523 1286 );
1287 + if ( 'd3' === $library ) {
1288 + $charts[ $id ]['code'] = get_post_meta( $chart->ID, Visualizer_Module_AIBuilder::CF_D3_CODE, true );
1289 + }
524 1290 }
525 1291 // enqueue charts array
526 1292 $ajaxurl = admin_url( 'admin-ajax.php' );
1293 +
527 1294 wp_localize_script(
528 - 'visualizer-library', 'visualizer', array(
1295 + 'visualizer-library',
1296 + 'visualizer',
1297 + array(
529 1298 'language' => $this->get_language(),
530 1299 'map_api_key' => get_option( 'visualizer-map-api-key' ),
531 1300 'charts' => $charts,
532 1301 'urls' => array(
533 - 'base' => add_query_arg( 'vpage', false ),
534 - 'create' => add_query_arg(
535 - array(
536 - 'action' => Visualizer_Plugin::ACTION_CREATE_CHART,
537 - 'library' => 'yes',
538 - 'type' => isset( $_GET['type'] ) ? $_GET['type'] : '',
539 - ), $ajaxurl
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 + )
540 1314 ),
541 - 'edit' => add_query_arg(
542 - array(
543 - 'action' => Visualizer_Plugin::ACTION_EDIT_CHART,
544 - 'library' => 'yes',
545 - ), $ajaxurl
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 + )
546 1324 ),
547 1325 ),
1326 + 'page_type' => 'library',
1327 + '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(),
548 1333 )
549 1334 );
550 1335 // render library page
551 1336 $render = new Visualizer_Render_Library();
@@ -550,12 +1335,13 @@
550 1335 // render library page
551 1336 $render = new Visualizer_Render_Library();
552 1337 $render->charts = $charts;
553 1338 $render->type = $filter;
554 - $render->types = self::_getChartTypesLocalized();
1339 + $render->types = self::_getChartTypesLocalized( false, false, false, true );
1340 + $render->custom_css = $css;
555 1341 $render->pagination = paginate_links(
556 1342 array(
557 - 'base' => add_query_arg( 'vpage', '%#%' ),
1343 + 'base' => add_query_arg( array( 'vpage' => '%#%', 'vaction' => false ) ),
558 1344 'format' => '',
559 1345 'current' => $page,
560 1346 'total' => $query->max_num_pages,
561 1347 'type' => 'array',
@@ -560,8 +1346,9 @@
560 1346 'total' => $query->max_num_pages,
561 1347 'type' => 'array',
562 1348 )
563 1349 );
1350 +
564 1351 $render->render();
565 1352 }
566 1353
567 1354 /**
@@ -576,14 +1363,14 @@
576 1363 *
577 1364 * @return array Updated array of action links.
578 1365 */
579 1366 public function getPluginActionLinks( $links, $file ) {
580 - if ( $file == plugin_basename( VISUALIZER_BASEFILE ) ) {
1367 + if ( $file === plugin_basename( VISUALIZER_BASEFILE ) ) {
581 1368 array_unshift(
582 1369 $links,
583 1370 sprintf(
584 1371 '<a href="%s">%s</a>',
585 - admin_url( 'upload.php?page=' . Visualizer_Plugin::NAME ),
1372 + admin_url( 'admin.php?page=' . Visualizer_Plugin::NAME ),
586 1373 esc_html__( 'Library', 'visualizer' )
587 1374 )
588 1375 );
589 1376 }
@@ -603,21 +1390,268 @@
603 1390 *
604 1391 * @return array Updated array of plugin meta links.
605 1392 */
606 1393 public function getPluginMetaLinks( $plugin_meta, $plugin_file ) {
607 - if ( $plugin_file == plugin_basename( VISUALIZER_BASEFILE ) ) {
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 + if ( $plugin_file === plugin_basename( VISUALIZER_BASEFILE ) ) {
1409 + $is_black_friday = apply_filters( 'themeisle_sdk_is_black_friday_sale', false );
608 1410 // knowledge base link
609 1411 $plugin_meta[] = sprintf(
610 - '<a href="https://github.com/codeinwp/visualizer/wiki" target="_blank">%s</a>',
611 - esc_html__( 'Knowledge Base', 'visualizer' )
1412 + '<a href="' . VISUALIZER_MAIN_DOC . '" target="_blank">%s</a>',
1413 + esc_html__( 'Docs', 'visualizer' )
612 1414 );
613 - // flattr link
614 - $plugin_meta[] = sprintf(
615 - '<a style="color:red" href="https://themeisle.com/plugins/visualizer-charts-and-graphs-pro-addon/" target="_blank">%s</a>',
616 - esc_html__( 'Pro Addon', 'visualizer' )
617 - );
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 + }
618 1422 }
619 1423
620 1424 return $plugin_meta;
621 1425 }
622 1426
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 + }
623 1657 }