PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.4.8
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.4.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 +485 -71 3.0.83.4.8 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,134 @@
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 + $library = $this->load_chart_type( $chart->ID );
907 +
908 + $id = 'visualizer-' . $chart->ID;
909 + $arguments = $this->get_inline_custom_css( $id, $settings );
910 + if ( ! empty( $arguments ) ) {
911 + $css .= $arguments[0];
912 + $settings = $arguments[1];
913 + }
914 +
516 915 // add chart to the array
517 - $charts[ 'visualizer-' . $chart->ID ] = array(
916 + $charts[ $id ] = array(
518 917 'id' => $chart->ID,
519 918 'type' => $type,
520 919 'series' => $series,
521 920 'settings' => $settings,
522 921 'data' => $data,
922 + 'library' => $library,
523 923 );
524 924 }
525 925 // enqueue charts array
526 926 $ajaxurl = admin_url( 'admin-ajax.php' );
527 927 wp_localize_script(
528 - 'visualizer-library', 'visualizer', array(
928 + 'visualizer-library',
929 + 'visualizer',
930 + array(
529 931 'language' => $this->get_language(),
530 932 'map_api_key' => get_option( 'visualizer-map-api-key' ),
531 933 'charts' => $charts,
532 934 'urls' => array(
533 - 'base' => add_query_arg( 'vpage', false ),
935 + 'base' => add_query_arg( array( 'vpage' => false, 'vaction' => false ) ),
534 936 'create' => add_query_arg(
535 937 array(
536 938 'action' => Visualizer_Plugin::ACTION_CREATE_CHART,
537 939 'library' => 'yes',
538 940 'type' => isset( $_GET['type'] ) ? $_GET['type'] : '',
539 - ), $ajaxurl
941 + 'chart-library' => isset( $_GET['chart-library'] ) ? $_GET['chart-library'] : '',
942 + 'vaction' => false,
943 + ),
944 + $ajaxurl
540 945 ),
541 946 'edit' => add_query_arg(
542 947 array(
543 948 'action' => Visualizer_Plugin::ACTION_EDIT_CHART,
544 949 'library' => 'yes',
545 - ), $ajaxurl
950 + 'vaction' => false,
951 + ),
952 + $ajaxurl
546 953 ),
547 954 ),
955 + 'page_type' => 'library',
956 + 'is_front' => false,
957 + 'i10n' => array(
958 + 'copied' => __( 'The shortcode has been copied to your clipboard. Hit Ctrl-V/Cmd-V to paste it.', 'visualizer' ),
959 + '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' ),
960 + ),
548 961 )
549 962 );
550 963 // render library page
551 964 $render = new Visualizer_Render_Library();
@@ -550,12 +963,13 @@
550 963 // render library page
551 964 $render = new Visualizer_Render_Library();
552 965 $render->charts = $charts;
553 966 $render->type = $filter;
554 - $render->types = self::_getChartTypesLocalized();
967 + $render->types = self::_getChartTypesLocalized( false, false, false, true );
968 + $render->custom_css = $css;
555 969 $render->pagination = paginate_links(
556 970 array(
557 - 'base' => add_query_arg( 'vpage', '%#%' ),
971 + 'base' => add_query_arg( array( 'vpage' => '%#%', 'vaction' => false ) ),
558 972 'format' => '',
559 973 'current' => $page,
560 974 'total' => $query->max_num_pages,
561 975 'type' => 'array',
@@ -576,14 +990,14 @@
576 990 *
577 991 * @return array Updated array of action links.
578 992 */
579 993 public function getPluginActionLinks( $links, $file ) {
580 - if ( $file == plugin_basename( VISUALIZER_BASEFILE ) ) {
994 + if ( $file === plugin_basename( VISUALIZER_BASEFILE ) ) {
581 995 array_unshift(
582 996 $links,
583 997 sprintf(
584 998 '<a href="%s">%s</a>',
585 - admin_url( 'upload.php?page=' . Visualizer_Plugin::NAME ),
999 + admin_url( 'admin.php?page=' . Visualizer_Plugin::NAME ),
586 1000 esc_html__( 'Library', 'visualizer' )
587 1001 )
588 1002 );
589 1003 }
@@ -603,17 +1017,17 @@
603 1017 *
604 1018 * @return array Updated array of plugin meta links.
605 1019 */
606 1020 public function getPluginMetaLinks( $plugin_meta, $plugin_file ) {
607 - if ( $plugin_file == plugin_basename( VISUALIZER_BASEFILE ) ) {
1021 + if ( $plugin_file === plugin_basename( VISUALIZER_BASEFILE ) ) {
608 1022 // knowledge base link
609 1023 $plugin_meta[] = sprintf(
610 - '<a href="https://github.com/codeinwp/visualizer/wiki" target="_blank">%s</a>',
611 - esc_html__( 'Knowledge Base', 'visualizer' )
1024 + '<a href="' . VISUALIZER_MAIN_DOC . '" target="_blank">%s</a>',
1025 + esc_html__( 'Docs', 'visualizer' )
612 1026 );
613 1027 // flattr link
614 1028 $plugin_meta[] = sprintf(
615 - '<a style="color:red" href="https://themeisle.com/plugins/visualizer-charts-and-graphs-pro-addon/" target="_blank">%s</a>',
1029 + '<a style="color:red" href="' . Visualizer_Plugin::PRO_TEASER_URL . '" target="_blank">%s</a>',
616 1030 esc_html__( 'Pro Addon', 'visualizer' )
617 1031 );
618 1032 }
619 1033