PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.6.1
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.6.1
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 +497 -71 3.0.93.6.1 View file →
@@ -52,26 +52,108 @@
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' );
56 + $this->_addAction( 'admin_footer', 'renderTemplates' );
57 57 $this->_addAction( 'admin_enqueue_scripts', 'enqueueLibraryScripts', null, 8 );
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 + if ( defined( 'TI_CYPRESS_TESTING' ) ) {
78 + $this->load_cypress_hooks();
79 + }
80 +
71 81 }
72 82
73 83 /**
84 + * Define the hooks that are needed for cypress.
85 + *
86 + * @since 3.4.0
87 + * @access private
88 + */
89 + private function load_cypress_hooks() {
90 + // all charts should load on the same page without pagination.
91 + add_filter(
92 + 'visualizer_query_args', function( $args ) {
93 + $args['posts_per_page'] = 20;
94 + return $args;
95 + }, 10, 1
96 + );
97 + }
98 +
99 + /**
100 + * Add disabled `optgroup` schedules to the drop downs.
101 + *
102 + * @since ?
103 + *
104 + * @access public
105 + *
106 + * @param string $feature The feature for which to add schedules.
107 + * @param int $chart_id The chart ID.
108 + * @param int $plan The plan number.
109 + */
110 + public function addSplChartSchedules( $feature, $chart_id, $plan ) {
111 + if ( apply_filters( 'visualizer_is_business', false ) ) {
112 + return;
113 + }
114 +
115 + $license = __( 'PRO', 'visualizer' );
116 + if ( Visualizer_Module::is_pro() ) {
117 + switch ( $plan ) {
118 + case 1:
119 + $license = __( 'Developer', 'visualizer' );
120 + break;
121 + }
122 + }
123 +
124 + $hours = array(
125 + '0' => __( 'Live', 'visualizer' ),
126 + '1' => __( 'Each hour', 'visualizer' ),
127 + '12' => __( 'Each 12 hours', 'visualizer' ),
128 + '24' => __( 'Each day', 'visualizer' ),
129 + '72' => __( 'Each 3 days', 'visualizer' ),
130 + );
131 +
132 + switch ( $feature ) {
133 + case 'json':
134 + case 'csv':
135 + // no more schedules if pro is already active.
136 + if ( Visualizer_Module::is_pro() ) {
137 + return;
138 + }
139 + break;
140 + case 'wp':
141 + // fall-through.
142 + case 'db':
143 + break;
144 + default:
145 + return;
146 + }
147 +
148 + echo '<optgroup disabled label="' . sprintf( __( 'More in the %s version', 'visualizer' ), $license ) . '">';
149 + foreach ( $hours as $hour => $desc ) {
150 + echo '<option disabled>' . $desc . '</option>';
151 + }
152 + echo '</optgroup>';
153 + }
154 +
155 + /**
74 156 * No limits on revisions.
75 157 */
76 158 public function limitRevisions( $num, $post ) {
77 159 if ( Visualizer_Plugin::CPT_VISUALIZER === $post->post_type ) {
@@ -132,16 +214,31 @@
132 214 *
133 215 * @access public
134 216 */
135 217 public function init() {
218 + // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
136 219 if ( current_user_can( 'edit_posts' ) && current_user_can( 'edit_pages' ) && 'true' == get_user_option( 'rich_editing' ) ) {
137 220 $this->_addFilter( 'mce_external_languages', 'add_tinymce_lang', 10, 1 );
138 221 $this->_addFilter( 'mce_external_plugins', 'tinymce_plugin', 10, 1 );
139 222 $this->_addFilter( 'mce_buttons', 'register_mce_button', 10, 1 );
223 + $this->_addFilter( 'tiny_mce_before_init', 'get_strings_for_block', 10, 1 );
140 224 }
141 225 }
142 226
143 227 /**
228 + * Add the strings required for the TinyMCE buttons for the classic block (not the classic editor).
229 + *
230 + * @since ?
231 + * @access friendly
232 + */
233 + function get_strings_for_block( $settings ) {
234 + $class = new Visualizer_Module_Language();
235 + $strings = $class->get_strings();
236 + $array = array( 'visualizer_tinymce_plugin' => json_encode( $strings ) );
237 + return array_merge( $settings, $array );
238 + }
239 +
240 + /**
144 241 * Load plugin translation for - TinyMCE API
145 242 *
146 243 * @access public
147 244 * @param array $arr The tinymce_lang array.
@@ -212,16 +309,23 @@
212 309 public function enqueueMediaScripts() {
213 310 global $typenow;
214 311 if ( post_type_supports( $typenow, 'editor' ) ) {
215 312 wp_enqueue_style( 'visualizer-media', VISUALIZER_ABSURL . 'css/media.css', array( 'media-views' ), Visualizer_Plugin::VERSION );
216 - wp_enqueue_script( 'visualizer-google-jsapi-new', '//www.gstatic.com/charts/loader.js', array( 'media-editor' ), null, true );
217 - wp_enqueue_script( 'visualizer-google-jsapi-old', '//www.google.com/jsapi', array( 'visualizer-google-jsapi-new' ), null, true );
218 - wp_enqueue_script( 'visualizer-media-model', VISUALIZER_ABSURL . 'js/media/model.js', array( 'visualizer-google-jsapi-old' ), Visualizer_Plugin::VERSION, true );
313 +
314 + // Load all the assets for the different libraries we support.
315 + $deps = array(
316 + Visualizer_Render_Sidebar_Google::enqueue_assets( array( 'media-editor' ) ),
317 + Visualizer_Render_Sidebar_Type_DataTable_Tabular::enqueue_assets( array( 'media-editor' ) ),
318 + );
319 +
320 + wp_enqueue_script( 'visualizer-media-model', VISUALIZER_ABSURL . 'js/media/model.js', $deps, Visualizer_Plugin::VERSION, true );
219 321 wp_enqueue_script( 'visualizer-media-collection', VISUALIZER_ABSURL . 'js/media/collection.js', array( 'visualizer-media-model' ), Visualizer_Plugin::VERSION, true );
220 322 wp_enqueue_script( 'visualizer-media-controller', VISUALIZER_ABSURL . 'js/media/controller.js', array( 'visualizer-media-collection' ), Visualizer_Plugin::VERSION, true );
221 323 wp_enqueue_script( 'visualizer-media-view', VISUALIZER_ABSURL . 'js/media/view.js', array( 'visualizer-media-controller' ), Visualizer_Plugin::VERSION, true );
222 324 wp_localize_script(
223 - 'visualizer-media-view', 'visualizer', array(
325 + 'visualizer-media-view',
326 + 'visualizer',
327 + array(
224 328 'i10n' => array(
225 329 'insert' => __( 'Insert', 'visualizer' ),
226 330 ),
227 331 )
@@ -275,9 +379,9 @@
275 379 * @static
276 380 * @access private
277 381 * @return array The associated array of chart types with localized names.
278 382 */
279 - public static function _getChartTypesLocalized( $enabledOnly = false, $get2Darray = false, $add_select = false ) {
383 + public static function _getChartTypesLocalized( $enabledOnly = false, $get2Darray = false, $add_select = false, $where = null ) {
280 384 $additional = array();
281 385 if ( $add_select ) {
282 386 $additional['select'] = array(
283 387 'name' => esc_html__( 'All', 'visualizer' ),
@@ -285,58 +389,88 @@
285 389 );
286 390 }
287 391
288 392 $types = array_merge(
289 - $additional, array(
393 + $additional,
394 + array(
395 + 'tabular' => array(
396 + 'name' => esc_html__( 'Table', 'visualizer' ),
397 + 'enabled' => true,
398 + 'supports' => array( 'Google Charts', 'DataTable' ),
399 + ),
290 400 'pie' => array(
291 - 'name' => esc_html__( 'Pie', 'visualizer' ),
401 + 'name' => esc_html__( 'Pie/Donut', 'visualizer' ),
292 402 'enabled' => true,
403 + 'supports' => array( 'Google Charts', 'ChartJS' ),
293 404 ),
294 405 'line' => array(
295 406 'name' => esc_html__( 'Line', 'visualizer' ),
296 407 'enabled' => true,
408 + 'supports' => array( 'Google Charts', 'ChartJS' ),
297 409 ),
298 410 'area' => array(
299 411 'name' => esc_html__( 'Area', 'visualizer' ),
300 412 'enabled' => true,
413 + // in ChartJS, the fill option is used to make Line chart an area: https://www.chartjs.org/docs/latest/charts/area.html
414 + 'supports' => array( 'Google Charts' ),
301 415 ),
302 416 'geo' => array(
303 417 'name' => esc_html__( 'Geo', 'visualizer' ),
304 418 'enabled' => true,
419 + 'supports' => array( 'Google Charts' ),
305 420 ),
306 421 'bar' => array(
307 422 'name' => esc_html__( 'Bar', 'visualizer' ),
308 423 'enabled' => true,
424 + 'supports' => array( 'Google Charts', 'ChartJS' ),
309 425 ),
310 426 'column' => array(
311 427 'name' => esc_html__( 'Column', 'visualizer' ),
312 428 'enabled' => true,
429 + 'supports' => array( 'Google Charts', 'ChartJS' ),
313 430 ),
314 - 'gauge' => array(
315 - 'name' => esc_html__( 'Gauge', 'visualizer' ),
431 + 'bubble' => array(
432 + 'name' => esc_html__( 'Bubble', 'visualizer' ),
316 433 'enabled' => true,
434 + // chartjs' bubble is ugly looking (and it won't work off the default bubble.csv) so it is being excluded for the time being.
435 + 'supports' => array( 'Google Charts' ),
317 436 ),
318 437 'scatter' => array(
319 438 'name' => esc_html__( 'Scatter', 'visualizer' ),
320 439 'enabled' => true,
440 + 'supports' => array( 'Google Charts' ),
321 441 ),
442 + 'gauge' => array(
443 + 'name' => esc_html__( 'Gauge', 'visualizer' ),
444 + 'enabled' => true,
445 + 'supports' => array( 'Google Charts' ),
446 + ),
322 447 'candlestick' => array(
323 448 'name' => esc_html__( 'Candlestick', 'visualizer' ),
324 449 'enabled' => true,
450 + 'supports' => array( 'Google Charts' ),
325 451 ),
326 452 // pro types
327 - 'table' => array(
328 - 'name' => esc_html__( 'Table', 'visualizer' ),
329 - 'enabled' => false,
330 - ),
331 453 'timeline' => array(
332 454 'name' => esc_html__( 'Timeline', 'visualizer' ),
333 455 'enabled' => false,
456 + 'supports' => array( 'Google Charts', 'ChartJS' ),
334 457 ),
335 458 'combo' => array(
336 459 'name' => esc_html__( 'Combo', 'visualizer' ),
337 460 'enabled' => false,
461 + 'supports' => array( 'Google Charts' ),
338 462 ),
463 + 'polarArea' => array(
464 + 'name' => esc_html__( 'Polar Area', 'visualizer' ),
465 + 'enabled' => false,
466 + 'supports' => array( 'ChartJS' ),
467 + ),
468 + 'radar' => array(
469 + 'name' => esc_html__( 'Radar/Spider', 'visualizer' ),
470 + 'enabled' => false,
471 + 'supports' => array( 'ChartJS' ),
472 + ),
339 473 )
340 474 );
341 475 $types = apply_filters( 'visualizer_pro_chart_types', $types );
342 476 if ( $enabledOnly ) {
@@ -345,8 +479,12 @@
345 479 if ( ! is_array( $array ) ) {
346 480 // support for old pro
347 481 $array = array( 'enabled' => true, 'name' => $array );
348 482 }
483 + // backward compatibility for PRO before v1.9.0
484 + if ( ! array_key_exists( 'supports', $array ) ) {
485 + $array['supports'] = array( 'Google Charts' );
486 + }
349 487 if ( ! $array['enabled'] ) {
350 488 continue;
351 489 }
352 490 $filtered[ $type ] = $array;
@@ -359,13 +497,74 @@
359 497 if ( ! is_array( $array ) ) {
360 498 // support for old pro
361 499 $array = array( 'enabled' => true, 'name' => $array );
362 500 }
501 + // backward compatibility for PRO before v1.9.0
502 + if ( ! array_key_exists( 'supports', $array ) ) {
503 + $array['supports'] = array( 'Google Charts' );
504 + }
363 505 $doubleD[ $type ] = $array['name'];
364 506 }
365 507 $types = $doubleD;
366 508 }
367 509
510 + return self::handleDeprecatedCharts( $types, $enabledOnly, $get2Darray, $where );
511 + }
512 +
513 + /**
514 + * Handle (soon-to-be) deprecated charts.
515 + */
516 + private static function handleDeprecatedCharts( $types, $enabledOnly, $get2Darray, $where ) {
517 + $deprecated = array();
518 +
519 + switch ( $where ) {
520 + case 'types':
521 + // fall-through
522 + case 'library':
523 + // if a user has a Gauge/Candlestick chart, then let them keep using it.
524 + if ( ! Visualizer_Module::is_pro() ) {
525 + if ( ! self::hasChartType( 'gauge' ) ) {
526 + if ( $get2Darray ) {
527 + $deprecated[] = 'gauge';
528 + } else {
529 + $types['gauge']['enabled'] = false;
530 + }
531 + }
532 + if ( ! self::hasChartType( 'candlestick' ) ) {
533 + if ( $get2Darray ) {
534 + $deprecated[] = 'candlestick';
535 + } else {
536 + $types['candlestick']['enabled'] = false;
537 + }
538 + }
539 + }
540 + break;
541 + default:
542 + // if a user has a Gauge/Candlestick chart, then let them keep using it.
543 + if ( ! Visualizer_Module::is_pro() ) {
544 + if ( ! self::hasChartType( 'gauge' ) ) {
545 + if ( $get2Darray ) {
546 + $deprecated[] = 'gauge';
547 + } else {
548 + $types['gauge']['enabled'] = false;
549 + }
550 + }
551 + if ( ! self::hasChartType( 'candlestick' ) ) {
552 + if ( $get2Darray ) {
553 + $deprecated[] = 'candlestick';
554 + } else {
555 + $types['candlestick']['enabled'] = false;
556 + }
557 + }
558 + }
559 + }
560 +
561 + if ( $deprecated ) {
562 + foreach ( $deprecated as $type ) {
563 + unset( $types[ $type ] );
564 + }
565 + }
566 +
368 567 return $types;
369 568 }
370 569
371 570 /**
@@ -375,11 +574,11 @@
375 574 * @global string $pagenow The name of the current page.
376 575 *
377 576 * @access public
378 577 */
379 - public function renderTempaltes() {
578 + public function renderTemplates() {
380 579 global $pagenow;
381 - if ( 'post.php' != $pagenow && 'post-new.php' != $pagenow ) {
580 + if ( 'post.php' !== $pagenow && 'post-new.php' !== $pagenow ) {
382 581 return;
383 582 }
384 583 $render = new Visualizer_Render_Templates();
385 584 $render->render();
@@ -397,26 +596,41 @@
397 596 *
398 597 * @param string $suffix The current page suffix.
399 598 */
400 599 public function enqueueLibraryScripts( $suffix ) {
401 - if ( $suffix == $this->_libraryPage ) {
600 + if ( $suffix === $this->_libraryPage ) {
402 601 wp_enqueue_style( 'visualizer-library', VISUALIZER_ABSURL . 'css/library.css', array(), Visualizer_Plugin::VERSION );
403 602 $this->_addFilter( 'media_upload_tabs', 'setupVisualizerTab' );
404 603 wp_enqueue_media();
405 604 wp_enqueue_script(
406 - 'visualizer-library', VISUALIZER_ABSURL . 'js/library.js', array(
605 + 'visualizer-library',
606 + VISUALIZER_ABSURL . 'js/library.js',
607 + array(
407 608 'jquery',
408 609 'media-views',
409 - ), Visualizer_Plugin::VERSION, true
610 + 'clipboard',
611 + ),
612 + Visualizer_Plugin::VERSION,
613 + true
410 614 );
411 - wp_enqueue_script( 'google-jsapi-new', '//www.gstatic.com/charts/loader.js', array(), null, true );
412 - wp_enqueue_script( 'google-jsapi-old', '//www.google.com/jsapi', array( 'google-jsapi-new' ), null, true );
413 - wp_enqueue_script(
414 - 'visualizer-render', VISUALIZER_ABSURL . 'js/render.js', array(
415 - 'google-jsapi-old',
416 - 'visualizer-library',
417 - ), Visualizer_Plugin::VERSION, true
418 - );
615 +
616 + wp_enqueue_script( 'visualizer-customization', $this->get_user_customization_js(), array(), null, true );
617 +
618 + $query = $this->getQuery();
619 + while ( $query->have_posts() ) {
620 + $chart = $query->next_post();
621 + $library = $this->load_chart_type( $chart->ID );
622 + if ( is_null( $library ) ) {
623 + continue;
624 + }
625 + wp_enqueue_script(
626 + "visualizer-render-$library",
627 + VISUALIZER_ABSURL . 'js/render-facade.js',
628 + apply_filters( 'visualizer_assets_render', array( 'visualizer-library', 'visualizer-customization' ), true ),
629 + Visualizer_Plugin::VERSION,
630 + true
631 + );
632 + }
419 633 }
420 634 }
421 635
422 636 /**
@@ -443,24 +657,140 @@
443 657 *
444 658 * @access public
445 659 */
446 660 public function registerAdminMenu() {
447 - $title = esc_html__( 'Visualizer Library', 'visualizer' );
448 - $callback = array( $this, 'renderLibraryPage' );
449 - $this->_libraryPage = add_submenu_page( 'upload.php', $title, $title, 'edit_posts', Visualizer_Plugin::NAME, $callback );
661 + $svg_base64_icon = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iNzdweCIgaGVpZ2h0PSI3N3B4IiB2aWV3Qm94PSIwIDAgNzcgNzciIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICA8IS0tIEdlbmVyYXRvcjogU2tldGNoIDUyLjYgKDY3NDkxKSAtIGh0dHA6Ly93d3cuYm9oZW1pYW5jb2RpbmcuY29tL3NrZXRjaCAtLT4KICAgIDx0aXRsZT5Db21iaW5lZCBTaGFwZTwvdGl0bGU+CiAgICA8ZGVzYz5DcmVhdGVkIHdpdGggU2tldGNoLjwvZGVzYz4KICAgIDxnIGlkPSJQcm9kdWN0LVBhZ2UiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPgogICAgICAgIDxnIGlkPSJXb3JkUHJlc3MtcGx1Z2lucyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTE5MC4wMDAwMDAsIC00MzUuMDAwMDAwKSIgZmlsbD0iIzM5QzNEMiI+CiAgICAgICAgICAgIDxwYXRoIGQ9Ik0yMjguNSw1MTIgQzIwNy4yMzcwMzcsNTEyIDE5MCw0OTQuNzYyOTYzIDE5MCw0NzMuNSBDMTkwLDQ1Mi4yMzcwMzcgMjA3LjIzNzAzNyw0MzUgMjI4LjUsNDM1IEMyNDkuNzYyOTYzLDQzNSAyNjcsNDUyLjIzNzAzNyAyNjcsNDczLjUgQzI2Nyw0OTQuNzYyOTYzIDI0OS43NjI5NjMsNTEyIDIyOC41LDUxMiBaIE0yNDYuODQzNzUsNDgzLjU5MjA1OSBMMjE1LjYyNSw0ODMuNTkyMDU5IEwyMTUuNjI1LDQ2MC44MjY1NDQgQzIxNS42MjUsNDYwLjE2NDU0NyAyMTUuMTA3NTc4LDQ1OS42MjgzNTkgMjE0LjQ2ODc1LDQ1OS42MjgzNTkgTDIxMi4xNTYyNSw0NTkuNjI4MzU5IEMyMTEuNTE3NDIyLDQ1OS42MjgzNTkgMjExLDQ2MC4xNjQ1NDcgMjExLDQ2MC44MjY1NDQgTDIxMSw0ODUuOTg4NDI5IEMyMTEsNDg3LjMxMTY3NCAyMTIuMDM1NTY2LDQ4OC4zODQ3OTggMjEzLjMxMjUsNDg4LjM4NDc5OCBMMjQ2Ljg0Mzc1LDQ4OC4zODQ3OTggQzI0Ny40ODI1NzgsNDg4LjM4NDc5OCAyNDgsNDg3Ljg0ODYxMSAyNDgsNDg3LjE4NjYxMyBMMjQ4LDQ4NC43OTAyNDQgQzI0OCw0ODQuMTI4MjQ2IDI0Ny40ODI1NzgsNDgzLjU5MjA1OSAyNDYuODQzNzUsNDgzLjU5MjA1OSBaIE0yNDQuNTMxMjUsNDYyLjAyNDcyOSBMMjM1Ljk5OTU3LDQ2Mi4wMjQ3MjkgQzIzNC40NTQ1MzEsNDYyLjAyNDcyOSAyMzMuNjgwNTY2LDQ2My45NjA1NDcgMjM0Ljc3MzIyMyw0NjUuMDkyODMyIEwyMzcuMTE0NjI5LDQ2Ny41MTkxNTYgTDIzMS44MTI1LDQ3My4wMTQzMzIgTDIyNi41MTAzNzEsNDY3LjUxOTkwNSBDMjI1LjYwNzA1MSw0NjYuNTgzODIzIDIyNC4xNDI5NDksNDY2LjU4MzgyMyAyMjMuMjQwMzUyLDQ2Ny41MTk5MDUgTDIxOC4yNzY0MjYsNDcyLjY2Mzg2MyBDMjE3LjgyNDc2Niw0NzMuMTMxOTA0IDIxNy44MjQ3NjYsNDczLjg5MDUwNSAyMTguMjc2NDI2LDQ3NC4zNTg1NDYgTDIxOS45MTEwNzQsNDc2LjA1MjQ4IEMyMjAuMzYyNzM0LDQ3Ni41MjA1MjEgMjIxLjA5NDc4NSw0NzYuNTIwNTIxIDIyMS41NDY0NDUsNDc2LjA1MjQ4IEwyMjQuODc1LDQ3Mi42MDI0NTYgTDIzMC4xNzcxMjksNDc4LjA5Njg4MyBDMjMxLjA4MDQ0OSw0NzkuMDMyOTY1IDIzMi41NDQ1NTEsNDc5LjAzMjk2NSAyMzMuNDQ3MTQ4LDQ3OC4wOTY4ODMgTDI0MC4zODQ2NDgsNDcwLjkwNzc3MyBMMjQyLjcyNjA1NSw0NzMuMzM0MDk4IEMyNDMuODE4NzExLDQ3NC40NjYzODIgMjQ1LjY4Njc3Nyw0NzMuNjY0MzQ3IDI0NS42ODY3NzcsNDcyLjA2MzI3MyBMMjQ1LjY4Njc3Nyw0NjMuMjIyOTE0IEMyNDUuNjg3NSw0NjIuNTYwOTE3IDI0NS4xNzAwNzgsNDYyLjAyNDcyOSAyNDQuNTMxMjUsNDYyLjAyNDcyOSBaIiBpZD0iQ29tYmluZWQtU2hhcGUiPjwvcGF0aD4KICAgICAgICA8L2c+CiAgICA8L2c+Cjwvc3ZnPg==';
662 +
663 + $this->_libraryPage = add_menu_page( __( 'Visualizer', 'visualizer' ), __( 'Visualizer', 'visualizer' ), 'edit_posts', Visualizer_Plugin::NAME, array( $this, 'renderLibraryPage' ), $svg_base64_icon, 99.7666 );
664 +
665 + add_submenu_page(
666 + Visualizer_Plugin::NAME,
667 + __( 'Chart Library', 'visualizer' ),
668 + __( 'Chart Library', 'visualizer' ),
669 + 'edit_posts',
670 + admin_url( 'admin.php?page=' . Visualizer_Plugin::NAME )
671 + );
672 + add_submenu_page(
673 + Visualizer_Plugin::NAME,
674 + __( 'Add New Chart', 'visualizer' ),
675 + __( 'Add New Chart', 'visualizer' ),
676 + 'edit_posts',
677 + admin_url( 'admin.php?page=' . Visualizer_Plugin::NAME . '&vaction=addnew' )
678 + );
679 + add_submenu_page(
680 + Visualizer_Plugin::NAME,
681 + __( 'Support', 'visualizer' ),
682 + __( '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>',
683 + 'edit_posts',
684 + 'viz-support',
685 + array( $this, 'renderSupportPage' )
686 + );
687 + remove_submenu_page( Visualizer_Plugin::NAME, Visualizer_Plugin::NAME );
688 +
689 + add_action( "load-{$this->_libraryPage}", array( $this, 'addScreenOptions' ) );
450 690 }
451 691
452 692 /**
453 - * Renders visualizer library page.
454 - *
455 - * @since 1.0.0
456 - *
457 - * @access public
693 + * Adds the screen options for pagination.
458 694 */
459 - public function renderLibraryPage() {
695 + function addScreenOptions() {
696 + $screen = get_current_screen();
697 +
698 + // bail if it's some other page.
699 + if ( ! is_object( $screen ) || $screen->id !== $this->_libraryPage ) {
700 + return;
701 + }
702 +
703 + $args = array(
704 + 'label' => __( 'Number of charts per page:', 'visualizer' ),
705 + 'default' => 6,
706 + 'option' => 'visualizer_per_page_library',
707 + );
708 + add_screen_option( 'per_page', $args );
709 + }
710 +
711 + /**
712 + * Returns the screen option for pagination.
713 + */
714 + function setScreenOptions( $status, $option, $value ) {
715 + if ( 'visualizer_per_page_library' === $option ) {
716 + return $value;
717 + }
718 + }
719 +
720 + /**
721 + * Adds the display filters to be used in the meta_query while displaying the charts.
722 + */
723 + private function getDisplayFilters( &$query_args ) {
724 + $query = array();
725 +
726 + // add chart type filter to the query arguments
727 + $type = filter_input( INPUT_GET, 'type' );
728 + if ( $type && in_array( $type, Visualizer_Plugin::getChartTypes(), true ) ) {
729 + $query[] = array(
730 + 'key' => Visualizer_Plugin::CF_CHART_TYPE,
731 + 'value' => $type,
732 + 'compare' => '=',
733 + );
734 + }
735 +
736 + // add chart library filter to the query arguments
737 + $library = filter_input( INPUT_GET, 'library' );
738 + if ( $library ) {
739 + $query[] = array(
740 + 'key' => Visualizer_Plugin::CF_CHART_LIBRARY,
741 + 'value' => $library,
742 + 'compare' => '=',
743 + );
744 + }
745 +
746 + // add date filter to the query arguments
747 + $date = filter_input( INPUT_GET, 'date' );
748 + $possible = array_keys( Visualizer_Plugin::getSupportedDateFilter() );
749 + if ( $date && in_array( $date, $possible, true ) ) {
750 + $query_args['date_query'] = array(
751 + 'after' => "$date -1 day",
752 + 'inclusive' => true,
753 + );
754 + }
755 +
756 + // add source filter to the query arguments
757 + $source = filter_input( INPUT_GET, 'source' );
758 + if ( $source ) {
759 + $source = ucwords( $source );
760 + $source = "Visualizer_Source_{$source}";
761 + $query[] = array(
762 + 'key' => Visualizer_Plugin::CF_SOURCE,
763 + 'value' => $source,
764 + 'compare' => '=',
765 + );
766 + }
767 +
768 + $query_args['meta_query'] = $query;
769 +
770 + $orderby = filter_input( INPUT_GET, 'orderby' );
771 + $order = filter_input( INPUT_GET, 'order' );
772 + if ( $orderby ) {
773 + $query_args['order_by'] = $orderby;
774 + }
775 + $query_args['order'] = empty( $order ) ? 'desc' : $order;
776 + }
777 +
778 + /**
779 + * Get the instance of WP_Query that fetches the charts as per the given criteria.
780 + */
781 + private function getQuery() {
782 + static $q;
783 + if ( ! is_null( $q ) ) {
784 + return $q;
785 + }
786 +
460 787 // get current page
461 788 $page = filter_input(
462 - INPUT_GET, 'vpage', FILTER_VALIDATE_INT, array(
789 + INPUT_GET,
790 + 'vpage',
791 + FILTER_VALIDATE_INT,
792 + array(
463 793 'options' => array(
464 794 'min_range' => 1,
465 795 'default' => 1,
466 796 ),
@@ -465,27 +795,32 @@
465 795 'default' => 1,
466 796 ),
467 797 )
468 798 );
799 +
800 + $per_page = 6;
801 + $screen = get_current_screen();
802 + if ( $screen ) {
803 + // retrieve the per_page option
804 + $screen_option = $screen->get_option( 'per_page', 'option' );
805 + // retrieve the value stored for the current user
806 + $user = get_current_user_id();
807 + $per_page = get_user_meta( $user, $screen_option, true );
808 + if ( empty( $per_page ) || $per_page < 1 ) {
809 + // nothing set, get the default value
810 + $per_page = $screen->get_option( 'per_page', 'default' );
811 + }
812 + }
813 +
469 814 // the initial query arguments to fetch charts
470 815 $query_args = array(
471 816 'post_type' => Visualizer_Plugin::CPT_VISUALIZER,
472 - 'posts_per_page' => 6,
817 + 'posts_per_page' => $per_page,
473 818 'paged' => $page,
474 819 );
475 - // add chart type filter to the query arguments
476 - $filter = filter_input( INPUT_GET, 'type' );
477 - if ( $filter && in_array( $filter, Visualizer_Plugin::getChartTypes() ) ) {
478 - $query_args['meta_query'] = array(
479 - array(
480 - 'key' => Visualizer_Plugin::CF_CHART_TYPE,
481 - 'value' => $filter,
482 - 'compare' => '=',
483 - ),
484 - );
485 - } else {
486 - $filter = 'all';
487 - }
820 +
821 + $this->getDisplayFilters( $query_args );
822 +
488 823 // Added by Ash/Upwork
489 824 $filterByMeta = filter_input( INPUT_GET, 's', FILTER_SANITIZE_STRING );
490 825 if ( $filterByMeta ) {
491 826 $query = array(
@@ -496,56 +831,146 @@
496 831 $meta = isset( $query_args['meta_query'] ) ? $query_args['meta_query'] : array();
497 832 $meta[] = $query;
498 833 $query_args['meta_query'] = $meta;
499 834 }
500 - // Added by Ash/Upwork
501 - // fetch charts
835 + $q = new WP_Query( apply_filters( 'visualizer_query_args', $query_args ) );
836 + return $q;
837 + }
838 +
839 + /**
840 + * Renders support page.
841 + *
842 + * @since 3.3.0
843 + *
844 + * @access public
845 + */
846 + public function renderSupportPage() {
847 + wp_enqueue_style( 'visualizer-upsell', VISUALIZER_ABSURL . 'css/upsell.css', array(), Visualizer_Plugin::VERSION );
848 + include_once VISUALIZER_ABSPATH . '/templates/support.php';
849 + }
850 +
851 + /**
852 + * Renders visualizer library page.
853 + *
854 + * @since 1.0.0
855 + *
856 + * @access public
857 + */
858 + public function renderLibraryPage() {
502 859 $charts = array();
503 - $query = new WP_Query( $query_args );
860 + $query = $this->getQuery();
861 +
862 + // get current page
863 + $page = filter_input(
864 + INPUT_GET,
865 + 'vpage',
866 + FILTER_VALIDATE_INT,
867 + array(
868 + 'options' => array(
869 + 'min_range' => 1,
870 + 'default' => 1,
871 + ),
872 + )
873 + );
874 + // add chart type filter to the query arguments
875 + $filter = filter_input( INPUT_GET, 'type' );
876 + if ( ! ( $filter && in_array( $filter, Visualizer_Plugin::getChartTypes(), true ) ) ) {
877 + $filter = 'all';
878 + }
879 +
880 + $css = '';
504 881 while ( $query->have_posts() ) {
505 882 $chart = $query->next_post();
506 883
507 884 // if the user has updated a chart and instead of saving it, has closed the modal. If the user refreshes, they should get the original chart.
508 885 $chart = $this->handleExistingRevisions( $chart->ID, $chart );
886 + // refresh a "live" db query chart.
887 + $chart = apply_filters( 'visualizer_schedule_refresh_chart', $chart, $chart->ID, false );
509 888
889 + $type = get_post_meta( $chart->ID, Visualizer_Plugin::CF_CHART_TYPE, true );
890 +
510 891 // fetch and update settings
511 892 $settings = get_post_meta( $chart->ID, Visualizer_Plugin::CF_SETTINGS, true );
512 - unset( $settings['height'], $settings['width'] );
513 - $type = get_post_meta( $chart->ID, Visualizer_Plugin::CF_CHART_TYPE, true );
893 +
894 + $settings = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_SETTINGS, $settings, $chart->ID, $type );
895 + if ( ! empty( $atts['settings'] ) ) {
896 + $settings = apply_filters( $atts['settings'], $settings, $chart->ID, $type );
897 + }
898 +
899 + if ( $settings ) {
900 + unset( $settings['height'], $settings['width'], $settings['chartArea'] );
901 + }
902 +
514 903 $series = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_SERIES, get_post_meta( $chart->ID, Visualizer_Plugin::CF_SERIES, true ), $chart->ID, $type );
515 - $data = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_DATA, unserialize( html_entity_decode( $chart->post_content ) ), $chart->ID, $type );
904 + $data = self::get_chart_data( $chart, $type );
905 +
906 + // Set default setting series when add manual chart data - Only during first creation.
907 + if ( isset( $settings['series'] ) && ! empty( $series ) ) {
908 + $count_series = count( $series ) - count( $settings['series'] );
909 + if ( $count_series > 1 ) {
910 + $clone_last_series = end( $settings['series'] );
911 + $clone_last_series = array_fill_keys( array_keys( $clone_last_series ), '' );
912 + foreach ( range( 1, $count_series ) as $item ) {
913 + $settings['series'][] = $clone_last_series;
914 + }
915 + }
916 + }
917 +
918 + $library = $this->load_chart_type( $chart->ID );
919 +
920 + $id = 'visualizer-' . $chart->ID;
921 + $arguments = $this->get_inline_custom_css( $id, $settings );
922 + if ( ! empty( $arguments ) ) {
923 + $css .= $arguments[0];
924 + $settings = $arguments[1];
925 + }
926 +
516 927 // add chart to the array
517 - $charts[ 'visualizer-' . $chart->ID ] = array(
928 + $charts[ $id ] = array(
518 929 'id' => $chart->ID,
519 930 'type' => $type,
520 931 'series' => $series,
521 932 'settings' => $settings,
522 933 'data' => $data,
934 + 'library' => $library,
523 935 );
524 936 }
525 937 // enqueue charts array
526 938 $ajaxurl = admin_url( 'admin-ajax.php' );
527 939 wp_localize_script(
528 - 'visualizer-library', 'visualizer', array(
940 + 'visualizer-library',
941 + 'visualizer',
942 + array(
529 943 'language' => $this->get_language(),
530 944 'map_api_key' => get_option( 'visualizer-map-api-key' ),
531 945 'charts' => $charts,
532 946 'urls' => array(
533 - 'base' => add_query_arg( 'vpage', false ),
947 + 'base' => add_query_arg( array( 'vpage' => false, 'vaction' => false ) ),
534 948 'create' => add_query_arg(
535 949 array(
536 950 'action' => Visualizer_Plugin::ACTION_CREATE_CHART,
537 951 'library' => 'yes',
538 952 'type' => isset( $_GET['type'] ) ? $_GET['type'] : '',
539 - ), $ajaxurl
953 + 'chart-library' => isset( $_GET['chart-library'] ) ? $_GET['chart-library'] : '',
954 + 'vaction' => false,
955 + ),
956 + $ajaxurl
540 957 ),
541 958 'edit' => add_query_arg(
542 959 array(
543 960 'action' => Visualizer_Plugin::ACTION_EDIT_CHART,
544 961 'library' => 'yes',
545 - ), $ajaxurl
962 + 'vaction' => false,
963 + ),
964 + $ajaxurl
546 965 ),
547 966 ),
967 + 'page_type' => 'library',
968 + 'is_front' => false,
969 + 'i10n' => array(
970 + 'copied' => __( 'The shortcode has been copied to your clipboard. Hit Ctrl-V/Cmd-V to paste it.', 'visualizer' ),
971 + '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' ),
972 + ),
548 973 )
549 974 );
550 975 // render library page
551 976 $render = new Visualizer_Render_Library();
@@ -550,12 +975,13 @@
550 975 // render library page
551 976 $render = new Visualizer_Render_Library();
552 977 $render->charts = $charts;
553 978 $render->type = $filter;
554 - $render->types = self::_getChartTypesLocalized();
979 + $render->types = self::_getChartTypesLocalized( false, false, false, true );
980 + $render->custom_css = $css;
555 981 $render->pagination = paginate_links(
556 982 array(
557 - 'base' => add_query_arg( 'vpage', '%#%' ),
983 + 'base' => add_query_arg( array( 'vpage' => '%#%', 'vaction' => false ) ),
558 984 'format' => '',
559 985 'current' => $page,
560 986 'total' => $query->max_num_pages,
561 987 'type' => 'array',
@@ -576,14 +1002,14 @@
576 1002 *
577 1003 * @return array Updated array of action links.
578 1004 */
579 1005 public function getPluginActionLinks( $links, $file ) {
580 - if ( $file == plugin_basename( VISUALIZER_BASEFILE ) ) {
1006 + if ( $file === plugin_basename( VISUALIZER_BASEFILE ) ) {
581 1007 array_unshift(
582 1008 $links,
583 1009 sprintf(
584 1010 '<a href="%s">%s</a>',
585 - admin_url( 'upload.php?page=' . Visualizer_Plugin::NAME ),
1011 + admin_url( 'admin.php?page=' . Visualizer_Plugin::NAME ),
586 1012 esc_html__( 'Library', 'visualizer' )
587 1013 )
588 1014 );
589 1015 }
@@ -603,17 +1029,17 @@
603 1029 *
604 1030 * @return array Updated array of plugin meta links.
605 1031 */
606 1032 public function getPluginMetaLinks( $plugin_meta, $plugin_file ) {
607 - if ( $plugin_file == plugin_basename( VISUALIZER_BASEFILE ) ) {
1033 + if ( $plugin_file === plugin_basename( VISUALIZER_BASEFILE ) ) {
608 1034 // knowledge base link
609 1035 $plugin_meta[] = sprintf(
610 - '<a href="https://github.com/codeinwp/visualizer/wiki" target="_blank">%s</a>',
611 - esc_html__( 'Knowledge Base', 'visualizer' )
1036 + '<a href="' . VISUALIZER_MAIN_DOC . '" target="_blank">%s</a>',
1037 + esc_html__( 'Docs', 'visualizer' )
612 1038 );
613 1039 // flattr link
614 1040 $plugin_meta[] = sprintf(
615 - '<a style="color:red" href="https://themeisle.com/plugins/visualizer-charts-and-graphs-pro-addon/" target="_blank">%s</a>',
1041 + '<a style="color:red" href="' . Visualizer_Plugin::PRO_TEASER_URL . '" target="_blank">%s</a>',
616 1042 esc_html__( 'Pro Addon', 'visualizer' )
617 1043 );
618 1044 }
619 1045