PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.10.8
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.10.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 3.10.4 All 148 releases
← All changes | classes/Visualizer/Module/Admin.php +589 -97 3.1.03.10.8 View file →
@@ -53,25 +53,109 @@
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 + if ( defined( 'TI_CYPRESS_TESTING' ) ) {
80 + $this->load_cypress_hooks();
81 + }
82 +
71 83 }
72 84
73 85 /**
86 + * Define the hooks that are needed for cypress.
87 + *
88 + * @since 3.4.0
89 + * @access private
90 + */
91 + private function load_cypress_hooks() {
92 + // all charts should load on the same page without pagination.
93 + add_filter(
94 + 'visualizer_query_args', function( $args ) {
95 + $args['posts_per_page'] = 20;
96 + return $args;
97 + }, 10, 1
98 + );
99 + }
100 +
101 + /**
102 + * Add disabled `optgroup` schedules to the drop downs.
103 + *
104 + * @since ?
105 + *
106 + * @access public
107 + *
108 + * @param string $feature The feature for which to add schedules.
109 + * @param int $chart_id The chart ID.
110 + * @param int $plan The plan number.
111 + */
112 + public function addSplChartSchedules( $feature, $chart_id, $plan ) {
113 + if ( apply_filters( 'visualizer_is_business', false ) ) {
114 + return;
115 + }
116 +
117 + $license = __( 'PRO', 'visualizer' );
118 + if ( Visualizer_Module::is_pro() ) {
119 + switch ( $plan ) {
120 + case 1:
121 + $license = __( 'Developer', 'visualizer' );
122 + break;
123 + }
124 + }
125 +
126 + $hours = array(
127 + '0' => __( 'Live', 'visualizer' ),
128 + '1' => __( 'Each hour', 'visualizer' ),
129 + '12' => __( 'Each 12 hours', 'visualizer' ),
130 + '24' => __( 'Each day', 'visualizer' ),
131 + '72' => __( 'Each 3 days', 'visualizer' ),
132 + );
133 +
134 + switch ( $feature ) {
135 + case 'json':
136 + case 'csv':
137 + // no more schedules if pro is already active.
138 + if ( Visualizer_Module::is_pro() ) {
139 + return;
140 + }
141 + break;
142 + case 'wp':
143 + // fall-through.
144 + case 'db':
145 + break;
146 + default:
147 + return;
148 + }
149 +
150 + echo '<optgroup disabled label="' . sprintf( __( 'More in the %s version', 'visualizer' ), $license ) . '">';
151 + foreach ( $hours as $hour => $desc ) {
152 + echo '<option disabled>' . $desc . '</option>';
153 + }
154 + echo '</optgroup>';
155 + }
156 +
157 + /**
74 158 * No limits on revisions.
75 159 */
76 160 public function limitRevisions( $num, $post ) {
77 161 if ( Visualizer_Plugin::CPT_VISUALIZER === $post->post_type ) {
@@ -132,16 +216,31 @@
132 216 *
133 217 * @access public
134 218 */
135 219 public function init() {
220 + // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
136 221 if ( current_user_can( 'edit_posts' ) && current_user_can( 'edit_pages' ) && 'true' == get_user_option( 'rich_editing' ) ) {
137 222 $this->_addFilter( 'mce_external_languages', 'add_tinymce_lang', 10, 1 );
138 223 $this->_addFilter( 'mce_external_plugins', 'tinymce_plugin', 10, 1 );
139 224 $this->_addFilter( 'mce_buttons', 'register_mce_button', 10, 1 );
225 + $this->_addFilter( 'tiny_mce_before_init', 'get_strings_for_block', 10, 1 );
140 226 }
141 227 }
142 228
143 229 /**
230 + * Add the strings required for the TinyMCE buttons for the classic block (not the classic editor).
231 + *
232 + * @since ?
233 + * @access friendly
234 + */
235 + function get_strings_for_block( $settings ) {
236 + $class = new Visualizer_Module_Language();
237 + $strings = $class->get_strings();
238 + $array = array( 'visualizer_tinymce_plugin' => json_encode( $strings ) );
239 + return array_merge( $settings, $array );
240 + }
241 +
242 + /**
144 243 * Load plugin translation for - TinyMCE API
145 244 *
146 245 * @access public
147 246 * @param array $arr The tinymce_lang array.
@@ -214,10 +313,12 @@
214 313 if ( post_type_supports( $typenow, 'editor' ) ) {
215 314 wp_enqueue_style( 'visualizer-media', VISUALIZER_ABSURL . 'css/media.css', array( 'media-views' ), Visualizer_Plugin::VERSION );
216 315
217 316 // Load all the assets for the different libraries we support.
218 - $deps = Visualizer_Render_Sidebar_Google::enqueue_assets( array( 'media-editor' ) );
219 - $deps += Visualizer_Render_Sidebar_Type_DataTable::enqueue_assets( array( 'media-editor' ) );
317 + $deps = array(
318 + Visualizer_Render_Sidebar_Google::enqueue_assets( array( 'media-editor' ) ),
319 + Visualizer_Render_Sidebar_Type_DataTable_Tabular::enqueue_assets( array( 'media-editor' ) ),
320 + );
220 321
221 322 wp_enqueue_script( 'visualizer-media-model', VISUALIZER_ABSURL . 'js/media/model.js', $deps, Visualizer_Plugin::VERSION, true );
222 323 wp_enqueue_script( 'visualizer-media-collection', VISUALIZER_ABSURL . 'js/media/collection.js', array( 'visualizer-media-model' ), Visualizer_Plugin::VERSION, true );
223 324 wp_enqueue_script( 'visualizer-media-controller', VISUALIZER_ABSURL . 'js/media/controller.js', array( 'visualizer-media-collection' ), Visualizer_Plugin::VERSION, true );
@@ -265,9 +366,9 @@
265 366 'filters' => $chart_types,
266 367 'types' => array_keys( $chart_types ),
267 368 ),
268 369 'nonce' => wp_create_nonce(),
269 - 'buildurl' => add_query_arg( 'action', Visualizer_Plugin::ACTION_CREATE_CHART, admin_url( 'admin-ajax.php' ) ),
370 + 'buildurl' => esc_url( add_query_arg( 'action', Visualizer_Plugin::ACTION_CREATE_CHART, admin_url( 'admin-ajax.php' ) ) ),
270 371 );
271 372
272 373 return $strings;
273 374 }
@@ -289,64 +390,91 @@
289 390 'enabled' => true,
290 391 );
291 392 }
292 393
394 + $enabled = self::proFeaturesLocked();
395 +
293 396 $types = array_merge(
294 397 $additional,
295 398 array(
296 - 'dataTable' => array(
297 - 'name' => esc_html__( 'Table (New)', 'visualizer' ),
399 + 'tabular' => array(
400 + 'name' => esc_html__( 'Table', 'visualizer' ),
298 401 'enabled' => true,
402 + 'supports' => $enabled ? array( 'Google Charts', 'DataTable' ) : array( 'DataTable' ),
299 403 ),
300 404 'pie' => array(
301 - 'name' => esc_html__( 'Pie', 'visualizer' ),
405 + 'name' => esc_html__( 'Pie/Donut', 'visualizer' ),
302 406 'enabled' => true,
407 + 'supports' => $enabled ? array( 'Google Charts', 'ChartJS' ) : array( 'Google Charts' ),
303 408 ),
304 409 'line' => array(
305 410 'name' => esc_html__( 'Line', 'visualizer' ),
306 411 'enabled' => true,
412 + 'supports' => $enabled ? array( 'Google Charts', 'ChartJS' ) : array( 'Google Charts' ),
307 413 ),
414 + 'bar' => array(
415 + 'name' => esc_html__( 'Bar', 'visualizer' ),
416 + 'enabled' => true,
417 + 'supports' => $enabled ? array( 'Google Charts', 'ChartJS' ) : array( 'Google Charts' ),
418 + ),
308 419 'area' => array(
309 420 'name' => esc_html__( 'Area', 'visualizer' ),
310 - 'enabled' => true,
421 + 'enabled' => $enabled,
422 + // in ChartJS, the fill option is used to make Line chart an area: https://www.chartjs.org/docs/latest/charts/area.html
423 + 'supports' => array( 'Google Charts' ),
311 424 ),
312 425 'geo' => array(
313 426 'name' => esc_html__( 'Geo', 'visualizer' ),
314 - 'enabled' => true,
427 + 'enabled' => $enabled,
428 + 'supports' => array( 'Google Charts' ),
315 429 ),
316 - 'bar' => array(
317 - 'name' => esc_html__( 'Bar', 'visualizer' ),
318 - 'enabled' => true,
319 - ),
320 430 'column' => array(
321 431 'name' => esc_html__( 'Column', 'visualizer' ),
322 - 'enabled' => true,
432 + 'enabled' => $enabled,
433 + 'supports' => array( 'Google Charts', 'ChartJS' ),
323 434 ),
324 - 'gauge' => array(
325 - 'name' => esc_html__( 'Gauge', 'visualizer' ),
326 - 'enabled' => true,
435 + 'bubble' => array(
436 + 'name' => esc_html__( 'Bubble', 'visualizer' ),
437 + 'enabled' => $enabled,
438 + // chartjs' bubble is ugly looking (and it won't work off the default bubble.csv) so it is being excluded for the time being.
439 + 'supports' => array( 'Google Charts' ),
327 440 ),
328 441 'scatter' => array(
329 442 'name' => esc_html__( 'Scatter', 'visualizer' ),
330 - 'enabled' => true,
443 + 'enabled' => $enabled,
444 + 'supports' => array( 'Google Charts' ),
331 445 ),
446 + 'gauge' => array(
447 + 'name' => esc_html__( 'Gauge', 'visualizer' ),
448 + 'enabled' => $enabled,
449 + 'supports' => array( 'Google Charts' ),
450 + ),
332 451 'candlestick' => array(
333 452 'name' => esc_html__( 'Candlestick', 'visualizer' ),
334 - 'enabled' => true,
453 + 'enabled' => $enabled,
454 + 'supports' => array( 'Google Charts' ),
335 455 ),
336 456 // pro types
337 - 'table' => array(
338 - 'name' => esc_html__( 'Table (Deprecated)', 'visualizer' ),
339 - 'enabled' => false,
340 - ),
341 457 'timeline' => array(
342 458 'name' => esc_html__( 'Timeline', 'visualizer' ),
343 459 'enabled' => false,
460 + 'supports' => array( 'Google Charts', 'ChartJS' ),
344 461 ),
345 462 'combo' => array(
346 463 'name' => esc_html__( 'Combo', 'visualizer' ),
347 464 'enabled' => false,
465 + 'supports' => array( 'Google Charts' ),
348 466 ),
467 + 'polarArea' => array(
468 + 'name' => esc_html__( 'Polar Area', 'visualizer' ),
469 + 'enabled' => false,
470 + 'supports' => array( 'ChartJS' ),
471 + ),
472 + 'radar' => array(
473 + 'name' => esc_html__( 'Radar/Spider', 'visualizer' ),
474 + 'enabled' => false,
475 + 'supports' => array( 'ChartJS' ),
476 + ),
349 477 )
350 478 );
351 479 $types = apply_filters( 'visualizer_pro_chart_types', $types );
352 480 if ( $enabledOnly ) {
@@ -355,8 +483,12 @@
355 483 if ( ! is_array( $array ) ) {
356 484 // support for old pro
357 485 $array = array( 'enabled' => true, 'name' => $array );
358 486 }
487 + // backward compatibility for PRO before v1.9.0
488 + if ( ! array_key_exists( 'supports', $array ) ) {
489 + $array['supports'] = array( 'Google Charts' );
490 + }
359 491 if ( ! $array['enabled'] ) {
360 492 continue;
361 493 }
362 494 $filtered[ $type ] = $array;
@@ -369,8 +501,12 @@
369 501 if ( ! is_array( $array ) ) {
370 502 // support for old pro
371 503 $array = array( 'enabled' => true, 'name' => $array );
372 504 }
505 + // backward compatibility for PRO before v1.9.0
506 + if ( ! array_key_exists( 'supports', $array ) ) {
507 + $array['supports'] = array( 'Google Charts' );
508 + }
373 509 $doubleD[ $type ] = $array['name'];
374 510 }
375 511 $types = $doubleD;
376 512 }
@@ -384,49 +520,45 @@
384 520 private static function handleDeprecatedCharts( $types, $enabledOnly, $get2Darray, $where ) {
385 521 $deprecated = array();
386 522
387 523 switch ( $where ) {
524 + case 'types':
525 + // fall-through
388 526 case 'library':
389 - // if the user has a Google Table chart, show it as deprecated otherwise remove the option from the library.
390 - if ( ! self::hasChartType( 'table' ) ) {
391 - $deprecated[] = 'table';
392 - if ( $get2Darray ) {
393 - $types['dataTable'] = esc_html__( 'Table', 'visualizer' );
394 - } else {
395 - $types['dataTable']['name'] = esc_html__( 'Table', 'visualizer' );
396 - }
397 - }
398 -
399 527 // if a user has a Gauge/Candlestick chart, then let them keep using it.
400 - if ( ! VISUALIZER_PRO ) {
528 + if ( ! Visualizer_Module::is_pro() ) {
401 529 if ( ! self::hasChartType( 'gauge' ) ) {
402 - $deprecated[] = 'gauge';
530 + if ( $get2Darray ) {
531 + $deprecated[] = 'gauge';
532 + } else {
533 + $types['gauge']['enabled'] = false;
534 + }
403 535 }
404 536 if ( ! self::hasChartType( 'candlestick' ) ) {
405 - $deprecated[] = 'candlestick';
537 + if ( $get2Darray ) {
538 + $deprecated[] = 'candlestick';
539 + } else {
540 + $types['candlestick']['enabled'] = false;
541 + }
406 542 }
407 543 }
408 544 break;
409 545 default:
410 - // remove the option to create a Google Table chart.
411 - $deprecated[] = 'table';
412 -
413 - // rename the new table chart type.
414 - if ( self::hasChartType( 'table' ) ) {
415 - if ( $get2Darray ) {
416 - $types['dataTable'] = esc_html__( 'Table', 'visualizer' );
417 - } else {
418 - $types['dataTable']['name'] = esc_html__( 'Table', 'visualizer' );
419 - }
420 - }
421 -
422 546 // if a user has a Gauge/Candlestick chart, then let them keep using it.
423 - if ( ! VISUALIZER_PRO ) {
547 + if ( ! Visualizer_Module::is_pro() ) {
424 548 if ( ! self::hasChartType( 'gauge' ) ) {
425 - $deprecated[] = 'gauge';
549 + if ( $get2Darray ) {
550 + $deprecated[] = 'gauge';
551 + } else {
552 + $types['gauge']['enabled'] = false;
553 + }
426 554 }
427 555 if ( ! self::hasChartType( 'candlestick' ) ) {
428 - $deprecated[] = 'candlestick';
556 + if ( $get2Darray ) {
557 + $deprecated[] = 'candlestick';
558 + } else {
559 + $types['candlestick']['enabled'] = false;
560 + }
429 561 }
430 562 }
431 563 }
432 564
@@ -448,9 +580,9 @@
448 580 * @access public
449 581 */
450 582 public function renderTemplates() {
451 583 global $pagenow;
452 - if ( 'post.php' != $pagenow && 'post-new.php' != $pagenow ) {
584 + if ( 'post.php' !== $pagenow && 'post-new.php' !== $pagenow ) {
453 585 return;
454 586 }
455 587 $render = new Visualizer_Render_Templates();
456 588 $render->render();
@@ -468,9 +600,9 @@
468 600 *
469 601 * @param string $suffix The current page suffix.
470 602 */
471 603 public function enqueueLibraryScripts( $suffix ) {
472 - if ( $suffix == $this->_libraryPage ) {
604 + if ( $suffix === $this->_libraryPage ) {
473 605 wp_enqueue_style( 'visualizer-library', VISUALIZER_ABSURL . 'css/library.css', array(), Visualizer_Plugin::VERSION );
474 606 $this->_addFilter( 'media_upload_tabs', 'setupVisualizerTab' );
475 607 wp_enqueue_media();
476 608 wp_enqueue_script(
@@ -478,8 +610,9 @@
478 610 VISUALIZER_ABSURL . 'js/library.js',
479 611 array(
480 612 'jquery',
481 613 'media-views',
614 + 'clipboard',
482 615 ),
483 616 Visualizer_Plugin::VERSION,
484 617 true
485 618 );
@@ -528,14 +661,177 @@
528 661 *
529 662 * @access public
530 663 */
531 664 public function registerAdminMenu() {
532 - $title = esc_html__( 'Visualizer Library', 'visualizer' );
533 - $callback = array( $this, 'renderLibraryPage' );
534 - $this->_libraryPage = add_submenu_page( 'upload.php', $title, $title, 'edit_posts', Visualizer_Plugin::NAME, $callback );
665 + $svg_base64_icon = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iNzdweCIgaGVpZ2h0PSI3N3B4IiB2aWV3Qm94PSIwIDAgNzcgNzciIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICA8IS0tIEdlbmVyYXRvcjogU2tldGNoIDUyLjYgKDY3NDkxKSAtIGh0dHA6Ly93d3cuYm9oZW1pYW5jb2RpbmcuY29tL3NrZXRjaCAtLT4KICAgIDx0aXRsZT5Db21iaW5lZCBTaGFwZTwvdGl0bGU+CiAgICA8ZGVzYz5DcmVhdGVkIHdpdGggU2tldGNoLjwvZGVzYz4KICAgIDxnIGlkPSJQcm9kdWN0LVBhZ2UiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPgogICAgICAgIDxnIGlkPSJXb3JkUHJlc3MtcGx1Z2lucyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTE5MC4wMDAwMDAsIC00MzUuMDAwMDAwKSIgZmlsbD0iIzM5QzNEMiI+CiAgICAgICAgICAgIDxwYXRoIGQ9Ik0yMjguNSw1MTIgQzIwNy4yMzcwMzcsNTEyIDE5MCw0OTQuNzYyOTYzIDE5MCw0NzMuNSBDMTkwLDQ1Mi4yMzcwMzcgMjA3LjIzNzAzNyw0MzUgMjI4LjUsNDM1IEMyNDkuNzYyOTYzLDQzNSAyNjcsNDUyLjIzNzAzNyAyNjcsNDczLjUgQzI2Nyw0OTQuNzYyOTYzIDI0OS43NjI5NjMsNTEyIDIyOC41LDUxMiBaIE0yNDYuODQzNzUsNDgzLjU5MjA1OSBMMjE1LjYyNSw0ODMuNTkyMDU5IEwyMTUuNjI1LDQ2MC44MjY1NDQgQzIxNS42MjUsNDYwLjE2NDU0NyAyMTUuMTA3NTc4LDQ1OS42MjgzNTkgMjE0LjQ2ODc1LDQ1OS42MjgzNTkgTDIxMi4xNTYyNSw0NTkuNjI4MzU5IEMyMTEuNTE3NDIyLDQ1OS42MjgzNTkgMjExLDQ2MC4xNjQ1NDcgMjExLDQ2MC44MjY1NDQgTDIxMSw0ODUuOTg4NDI5IEMyMTEsNDg3LjMxMTY3NCAyMTIuMDM1NTY2LDQ4OC4zODQ3OTggMjEzLjMxMjUsNDg4LjM4NDc5OCBMMjQ2Ljg0Mzc1LDQ4OC4zODQ3OTggQzI0Ny40ODI1NzgsNDg4LjM4NDc5OCAyNDgsNDg3Ljg0ODYxMSAyNDgsNDg3LjE4NjYxMyBMMjQ4LDQ4NC43OTAyNDQgQzI0OCw0ODQuMTI4MjQ2IDI0Ny40ODI1NzgsNDgzLjU5MjA1OSAyNDYuODQzNzUsNDgzLjU5MjA1OSBaIE0yNDQuNTMxMjUsNDYyLjAyNDcyOSBMMjM1Ljk5OTU3LDQ2Mi4wMjQ3MjkgQzIzNC40NTQ1MzEsNDYyLjAyNDcyOSAyMzMuNjgwNTY2LDQ2My45NjA1NDcgMjM0Ljc3MzIyMyw0NjUuMDkyODMyIEwyMzcuMTE0NjI5LDQ2Ny41MTkxNTYgTDIzMS44MTI1LDQ3My4wMTQzMzIgTDIyNi41MTAzNzEsNDY3LjUxOTkwNSBDMjI1LjYwNzA1MSw0NjYuNTgzODIzIDIyNC4xNDI5NDksNDY2LjU4MzgyMyAyMjMuMjQwMzUyLDQ2Ny41MTk5MDUgTDIxOC4yNzY0MjYsNDcyLjY2Mzg2MyBDMjE3LjgyNDc2Niw0NzMuMTMxOTA0IDIxNy44MjQ3NjYsNDczLjg5MDUwNSAyMTguMjc2NDI2LDQ3NC4zNTg1NDYgTDIxOS45MTEwNzQsNDc2LjA1MjQ4IEMyMjAuMzYyNzM0LDQ3Ni41MjA1MjEgMjIxLjA5NDc4NSw0NzYuNTIwNTIxIDIyMS41NDY0NDUsNDc2LjA1MjQ4IEwyMjQuODc1LDQ3Mi42MDI0NTYgTDIzMC4xNzcxMjksNDc4LjA5Njg4MyBDMjMxLjA4MDQ0OSw0NzkuMDMyOTY1IDIzMi41NDQ1NTEsNDc5LjAzMjk2NSAyMzMuNDQ3MTQ4LDQ3OC4wOTY4ODMgTDI0MC4zODQ2NDgsNDcwLjkwNzc3MyBMMjQyLjcyNjA1NSw0NzMuMzM0MDk4IEMyNDMuODE4NzExLDQ3NC40NjYzODIgMjQ1LjY4Njc3Nyw0NzMuNjY0MzQ3IDI0NS42ODY3NzcsNDcyLjA2MzI3MyBMMjQ1LjY4Njc3Nyw0NjMuMjIyOTE0IEMyNDUuNjg3NSw0NjIuNTYwOTE3IDI0NS4xNzAwNzgsNDYyLjAyNDcyOSAyNDQuNTMxMjUsNDYyLjAyNDcyOSBaIiBpZD0iQ29tYmluZWQtU2hhcGUiPjwvcGF0aD4KICAgICAgICA8L2c+CiAgICA8L2c+Cjwvc3ZnPg==';
666 +
667 + $this->_libraryPage = add_menu_page( __( 'Visualizer', 'visualizer' ), __( 'Visualizer', 'visualizer' ), 'edit_posts', Visualizer_Plugin::NAME, array( $this, 'renderLibraryPage' ), $svg_base64_icon, 99.7666 );
668 +
669 + add_submenu_page(
670 + Visualizer_Plugin::NAME,
671 + __( 'Chart Library', 'visualizer' ),
672 + __( 'Chart Library', 'visualizer' ),
673 + 'edit_posts',
674 + 'admin.php?page=' . Visualizer_Plugin::NAME
675 + );
676 + add_submenu_page(
677 + Visualizer_Plugin::NAME,
678 + __( 'Add New Chart', 'visualizer' ),
679 + __( 'Add New Chart', 'visualizer' ),
680 + 'edit_posts',
681 + 'admin.php?page=' . Visualizer_Plugin::NAME . '&vaction=addnew'
682 + );
683 + add_submenu_page(
684 + Visualizer_Plugin::NAME,
685 + __( 'Support', 'visualizer' ),
686 + __( '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>',
687 + 'edit_posts',
688 + 'viz-support',
689 + array( $this, 'renderSupportPage' )
690 + );
691 +
692 + remove_submenu_page( Visualizer_Plugin::NAME, Visualizer_Plugin::NAME );
693 +
694 + add_action( "load-{$this->_libraryPage}", array( $this, 'addScreenOptions' ) );
695 + add_action( 'admin_footer', array( $this, 'handleGetProSubMenu' ) );
535 696 }
536 697
537 698 /**
699 + * Handle get pro plugin submenu.
700 + */
701 + public function handleGetProSubMenu() {
702 + if ( ! Visualizer_Module::is_pro() ) {
703 + ?>
704 + <style type="text/css">
705 + #toplevel_page_visualizer ul.wp-submenu li:last-child {
706 + background: #FF7E65;
707 + font-size: 14px;
708 + font-weight: 600;
709 + color: #fff;
710 + }
711 + #toplevel_page_visualizer ul.wp-submenu li:last-child > a {
712 + color: #fff !important;
713 + }
714 + #toplevel_page_visualizer ul.wp-submenu li:last-child > a:hover {
715 + box-shadow: inherit;
716 + }
717 + </style>
718 + <?php
719 + if ( get_option( 'visualizer_fresh_install', false ) ) {
720 + ?>
721 + <style type="text/css">
722 + #toplevel_page_visualizer ul.wp-submenu li.wp-first-item + li + li + li {
723 + display: none;
724 + }
725 + </style>
726 + <?php
727 + }
728 + }
729 + }
730 +
731 + /**
732 + * Adds the screen options for pagination.
733 + */
734 + function addScreenOptions() {
735 + $screen = get_current_screen();
736 +
737 + // bail if it's some other page.
738 + if ( ! is_object( $screen ) || $screen->id !== $this->_libraryPage ) {
739 + return;
740 + }
741 +
742 + $args = array(
743 + 'label' => __( 'Number of charts per page:', 'visualizer' ),
744 + 'default' => 6,
745 + 'option' => 'visualizer_library_per_page',
746 + );
747 + add_screen_option( 'per_page', $args );
748 + }
749 +
750 + /**
751 + * Returns the screen option for pagination.
752 + */
753 + function setScreenOptions( $status, $option, $value ) {
754 + if ( 'visualizer_library_per_page' === $option ) {
755 + return $value;
756 + }
757 + }
758 +
759 + /**
760 + * Adds the display filters to be used in the meta_query while displaying the charts.
761 + */
762 + private function getDisplayFilters( &$query_args ) {
763 + $query = array();
764 + global $sitepress;
765 + if ( Visualizer_Module::is_pro() && ( function_exists( 'icl_get_languages' ) && $sitepress instanceof \SitePress ) ) {
766 + $current_lang = icl_get_current_language();
767 + if ( in_array( $current_lang, array( 'all', icl_get_default_language() ), true ) ) {
768 + $query[] = array(
769 + 'key' => 'chart_lang',
770 + 'compare' => 'NOT EXISTS',
771 + );
772 + } else {
773 + $query[] = array(
774 + 'key' => 'chart_lang',
775 + 'value' => $current_lang,
776 + 'compare' => '=',
777 + );
778 + }
779 + }
780 +
781 + // add chart type filter to the query arguments
782 + $type = filter_input( INPUT_GET, 'type' );
783 + if ( $type && in_array( $type, Visualizer_Plugin::getChartTypes(), true ) ) {
784 + $query[] = array(
785 + 'key' => Visualizer_Plugin::CF_CHART_TYPE,
786 + 'value' => $type,
787 + 'compare' => '=',
788 + );
789 + }
790 +
791 + // add chart library filter to the query arguments
792 + $library = filter_input( INPUT_GET, 'library' );
793 + if ( $library ) {
794 + $query[] = array(
795 + 'key' => Visualizer_Plugin::CF_CHART_LIBRARY,
796 + 'value' => $library,
797 + 'compare' => '=',
798 + );
799 + }
800 +
801 + // add date filter to the query arguments
802 + $date = filter_input( INPUT_GET, 'date' );
803 + $possible = array_keys( Visualizer_Plugin::getSupportedDateFilter() );
804 + if ( $date && in_array( $date, $possible, true ) ) {
805 + $query_args['date_query'] = array(
806 + 'after' => "$date -1 day",
807 + 'inclusive' => true,
808 + );
809 + }
810 +
811 + // add source filter to the query arguments
812 + $source = filter_input( INPUT_GET, 'source' );
813 + if ( $source ) {
814 + $source = ucwords( $source );
815 + $source = "Visualizer_Source_{$source}";
816 + $query[] = array(
817 + 'key' => Visualizer_Plugin::CF_SOURCE,
818 + 'value' => $source,
819 + 'compare' => '=',
820 + );
821 + }
822 +
823 + $query_args['meta_query'] = $query;
824 +
825 + $orderby = filter_input( INPUT_GET, 'orderby' );
826 + $order = filter_input( INPUT_GET, 'order' );
827 + if ( $orderby ) {
828 + $query_args['order_by'] = $orderby;
829 + }
830 + $query_args['order'] = empty( $order ) ? 'desc' : $order;
831 + }
832 +
833 + /**
538 834 * Get the instance of WP_Query that fetches the charts as per the given criteria.
539 835 */
540 836 private function getQuery() {
541 837 static $q;
@@ -554,29 +850,34 @@
554 850 'default' => 1,
555 851 ),
556 852 )
557 853 );
854 +
855 + $per_page = 6;
856 + $screen = get_current_screen();
857 + if ( $screen ) {
858 + // retrieve the per_page option
859 + $screen_option = $screen->get_option( 'per_page', 'option' );
860 + // retrieve the value stored for the current user
861 + $user = get_current_user_id();
862 + $per_page = get_user_meta( $user, $screen_option, true );
863 + if ( empty( $per_page ) || $per_page < 1 ) {
864 + // nothing set, get the default value
865 + $per_page = $screen->get_option( 'per_page', 'default' );
866 + }
867 + }
868 +
558 869 // the initial query arguments to fetch charts
559 870 $query_args = array(
560 871 'post_type' => Visualizer_Plugin::CPT_VISUALIZER,
561 - 'posts_per_page' => 6,
872 + 'posts_per_page' => $per_page,
562 873 'paged' => $page,
563 874 );
564 - // add chart type filter to the query arguments
565 - $filter = filter_input( INPUT_GET, 'type' );
566 - if ( $filter && in_array( $filter, Visualizer_Plugin::getChartTypes() ) ) {
567 - $query_args['meta_query'] = array(
568 - array(
569 - 'key' => Visualizer_Plugin::CF_CHART_TYPE,
570 - 'value' => $filter,
571 - 'compare' => '=',
572 - ),
573 - );
574 - } else {
575 - $filter = 'all';
576 - }
875 +
876 + $this->getDisplayFilters( $query_args );
877 +
577 878 // Added by Ash/Upwork
578 - $filterByMeta = filter_input( INPUT_GET, 's', FILTER_SANITIZE_STRING );
879 + $filterByMeta = ! empty( $_GET['s'] ) ? sanitize_text_field( wp_unslash( $_GET['s'] ) ) : null; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
579 880 if ( $filterByMeta ) {
580 881 $query = array(
581 882 'key' => Visualizer_Plugin::CF_SETTINGS,
582 883 'value' => $filterByMeta,
@@ -585,13 +886,26 @@
585 886 $meta = isset( $query_args['meta_query'] ) ? $query_args['meta_query'] : array();
586 887 $meta[] = $query;
587 888 $query_args['meta_query'] = $meta;
588 889 }
589 - $q = new WP_Query( $query_args );
890 + $q = new WP_Query( apply_filters( 'visualizer_query_args', $query_args ) );
590 891 return $q;
591 892 }
592 893
593 894 /**
895 + * Renders support page.
896 + *
897 + * @since 3.3.0
898 + *
899 + * @access public
900 + */
901 + public function renderSupportPage() {
902 + wp_enqueue_style( 'visualizer-upsell', VISUALIZER_ABSURL . 'css/upsell.css', array(), Visualizer_Plugin::VERSION );
903 + $this->load_survey();
904 + include_once VISUALIZER_ABSPATH . '/templates/support.php';
905 + }
906 +
907 + /**
594 908 * Renders visualizer library page.
595 909 *
596 910 * @since 1.0.0
597 911 *
@@ -614,9 +928,9 @@
614 928 )
615 929 );
616 930 // add chart type filter to the query arguments
617 931 $filter = filter_input( INPUT_GET, 'type' );
618 - if ( ! ( $filter && in_array( $filter, Visualizer_Plugin::getChartTypes() ) ) ) {
932 + if ( ! ( $filter && in_array( $filter, Visualizer_Plugin::getChartTypes(), true ) ) ) {
619 933 $filter = 'all';
620 934 }
621 935
622 936 $css = '';
@@ -637,12 +951,27 @@
637 951 if ( ! empty( $atts['settings'] ) ) {
638 952 $settings = apply_filters( $atts['settings'], $settings, $chart->ID, $type );
639 953 }
640 954
641 - unset( $settings['height'], $settings['width'] );
955 + if ( $settings ) {
956 + unset( $settings['height'], $settings['width'], $settings['chartArea'] );
957 + }
958 +
642 959 $series = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_SERIES, get_post_meta( $chart->ID, Visualizer_Plugin::CF_SERIES, true ), $chart->ID, $type );
643 - $data = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_DATA, unserialize( html_entity_decode( $chart->post_content ) ), $chart->ID, $type );
960 + $data = self::get_chart_data( $chart, $type );
644 961
962 + // Set default setting series when add manual chart data - Only during first creation.
963 + if ( isset( $settings['series'] ) && ! empty( $series ) ) {
964 + $count_series = count( $series ) - count( $settings['series'] );
965 + if ( $count_series > 1 ) {
966 + $clone_last_series = end( $settings['series'] );
967 + $clone_last_series = array_fill_keys( array_keys( $clone_last_series ), '' );
968 + foreach ( range( 1, $count_series ) as $item ) {
969 + $settings['series'][] = $clone_last_series;
970 + }
971 + }
972 + }
973 +
645 974 $library = $this->load_chart_type( $chart->ID );
646 975
647 976 $id = 'visualizer-' . $chart->ID;
648 977 $arguments = $this->get_inline_custom_css( $id, $settings );
@@ -650,8 +979,15 @@
650 979 $css .= $arguments[0];
651 980 $settings = $arguments[1];
652 981 }
653 982
983 + if ( isset( $settings['controls']['ui']['labelStacking'] ) ) {
984 + unset( $settings['controls']['ui']['labelStacking'] );
985 + }
986 + if ( isset( $settings['controls']['ui']['orientation'] ) ) {
987 + unset( $settings['controls']['ui']['orientation'] );
988 + }
989 +
654 990 // add chart to the array
655 991 $charts[ $id ] = array(
656 992 'id' => $chart->ID,
657 993 'type' => $type,
@@ -670,26 +1006,38 @@
670 1006 'language' => $this->get_language(),
671 1007 'map_api_key' => get_option( 'visualizer-map-api-key' ),
672 1008 'charts' => $charts,
673 1009 'urls' => array(
674 - 'base' => add_query_arg( 'vpage', false ),
675 - 'create' => add_query_arg(
676 - array(
677 - 'action' => Visualizer_Plugin::ACTION_CREATE_CHART,
678 - 'library' => 'yes',
679 - 'type' => isset( $_GET['type'] ) ? $_GET['type'] : '',
680 - ),
681 - $ajaxurl
1010 + 'base' => esc_url( add_query_arg( array( 'vpage' => false, 'vaction' => false ) ) ),
1011 + 'create' => esc_url(
1012 + add_query_arg(
1013 + array(
1014 + 'action' => Visualizer_Plugin::ACTION_CREATE_CHART,
1015 + 'library' => 'yes',
1016 + 'type' => isset( $_GET['type'] ) ? $_GET['type'] : '',
1017 + 'chart-library' => isset( $_GET['chart-library'] ) ? $_GET['chart-library'] : '',
1018 + 'vaction' => false,
1019 + ),
1020 + $ajaxurl
1021 + )
682 1022 ),
683 - 'edit' => add_query_arg(
684 - array(
685 - 'action' => Visualizer_Plugin::ACTION_EDIT_CHART,
686 - 'library' => 'yes',
687 - ),
688 - $ajaxurl
1023 + 'edit' => esc_url(
1024 + add_query_arg(
1025 + array(
1026 + 'action' => Visualizer_Plugin::ACTION_EDIT_CHART,
1027 + 'library' => 'yes',
1028 + 'vaction' => false,
1029 + ),
1030 + $ajaxurl
1031 + )
689 1032 ),
690 1033 ),
691 1034 'page_type' => 'library',
1035 + 'is_front' => false,
1036 + 'i10n' => array(
1037 + 'copied' => __( 'The shortcode has been copied to your clipboard. Hit Ctrl-V/Cmd-V to paste it.', 'visualizer' ),
1038 + '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' ),
1039 + ),
692 1040 )
693 1041 );
694 1042 // render library page
695 1043 $render = new Visualizer_Render_Library();
@@ -698,9 +1046,9 @@
698 1046 $render->types = self::_getChartTypesLocalized( false, false, false, true );
699 1047 $render->custom_css = $css;
700 1048 $render->pagination = paginate_links(
701 1049 array(
702 - 'base' => add_query_arg( 'vpage', '%#%' ),
1050 + 'base' => add_query_arg( array( 'vpage' => '%#%', 'vaction' => false ) ),
703 1051 'format' => '',
704 1052 'current' => $page,
705 1053 'total' => $query->max_num_pages,
706 1054 'type' => 'array',
@@ -705,8 +1053,11 @@
705 1053 'total' => $query->max_num_pages,
706 1054 'type' => 'array',
707 1055 )
708 1056 );
1057 +
1058 + $this->load_survey();
1059 +
709 1060 $render->render();
710 1061 }
711 1062
712 1063 /**
@@ -721,14 +1072,14 @@
721 1072 *
722 1073 * @return array Updated array of action links.
723 1074 */
724 1075 public function getPluginActionLinks( $links, $file ) {
725 - if ( $file == plugin_basename( VISUALIZER_BASEFILE ) ) {
1076 + if ( $file === plugin_basename( VISUALIZER_BASEFILE ) ) {
726 1077 array_unshift(
727 1078 $links,
728 1079 sprintf(
729 1080 '<a href="%s">%s</a>',
730 - admin_url( 'upload.php?page=' . Visualizer_Plugin::NAME ),
1081 + admin_url( 'admin.php?page=' . Visualizer_Plugin::NAME ),
731 1082 esc_html__( 'Library', 'visualizer' )
732 1083 )
733 1084 );
734 1085 }
@@ -748,17 +1099,17 @@
748 1099 *
749 1100 * @return array Updated array of plugin meta links.
750 1101 */
751 1102 public function getPluginMetaLinks( $plugin_meta, $plugin_file ) {
752 - if ( $plugin_file == plugin_basename( VISUALIZER_BASEFILE ) ) {
1103 + if ( $plugin_file === plugin_basename( VISUALIZER_BASEFILE ) ) {
753 1104 // knowledge base link
754 1105 $plugin_meta[] = sprintf(
755 - '<a href="https://github.com/codeinwp/visualizer/wiki" target="_blank">%s</a>',
756 - esc_html__( 'Knowledge Base', 'visualizer' )
1106 + '<a href="' . VISUALIZER_MAIN_DOC . '" target="_blank">%s</a>',
1107 + esc_html__( 'Docs', 'visualizer' )
757 1108 );
758 1109 // flattr link
759 1110 $plugin_meta[] = sprintf(
760 - '<a style="color:red" href="https://themeisle.com/plugins/visualizer-charts-and-graphs-pro-addon/" target="_blank">%s</a>',
1111 + '<a style="color:red" href="' . tsdk_utmify( Visualizer_Plugin::PRO_TEASER_URL, 'pluginrow' ) . '" target="_blank">%s</a>',
761 1112 esc_html__( 'Pro Addon', 'visualizer' )
762 1113 );
763 1114 }
764 1115
@@ -764,5 +1115,146 @@
764 1115
765 1116 return $plugin_meta;
766 1117 }
767 1118
1119 + /**
1120 + * If check is existing user.
1121 + *
1122 + * @return bool Default false
1123 + */
1124 + public static function proFeaturesLocked() {
1125 + if ( Visualizer_Module::is_pro() ) {
1126 + return true;
1127 + }
1128 + return 'yes' === get_option( 'visualizer-new-user', 'yes' ) ? false : true;
1129 + }
1130 +
1131 + /**
1132 + * Multilingual Support.
1133 + *
1134 + * @param int $chart_id Chart ID.
1135 + * @return bool Default false
1136 + */
1137 + public function addMultilingualSupport( $chart_id ) {
1138 + global $sitepress;
1139 + if ( Visualizer_Module::is_pro() ) {
1140 + return;
1141 + }
1142 + if ( function_exists( 'icl_get_languages' ) && $sitepress instanceof \SitePress ) {
1143 + $language = icl_get_languages();
1144 + $current_lang = icl_get_current_language();
1145 + $default_lang = icl_get_default_language();
1146 + $post_info = wpml_get_language_information( null, $chart_id );
1147 + $translations = array();
1148 + if ( ! empty( $post_info ) && ( $default_lang === $post_info['language_code'] ) ) {
1149 + $trid = $sitepress->get_element_trid( $chart_id, 'post_' . Visualizer_Plugin::CPT_VISUALIZER );
1150 + $translations = $sitepress->get_element_translations( $trid );
1151 + }
1152 + if ( empty( $translations ) ) {
1153 + return;
1154 + }
1155 + ?>
1156 + <hr><div class="visualizer-languages-list only-pro">
1157 + <?php
1158 + foreach ( $language as $lang ) {
1159 + $lang_code = $lang['code'];
1160 + if ( $current_lang !== $lang_code ) {
1161 + ?>
1162 + <a href="javascript:;">
1163 + <img src="<?php echo esc_url( $lang['country_flag_url'] ); ?>" alt="<?php echo esc_attr( $lang['translated_name'] ); ?>">
1164 + </a>
1165 + <?php
1166 + }
1167 + }
1168 + ?>
1169 + <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>
1170 + </div>
1171 + <?php
1172 + }
1173 + }
1174 +
1175 + /**
1176 + * Check chart is enabled or not.
1177 + *
1178 + * @param string $type Chart ID.
1179 + *
1180 + * @return bool Default false
1181 + */
1182 + public static function checkChartStatus( $type ) {
1183 + $types = self::_getChartTypesLocalized( false, false, false, true );
1184 + if ( isset( $types[ $type ] ) ) {
1185 + return ! empty( $types[ $type ]['enabled'] );
1186 + }
1187 + return false;
1188 + }
1189 +
1190 + /**
1191 + * Get the survey metadata.
1192 + *
1193 + * @return array The survey metadata.
1194 + */
1195 + private function get_survey_metadata() {
1196 + $install_date = get_option( 'visualizer_install', false );
1197 + $install_category = 0;
1198 +
1199 + if ( false !== $install_date ) {
1200 + $days_since_install = round( ( time() - $install_date ) / DAY_IN_SECONDS );
1201 +
1202 + if ( 0 === $days_since_install || 1 === $days_since_install ) {
1203 + $install_category = 0;
1204 + } elseif ( 1 < $days_since_install && 8 > $days_since_install ) {
1205 + $install_category = 7;
1206 + } elseif ( 8 <= $days_since_install && 31 > $days_since_install ) {
1207 + $install_category = 30;
1208 + } elseif ( 30 < $days_since_install && 90 > $days_since_install ) {
1209 + $install_category = 90;
1210 + } elseif ( 90 <= $days_since_install ) {
1211 + $install_category = 91;
1212 + }
1213 + }
1214 +
1215 + $plugin_data = get_plugin_data( VISUALIZER_BASEFILE, false, false );
1216 + $plugin_version = '';
1217 + if ( ! empty( $plugin_data['Version'] ) ) {
1218 + $plugin_version = $plugin_data['Version'];
1219 + }
1220 +
1221 + $user_id = 'visualizer_' . preg_replace( '/[^\w\d]*/', '', get_site_url() ); // Use a normalized version of the site URL as a user ID.
1222 +
1223 + $license_data = get_option( 'visualizer_pro_license_data', false );
1224 + if ( false !== $license_data ) {
1225 + $user_id = 'visualizer_' . $license_data->key;
1226 + }
1227 +
1228 + return array(
1229 + 'userId' => $user_id,
1230 + 'attributes' => array(
1231 + 'days_since_install' => $install_category,
1232 + 'free_version' => $plugin_version,
1233 + 'pro_version' => defined( 'VISUALIZER_PRO_VERSION' ) ? VISUALIZER_PRO_VERSION : '',
1234 + 'license_status' => apply_filters( 'product_visualizer_license_status', 'invalid' ),
1235 + ),
1236 + );
1237 + }
1238 +
1239 + /**
1240 + * Load the survey.
1241 + */
1242 + private function load_survey() {
1243 +
1244 + if ( defined( 'TI_CYPRESS_TESTING' ) ) {
1245 + return;
1246 + }
1247 +
1248 + $survey_handler = apply_filters( 'themeisle_sdk_dependency_script_handler', 'survey' );
1249 +
1250 + if ( empty( $survey_handler ) ) {
1251 + return;
1252 + }
1253 +
1254 + $metadata = $this->get_survey_metadata();
1255 +
1256 + do_action( 'themeisle_sdk_dependency_enqueue_script', 'survey' );
1257 + wp_enqueue_script( 'visualizer_chart_survey', VISUALIZER_ABSURL . 'js/survey.js', array( $survey_handler ), $metadata['attributes']['free_version'], true );
1258 + wp_localize_script( 'visualizer_chart_survey', 'visualizerSurveyData', $metadata );
1259 + }
768 1260 }