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