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