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 +585 -88 3.1.23.11.0 View file →
@@ -53,25 +53,129 @@
53 53 parent::__construct( $plugin );
54 54 $this->_addAction( 'load-post.php', 'enqueueMediaScripts' );
55 55 $this->_addAction( 'load-post-new.php', 'enqueueMediaScripts' );
56 56 $this->_addAction( 'admin_footer', 'renderTemplates' );
57 - $this->_addAction( 'admin_enqueue_scripts', 'enqueueLibraryScripts', null, 8 );
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 +
65 68 // revision support.
66 69 $this->_addFilter( 'wp_revisions_to_keep', 'limitRevisions', null, 10, 2 );
67 70 $this->_addAction( '_wp_put_post_revision', 'addRevision', null, 10, 1 );
68 71 $this->_addAction( 'wp_restore_post_revision', 'restoreRevision', null, 10, 2 );
69 72
73 + $this->_addAction( 'visualizer_chart_schedules_spl', 'addSplChartSchedules', null, 10, 3 );
74 +
70 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 +
71 85 }
86 + /**
87 + * Display review notice.
88 + */
89 + public function render_review_notice( $footer_text ) {
90 + $current_screen = get_current_screen();
72 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 +
73 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 + /**
74 178 * No limits on revisions.
75 179 */
76 180 public function limitRevisions( $num, $post ) {
77 181 if ( Visualizer_Plugin::CPT_VISUALIZER === $post->post_type ) {
@@ -132,16 +236,31 @@
132 236 *
133 237 * @access public
134 238 */
135 239 public function init() {
240 + // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
136 241 if ( current_user_can( 'edit_posts' ) && current_user_can( 'edit_pages' ) && 'true' == get_user_option( 'rich_editing' ) ) {
137 242 $this->_addFilter( 'mce_external_languages', 'add_tinymce_lang', 10, 1 );
138 243 $this->_addFilter( 'mce_external_plugins', 'tinymce_plugin', 10, 1 );
139 244 $this->_addFilter( 'mce_buttons', 'register_mce_button', 10, 1 );
245 + $this->_addFilter( 'tiny_mce_before_init', 'get_strings_for_block', 10, 1 );
140 246 }
141 247 }
142 248
143 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 + /**
144 263 * Load plugin translation for - TinyMCE API
145 264 *
146 265 * @access public
147 266 * @param array $arr The tinymce_lang array.
@@ -216,9 +335,9 @@
216 335
217 336 // Load all the assets for the different libraries we support.
218 337 $deps = array(
219 338 Visualizer_Render_Sidebar_Google::enqueue_assets( array( 'media-editor' ) ),
220 - Visualizer_Render_Sidebar_Type_DataTable::enqueue_assets( array( 'media-editor' ) ),
339 + Visualizer_Render_Sidebar_Type_DataTable_Tabular::enqueue_assets( array( 'media-editor' ) ),
221 340 );
222 341
223 342 wp_enqueue_script( 'visualizer-media-model', VISUALIZER_ABSURL . 'js/media/model.js', $deps, Visualizer_Plugin::VERSION, true );
224 343 wp_enqueue_script( 'visualizer-media-collection', VISUALIZER_ABSURL . 'js/media/collection.js', array( 'visualizer-media-model' ), Visualizer_Plugin::VERSION, true );
@@ -267,9 +386,9 @@
267 386 'filters' => $chart_types,
268 387 'types' => array_keys( $chart_types ),
269 388 ),
270 389 'nonce' => wp_create_nonce(),
271 - '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' ) ) ),
272 391 );
273 392
274 393 return $strings;
275 394 }
@@ -291,64 +410,91 @@
291 410 'enabled' => true,
292 411 );
293 412 }
294 413
414 + $enabled = self::proFeaturesLocked();
415 +
295 416 $types = array_merge(
296 417 $additional,
297 418 array(
298 - 'dataTable' => array(
299 - 'name' => esc_html__( 'Table (New)', 'visualizer' ),
419 + 'tabular' => array(
420 + 'name' => esc_html__( 'Table', 'visualizer' ),
300 421 'enabled' => true,
422 + 'supports' => $enabled ? array( 'Google Charts', 'DataTable' ) : array( 'DataTable' ),
301 423 ),
302 424 'pie' => array(
303 - 'name' => esc_html__( 'Pie', 'visualizer' ),
425 + 'name' => esc_html__( 'Pie/Donut', 'visualizer' ),
304 426 'enabled' => true,
427 + 'supports' => array( 'Google Charts', 'ChartJS' ),
305 428 ),
306 429 'line' => array(
307 430 'name' => esc_html__( 'Line', 'visualizer' ),
308 431 'enabled' => true,
432 + 'supports' => array( 'Google Charts', 'ChartJS' ),
309 433 ),
434 + 'bar' => array(
435 + 'name' => esc_html__( 'Bar', 'visualizer' ),
436 + 'enabled' => true,
437 + 'supports' => $enabled ? array( 'Google Charts', 'ChartJS' ) : array( 'Google Charts' ),
438 + ),
310 439 'area' => array(
311 440 'name' => esc_html__( 'Area', 'visualizer' ),
312 - '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' ),
313 444 ),
314 445 'geo' => array(
315 446 'name' => esc_html__( 'Geo', 'visualizer' ),
316 - 'enabled' => true,
447 + 'enabled' => $enabled,
448 + 'supports' => array( 'Google Charts' ),
317 449 ),
318 - 'bar' => array(
319 - 'name' => esc_html__( 'Bar', 'visualizer' ),
320 - 'enabled' => true,
321 - ),
322 450 'column' => array(
323 451 'name' => esc_html__( 'Column', 'visualizer' ),
324 - 'enabled' => true,
452 + 'enabled' => $enabled,
453 + 'supports' => array( 'Google Charts', 'ChartJS' ),
325 454 ),
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' ),
460 + ),
326 461 'scatter' => array(
327 462 'name' => esc_html__( 'Scatter', 'visualizer' ),
328 - 'enabled' => true,
463 + 'enabled' => $enabled,
464 + 'supports' => array( 'Google Charts' ),
329 465 ),
330 466 'gauge' => array(
331 467 'name' => esc_html__( 'Gauge', 'visualizer' ),
332 - 'enabled' => true,
468 + 'enabled' => $enabled,
469 + 'supports' => array( 'Google Charts' ),
333 470 ),
334 471 'candlestick' => array(
335 472 'name' => esc_html__( 'Candlestick', 'visualizer' ),
336 - 'enabled' => true,
473 + 'enabled' => $enabled,
474 + 'supports' => array( 'Google Charts' ),
337 475 ),
338 476 // pro types
339 - 'table' => array(
340 - 'name' => esc_html__( 'Table (Deprecated)', 'visualizer' ),
341 - 'enabled' => false,
342 - ),
343 477 'timeline' => array(
344 478 'name' => esc_html__( 'Timeline', 'visualizer' ),
345 479 'enabled' => false,
480 + 'supports' => array( 'Google Charts', 'ChartJS' ),
346 481 ),
347 482 'combo' => array(
348 483 'name' => esc_html__( 'Combo', 'visualizer' ),
349 484 'enabled' => false,
485 + 'supports' => array( 'Google Charts' ),
350 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 + ),
351 497 )
352 498 );
353 499 $types = apply_filters( 'visualizer_pro_chart_types', $types );
354 500 if ( $enabledOnly ) {
@@ -357,8 +503,12 @@
357 503 if ( ! is_array( $array ) ) {
358 504 // support for old pro
359 505 $array = array( 'enabled' => true, 'name' => $array );
360 506 }
507 + // backward compatibility for PRO before v1.9.0
508 + if ( ! array_key_exists( 'supports', $array ) ) {
509 + $array['supports'] = array( 'Google Charts' );
510 + }
361 511 if ( ! $array['enabled'] ) {
362 512 continue;
363 513 }
364 514 $filtered[ $type ] = $array;
@@ -371,8 +521,12 @@
371 521 if ( ! is_array( $array ) ) {
372 522 // support for old pro
373 523 $array = array( 'enabled' => true, 'name' => $array );
374 524 }
525 + // backward compatibility for PRO before v1.9.0
526 + if ( ! array_key_exists( 'supports', $array ) ) {
527 + $array['supports'] = array( 'Google Charts' );
528 + }
375 529 $doubleD[ $type ] = $array['name'];
376 530 }
377 531 $types = $doubleD;
378 532 }
@@ -386,21 +540,13 @@
386 540 private static function handleDeprecatedCharts( $types, $enabledOnly, $get2Darray, $where ) {
387 541 $deprecated = array();
388 542
389 543 switch ( $where ) {
544 + case 'types':
545 + // fall-through
390 546 case 'library':
391 - // if the user has a Google Table chart, show it as deprecated otherwise remove the option from the library.
392 - if ( ! self::hasChartType( 'table' ) ) {
393 - $deprecated[] = 'table';
394 - if ( $get2Darray ) {
395 - $types['dataTable'] = esc_html__( 'Table', 'visualizer' );
396 - } else {
397 - $types['dataTable']['name'] = esc_html__( 'Table', 'visualizer' );
398 - }
399 - }
400 -
401 547 // if a user has a Gauge/Candlestick chart, then let them keep using it.
402 - if ( ! VISUALIZER_PRO ) {
548 + if ( ! Visualizer_Module::is_pro() ) {
403 549 if ( ! self::hasChartType( 'gauge' ) ) {
404 550 if ( $get2Darray ) {
405 551 $deprecated[] = 'gauge';
406 552 } else {
@@ -416,20 +562,10 @@
416 562 }
417 563 }
418 564 break;
419 565 default:
420 - // remove the option to create a Google Table chart.
421 - $deprecated[] = 'table';
422 -
423 - // rename the new table chart type.
424 - if ( $get2Darray ) {
425 - $types['dataTable'] = esc_html__( 'Table', 'visualizer' );
426 - } else {
427 - $types['dataTable']['name'] = esc_html__( 'Table', 'visualizer' );
428 - }
429 -
430 566 // if a user has a Gauge/Candlestick chart, then let them keep using it.
431 - if ( ! VISUALIZER_PRO ) {
567 + if ( ! Visualizer_Module::is_pro() ) {
432 568 if ( ! self::hasChartType( 'gauge' ) ) {
433 569 if ( $get2Darray ) {
434 570 $deprecated[] = 'gauge';
435 571 } else {
@@ -464,9 +600,9 @@
464 600 * @access public
465 601 */
466 602 public function renderTemplates() {
467 603 global $pagenow;
468 - if ( 'post.php' != $pagenow && 'post-new.php' != $pagenow ) {
604 + if ( 'post.php' !== $pagenow && 'post-new.php' !== $pagenow ) {
469 605 return;
470 606 }
471 607 $render = new Visualizer_Render_Templates();
472 608 $render->render();
@@ -484,9 +620,9 @@
484 620 *
485 621 * @param string $suffix The current page suffix.
486 622 */
487 623 public function enqueueLibraryScripts( $suffix ) {
488 - if ( $suffix == $this->_libraryPage ) {
624 + if ( $suffix === $this->_libraryPage ) {
489 625 wp_enqueue_style( 'visualizer-library', VISUALIZER_ABSURL . 'css/library.css', array(), Visualizer_Plugin::VERSION );
490 626 $this->_addFilter( 'media_upload_tabs', 'setupVisualizerTab' );
491 627 wp_enqueue_media();
492 628 wp_enqueue_script(
@@ -494,8 +630,9 @@
494 630 VISUALIZER_ABSURL . 'js/library.js',
495 631 array(
496 632 'jquery',
497 633 'media-views',
634 + 'clipboard',
498 635 ),
499 636 Visualizer_Plugin::VERSION,
500 637 true
501 638 );
@@ -544,14 +681,177 @@
544 681 *
545 682 * @access public
546 683 */
547 684 public function registerAdminMenu() {
548 - $title = esc_html__( 'Visualizer Library', 'visualizer' );
549 - $callback = array( $this, 'renderLibraryPage' );
550 - $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' ) );
551 716 }
552 717
553 718 /**
719 + * Handle get pro plugin submenu.
720 + */
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 + /**
554 854 * Get the instance of WP_Query that fetches the charts as per the given criteria.
555 855 */
556 856 private function getQuery() {
557 857 static $q;
@@ -570,29 +870,34 @@
570 870 'default' => 1,
571 871 ),
572 872 )
573 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 +
574 889 // the initial query arguments to fetch charts
575 890 $query_args = array(
576 891 'post_type' => Visualizer_Plugin::CPT_VISUALIZER,
577 - 'posts_per_page' => 6,
892 + 'posts_per_page' => $per_page,
578 893 'paged' => $page,
579 894 );
580 - // add chart type filter to the query arguments
581 - $filter = filter_input( INPUT_GET, 'type' );
582 - if ( $filter && in_array( $filter, Visualizer_Plugin::getChartTypes() ) ) {
583 - $query_args['meta_query'] = array(
584 - array(
585 - 'key' => Visualizer_Plugin::CF_CHART_TYPE,
586 - 'value' => $filter,
587 - 'compare' => '=',
588 - ),
589 - );
590 - } else {
591 - $filter = 'all';
592 - }
895 +
896 + $this->getDisplayFilters( $query_args );
897 +
593 898 // Added by Ash/Upwork
594 - $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
595 900 if ( $filterByMeta ) {
596 901 $query = array(
597 902 'key' => Visualizer_Plugin::CF_SETTINGS,
598 903 'value' => $filterByMeta,
@@ -601,13 +906,26 @@
601 906 $meta = isset( $query_args['meta_query'] ) ? $query_args['meta_query'] : array();
602 907 $meta[] = $query;
603 908 $query_args['meta_query'] = $meta;
604 909 }
605 - $q = new WP_Query( $query_args );
910 + $q = new WP_Query( apply_filters( 'visualizer_query_args', $query_args ) );
606 911 return $q;
607 912 }
608 913
609 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 + /**
610 928 * Renders visualizer library page.
611 929 *
612 930 * @since 1.0.0
613 931 *
@@ -630,9 +948,9 @@
630 948 )
631 949 );
632 950 // add chart type filter to the query arguments
633 951 $filter = filter_input( INPUT_GET, 'type' );
634 - if ( ! ( $filter && in_array( $filter, Visualizer_Plugin::getChartTypes() ) ) ) {
952 + if ( ! ( $filter && in_array( $filter, Visualizer_Plugin::getChartTypes(), true ) ) ) {
635 953 $filter = 'all';
636 954 }
637 955
638 956 $css = '';
@@ -653,12 +971,27 @@
653 971 if ( ! empty( $atts['settings'] ) ) {
654 972 $settings = apply_filters( $atts['settings'], $settings, $chart->ID, $type );
655 973 }
656 974
657 - unset( $settings['height'], $settings['width'] );
975 + if ( $settings ) {
976 + unset( $settings['height'], $settings['width'], $settings['chartArea'] );
977 + }
978 +
658 979 $series = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_SERIES, get_post_meta( $chart->ID, Visualizer_Plugin::CF_SERIES, true ), $chart->ID, $type );
659 - $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 );
660 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 +
661 994 $library = $this->load_chart_type( $chart->ID );
662 995
663 996 $id = 'visualizer-' . $chart->ID;
664 997 $arguments = $this->get_inline_custom_css( $id, $settings );
@@ -666,8 +999,15 @@
666 999 $css .= $arguments[0];
667 1000 $settings = $arguments[1];
668 1001 }
669 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 +
670 1010 // add chart to the array
671 1011 $charts[ $id ] = array(
672 1012 'id' => $chart->ID,
673 1013 'type' => $type,
@@ -686,26 +1026,39 @@
686 1026 'language' => $this->get_language(),
687 1027 'map_api_key' => get_option( 'visualizer-map-api-key' ),
688 1028 'charts' => $charts,
689 1029 'urls' => array(
690 - 'base' => add_query_arg( 'vpage', false ),
691 - 'create' => add_query_arg(
692 - array(
693 - 'action' => Visualizer_Plugin::ACTION_CREATE_CHART,
694 - 'library' => 'yes',
695 - 'type' => isset( $_GET['type'] ) ? $_GET['type'] : '',
696 - ),
697 - $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 + )
698 1042 ),
699 - 'edit' => add_query_arg(
700 - array(
701 - 'action' => Visualizer_Plugin::ACTION_EDIT_CHART,
702 - 'library' => 'yes',
703 - ),
704 - $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 + )
705 1052 ),
706 1053 ),
707 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(),
708 1061 )
709 1062 );
710 1063 // render library page
711 1064 $render = new Visualizer_Render_Library();
@@ -714,9 +1067,9 @@
714 1067 $render->types = self::_getChartTypesLocalized( false, false, false, true );
715 1068 $render->custom_css = $css;
716 1069 $render->pagination = paginate_links(
717 1070 array(
718 - 'base' => add_query_arg( 'vpage', '%#%' ),
1071 + 'base' => add_query_arg( array( 'vpage' => '%#%', 'vaction' => false ) ),
719 1072 'format' => '',
720 1073 'current' => $page,
721 1074 'total' => $query->max_num_pages,
722 1075 'type' => 'array',
@@ -721,8 +1074,11 @@
721 1074 'total' => $query->max_num_pages,
722 1075 'type' => 'array',
723 1076 )
724 1077 );
1078 +
1079 + $this->load_survey();
1080 +
725 1081 $render->render();
726 1082 }
727 1083
728 1084 /**
@@ -737,14 +1093,14 @@
737 1093 *
738 1094 * @return array Updated array of action links.
739 1095 */
740 1096 public function getPluginActionLinks( $links, $file ) {
741 - if ( $file == plugin_basename( VISUALIZER_BASEFILE ) ) {
1097 + if ( $file === plugin_basename( VISUALIZER_BASEFILE ) ) {
742 1098 array_unshift(
743 1099 $links,
744 1100 sprintf(
745 1101 '<a href="%s">%s</a>',
746 - admin_url( 'upload.php?page=' . Visualizer_Plugin::NAME ),
1102 + admin_url( 'admin.php?page=' . Visualizer_Plugin::NAME ),
747 1103 esc_html__( 'Library', 'visualizer' )
748 1104 )
749 1105 );
750 1106 }
@@ -764,17 +1120,17 @@
764 1120 *
765 1121 * @return array Updated array of plugin meta links.
766 1122 */
767 1123 public function getPluginMetaLinks( $plugin_meta, $plugin_file ) {
768 - if ( $plugin_file == plugin_basename( VISUALIZER_BASEFILE ) ) {
1124 + if ( $plugin_file === plugin_basename( VISUALIZER_BASEFILE ) ) {
769 1125 // knowledge base link
770 1126 $plugin_meta[] = sprintf(
771 - '<a href="https://github.com/codeinwp/visualizer/wiki" target="_blank">%s</a>',
772 - esc_html__( 'Knowledge Base', 'visualizer' )
1127 + '<a href="' . VISUALIZER_MAIN_DOC . '" target="_blank">%s</a>',
1128 + esc_html__( 'Docs', 'visualizer' )
773 1129 );
774 1130 // flattr link
775 1131 $plugin_meta[] = sprintf(
776 - '<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>',
777 1133 esc_html__( 'Pro Addon', 'visualizer' )
778 1134 );
779 1135 }
780 1136
@@ -780,5 +1136,146 @@
780 1136
781 1137 return $plugin_meta;
782 1138 }
783 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 + }
784 1281 }