PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.7.9
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.7.9
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 +411 -87 3.1.23.7.9 View file →
@@ -53,25 +53,107 @@
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 + 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.
@@ -216,9 +313,9 @@
216 313
217 314 // Load all the assets for the different libraries we support.
218 315 $deps = array(
219 316 Visualizer_Render_Sidebar_Google::enqueue_assets( array( 'media-editor' ) ),
220 - Visualizer_Render_Sidebar_Type_DataTable::enqueue_assets( array( 'media-editor' ) ),
317 + Visualizer_Render_Sidebar_Type_DataTable_Tabular::enqueue_assets( array( 'media-editor' ) ),
221 318 );
222 319
223 320 wp_enqueue_script( 'visualizer-media-model', VISUALIZER_ABSURL . 'js/media/model.js', $deps, Visualizer_Plugin::VERSION, true );
224 321 wp_enqueue_script( 'visualizer-media-collection', VISUALIZER_ABSURL . 'js/media/collection.js', array( 'visualizer-media-model' ), Visualizer_Plugin::VERSION, true );
@@ -267,9 +364,9 @@
267 364 'filters' => $chart_types,
268 365 'types' => array_keys( $chart_types ),
269 366 ),
270 367 'nonce' => wp_create_nonce(),
271 - 'buildurl' => add_query_arg( 'action', Visualizer_Plugin::ACTION_CREATE_CHART, admin_url( 'admin-ajax.php' ) ),
368 + 'buildurl' => esc_url( add_query_arg( 'action', Visualizer_Plugin::ACTION_CREATE_CHART, admin_url( 'admin-ajax.php' ) ) ),
272 369 );
273 370
274 371 return $strings;
275 372 }
@@ -291,64 +388,91 @@
291 388 'enabled' => true,
292 389 );
293 390 }
294 391
392 + $enabled = self::proFeaturesLocked();
393 +
295 394 $types = array_merge(
296 395 $additional,
297 396 array(
298 - 'dataTable' => array(
299 - 'name' => esc_html__( 'Table (New)', 'visualizer' ),
397 + 'tabular' => array(
398 + 'name' => esc_html__( 'Table', 'visualizer' ),
300 399 'enabled' => true,
400 + 'supports' => $enabled ? array( 'Google Charts', 'DataTable' ) : array( 'DataTable' ),
301 401 ),
302 402 'pie' => array(
303 - 'name' => esc_html__( 'Pie', 'visualizer' ),
403 + 'name' => esc_html__( 'Pie/Donut', 'visualizer' ),
304 404 'enabled' => true,
405 + 'supports' => $enabled ? array( 'Google Charts', 'ChartJS' ) : array( 'Google Charts' ),
305 406 ),
306 407 'line' => array(
307 408 'name' => esc_html__( 'Line', 'visualizer' ),
308 409 'enabled' => true,
410 + 'supports' => $enabled ? array( 'Google Charts', 'ChartJS' ) : array( 'Google Charts' ),
309 411 ),
412 + 'bar' => array(
413 + 'name' => esc_html__( 'Bar', 'visualizer' ),
414 + 'enabled' => true,
415 + 'supports' => $enabled ? array( 'Google Charts', 'ChartJS' ) : array( 'Google Charts' ),
416 + ),
310 417 'area' => array(
311 418 'name' => esc_html__( 'Area', 'visualizer' ),
312 - 'enabled' => true,
419 + 'enabled' => $enabled,
420 + // in ChartJS, the fill option is used to make Line chart an area: https://www.chartjs.org/docs/latest/charts/area.html
421 + 'supports' => array( 'Google Charts' ),
313 422 ),
314 423 'geo' => array(
315 424 'name' => esc_html__( 'Geo', 'visualizer' ),
316 - 'enabled' => true,
425 + 'enabled' => $enabled,
426 + 'supports' => array( 'Google Charts' ),
317 427 ),
318 - 'bar' => array(
319 - 'name' => esc_html__( 'Bar', 'visualizer' ),
320 - 'enabled' => true,
321 - ),
322 428 'column' => array(
323 429 'name' => esc_html__( 'Column', 'visualizer' ),
324 - 'enabled' => true,
430 + 'enabled' => $enabled,
431 + 'supports' => array( 'Google Charts', 'ChartJS' ),
325 432 ),
433 + 'bubble' => array(
434 + 'name' => esc_html__( 'Bubble', 'visualizer' ),
435 + 'enabled' => $enabled,
436 + // chartjs' bubble is ugly looking (and it won't work off the default bubble.csv) so it is being excluded for the time being.
437 + 'supports' => array( 'Google Charts' ),
438 + ),
326 439 'scatter' => array(
327 440 'name' => esc_html__( 'Scatter', 'visualizer' ),
328 - 'enabled' => true,
441 + 'enabled' => $enabled,
442 + 'supports' => array( 'Google Charts' ),
329 443 ),
330 444 'gauge' => array(
331 445 'name' => esc_html__( 'Gauge', 'visualizer' ),
332 - 'enabled' => true,
446 + 'enabled' => $enabled,
447 + 'supports' => array( 'Google Charts' ),
333 448 ),
334 449 'candlestick' => array(
335 450 'name' => esc_html__( 'Candlestick', 'visualizer' ),
336 - 'enabled' => true,
451 + 'enabled' => $enabled,
452 + 'supports' => array( 'Google Charts' ),
337 453 ),
338 454 // pro types
339 - 'table' => array(
340 - 'name' => esc_html__( 'Table (Deprecated)', 'visualizer' ),
341 - 'enabled' => false,
342 - ),
343 455 'timeline' => array(
344 456 'name' => esc_html__( 'Timeline', 'visualizer' ),
345 457 'enabled' => false,
458 + 'supports' => array( 'Google Charts', 'ChartJS' ),
346 459 ),
347 460 'combo' => array(
348 461 'name' => esc_html__( 'Combo', 'visualizer' ),
349 462 'enabled' => false,
463 + 'supports' => array( 'Google Charts' ),
350 464 ),
465 + 'polarArea' => array(
466 + 'name' => esc_html__( 'Polar Area', 'visualizer' ),
467 + 'enabled' => false,
468 + 'supports' => array( 'ChartJS' ),
469 + ),
470 + 'radar' => array(
471 + 'name' => esc_html__( 'Radar/Spider', 'visualizer' ),
472 + 'enabled' => false,
473 + 'supports' => array( 'ChartJS' ),
474 + ),
351 475 )
352 476 );
353 477 $types = apply_filters( 'visualizer_pro_chart_types', $types );
354 478 if ( $enabledOnly ) {
@@ -357,8 +481,12 @@
357 481 if ( ! is_array( $array ) ) {
358 482 // support for old pro
359 483 $array = array( 'enabled' => true, 'name' => $array );
360 484 }
485 + // backward compatibility for PRO before v1.9.0
486 + if ( ! array_key_exists( 'supports', $array ) ) {
487 + $array['supports'] = array( 'Google Charts' );
488 + }
361 489 if ( ! $array['enabled'] ) {
362 490 continue;
363 491 }
364 492 $filtered[ $type ] = $array;
@@ -371,8 +499,12 @@
371 499 if ( ! is_array( $array ) ) {
372 500 // support for old pro
373 501 $array = array( 'enabled' => true, 'name' => $array );
374 502 }
503 + // backward compatibility for PRO before v1.9.0
504 + if ( ! array_key_exists( 'supports', $array ) ) {
505 + $array['supports'] = array( 'Google Charts' );
506 + }
375 507 $doubleD[ $type ] = $array['name'];
376 508 }
377 509 $types = $doubleD;
378 510 }
@@ -386,21 +518,13 @@
386 518 private static function handleDeprecatedCharts( $types, $enabledOnly, $get2Darray, $where ) {
387 519 $deprecated = array();
388 520
389 521 switch ( $where ) {
522 + case 'types':
523 + // fall-through
390 524 case 'library':
391 - // if the user has a Google Table chart, show it as deprecated otherwise remove the option from the library.
392 - if ( ! self::hasChartType( 'table' ) ) {
393 - $deprecated[] = 'table';
394 - if ( $get2Darray ) {
395 - $types['dataTable'] = esc_html__( 'Table', 'visualizer' );
396 - } else {
397 - $types['dataTable']['name'] = esc_html__( 'Table', 'visualizer' );
398 - }
399 - }
400 -
401 525 // if a user has a Gauge/Candlestick chart, then let them keep using it.
402 - if ( ! VISUALIZER_PRO ) {
526 + if ( ! Visualizer_Module::is_pro() ) {
403 527 if ( ! self::hasChartType( 'gauge' ) ) {
404 528 if ( $get2Darray ) {
405 529 $deprecated[] = 'gauge';
406 530 } else {
@@ -416,20 +540,10 @@
416 540 }
417 541 }
418 542 break;
419 543 default:
420 - // remove the option to create a Google Table chart.
421 - $deprecated[] = 'table';
422 -
423 - // rename the new table chart type.
424 - if ( $get2Darray ) {
425 - $types['dataTable'] = esc_html__( 'Table', 'visualizer' );
426 - } else {
427 - $types['dataTable']['name'] = esc_html__( 'Table', 'visualizer' );
428 - }
429 -
430 544 // if a user has a Gauge/Candlestick chart, then let them keep using it.
431 - if ( ! VISUALIZER_PRO ) {
545 + if ( ! Visualizer_Module::is_pro() ) {
432 546 if ( ! self::hasChartType( 'gauge' ) ) {
433 547 if ( $get2Darray ) {
434 548 $deprecated[] = 'gauge';
435 549 } else {
@@ -464,9 +578,9 @@
464 578 * @access public
465 579 */
466 580 public function renderTemplates() {
467 581 global $pagenow;
468 - if ( 'post.php' != $pagenow && 'post-new.php' != $pagenow ) {
582 + if ( 'post.php' !== $pagenow && 'post-new.php' !== $pagenow ) {
469 583 return;
470 584 }
471 585 $render = new Visualizer_Render_Templates();
472 586 $render->render();
@@ -484,9 +598,9 @@
484 598 *
485 599 * @param string $suffix The current page suffix.
486 600 */
487 601 public function enqueueLibraryScripts( $suffix ) {
488 - if ( $suffix == $this->_libraryPage ) {
602 + if ( $suffix === $this->_libraryPage ) {
489 603 wp_enqueue_style( 'visualizer-library', VISUALIZER_ABSURL . 'css/library.css', array(), Visualizer_Plugin::VERSION );
490 604 $this->_addFilter( 'media_upload_tabs', 'setupVisualizerTab' );
491 605 wp_enqueue_media();
492 606 wp_enqueue_script(
@@ -494,8 +608,9 @@
494 608 VISUALIZER_ABSURL . 'js/library.js',
495 609 array(
496 610 'jquery',
497 611 'media-views',
612 + 'clipboard',
498 613 ),
499 614 Visualizer_Plugin::VERSION,
500 615 true
501 616 );
@@ -544,14 +659,168 @@
544 659 *
545 660 * @access public
546 661 */
547 662 public function registerAdminMenu() {
548 - $title = esc_html__( 'Visualizer Library', 'visualizer' );
549 - $callback = array( $this, 'renderLibraryPage' );
550 - $this->_libraryPage = add_submenu_page( 'upload.php', $title, $title, 'edit_posts', Visualizer_Plugin::NAME, $callback );
663 + $svg_base64_icon = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iNzdweCIgaGVpZ2h0PSI3N3B4IiB2aWV3Qm94PSIwIDAgNzcgNzciIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICA8IS0tIEdlbmVyYXRvcjogU2tldGNoIDUyLjYgKDY3NDkxKSAtIGh0dHA6Ly93d3cuYm9oZW1pYW5jb2RpbmcuY29tL3NrZXRjaCAtLT4KICAgIDx0aXRsZT5Db21iaW5lZCBTaGFwZTwvdGl0bGU+CiAgICA8ZGVzYz5DcmVhdGVkIHdpdGggU2tldGNoLjwvZGVzYz4KICAgIDxnIGlkPSJQcm9kdWN0LVBhZ2UiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPgogICAgICAgIDxnIGlkPSJXb3JkUHJlc3MtcGx1Z2lucyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTE5MC4wMDAwMDAsIC00MzUuMDAwMDAwKSIgZmlsbD0iIzM5QzNEMiI+CiAgICAgICAgICAgIDxwYXRoIGQ9Ik0yMjguNSw1MTIgQzIwNy4yMzcwMzcsNTEyIDE5MCw0OTQuNzYyOTYzIDE5MCw0NzMuNSBDMTkwLDQ1Mi4yMzcwMzcgMjA3LjIzNzAzNyw0MzUgMjI4LjUsNDM1IEMyNDkuNzYyOTYzLDQzNSAyNjcsNDUyLjIzNzAzNyAyNjcsNDczLjUgQzI2Nyw0OTQuNzYyOTYzIDI0OS43NjI5NjMsNTEyIDIyOC41LDUxMiBaIE0yNDYuODQzNzUsNDgzLjU5MjA1OSBMMjE1LjYyNSw0ODMuNTkyMDU5IEwyMTUuNjI1LDQ2MC44MjY1NDQgQzIxNS42MjUsNDYwLjE2NDU0NyAyMTUuMTA3NTc4LDQ1OS42MjgzNTkgMjE0LjQ2ODc1LDQ1OS42MjgzNTkgTDIxMi4xNTYyNSw0NTkuNjI4MzU5IEMyMTEuNTE3NDIyLDQ1OS42MjgzNTkgMjExLDQ2MC4xNjQ1NDcgMjExLDQ2MC44MjY1NDQgTDIxMSw0ODUuOTg4NDI5IEMyMTEsNDg3LjMxMTY3NCAyMTIuMDM1NTY2LDQ4OC4zODQ3OTggMjEzLjMxMjUsNDg4LjM4NDc5OCBMMjQ2Ljg0Mzc1LDQ4OC4zODQ3OTggQzI0Ny40ODI1NzgsNDg4LjM4NDc5OCAyNDgsNDg3Ljg0ODYxMSAyNDgsNDg3LjE4NjYxMyBMMjQ4LDQ4NC43OTAyNDQgQzI0OCw0ODQuMTI4MjQ2IDI0Ny40ODI1NzgsNDgzLjU5MjA1OSAyNDYuODQzNzUsNDgzLjU5MjA1OSBaIE0yNDQuNTMxMjUsNDYyLjAyNDcyOSBMMjM1Ljk5OTU3LDQ2Mi4wMjQ3MjkgQzIzNC40NTQ1MzEsNDYyLjAyNDcyOSAyMzMuNjgwNTY2LDQ2My45NjA1NDcgMjM0Ljc3MzIyMyw0NjUuMDkyODMyIEwyMzcuMTE0NjI5LDQ2Ny41MTkxNTYgTDIzMS44MTI1LDQ3My4wMTQzMzIgTDIyNi41MTAzNzEsNDY3LjUxOTkwNSBDMjI1LjYwNzA1MSw0NjYuNTgzODIzIDIyNC4xNDI5NDksNDY2LjU4MzgyMyAyMjMuMjQwMzUyLDQ2Ny41MTk5MDUgTDIxOC4yNzY0MjYsNDcyLjY2Mzg2MyBDMjE3LjgyNDc2Niw0NzMuMTMxOTA0IDIxNy44MjQ3NjYsNDczLjg5MDUwNSAyMTguMjc2NDI2LDQ3NC4zNTg1NDYgTDIxOS45MTEwNzQsNDc2LjA1MjQ4IEMyMjAuMzYyNzM0LDQ3Ni41MjA1MjEgMjIxLjA5NDc4NSw0NzYuNTIwNTIxIDIyMS41NDY0NDUsNDc2LjA1MjQ4IEwyMjQuODc1LDQ3Mi42MDI0NTYgTDIzMC4xNzcxMjksNDc4LjA5Njg4MyBDMjMxLjA4MDQ0OSw0NzkuMDMyOTY1IDIzMi41NDQ1NTEsNDc5LjAzMjk2NSAyMzMuNDQ3MTQ4LDQ3OC4wOTY4ODMgTDI0MC4zODQ2NDgsNDcwLjkwNzc3MyBMMjQyLjcyNjA1NSw0NzMuMzM0MDk4IEMyNDMuODE4NzExLDQ3NC40NjYzODIgMjQ1LjY4Njc3Nyw0NzMuNjY0MzQ3IDI0NS42ODY3NzcsNDcyLjA2MzI3MyBMMjQ1LjY4Njc3Nyw0NjMuMjIyOTE0IEMyNDUuNjg3NSw0NjIuNTYwOTE3IDI0NS4xNzAwNzgsNDYyLjAyNDcyOSAyNDQuNTMxMjUsNDYyLjAyNDcyOSBaIiBpZD0iQ29tYmluZWQtU2hhcGUiPjwvcGF0aD4KICAgICAgICA8L2c+CiAgICA8L2c+Cjwvc3ZnPg==';
664 +
665 + $this->_libraryPage = add_menu_page( __( 'Visualizer', 'visualizer' ), __( 'Visualizer', 'visualizer' ), 'edit_posts', Visualizer_Plugin::NAME, array( $this, 'renderLibraryPage' ), $svg_base64_icon, 99.7666 );
666 +
667 + add_submenu_page(
668 + Visualizer_Plugin::NAME,
669 + __( 'Chart Library', 'visualizer' ),
670 + __( 'Chart Library', 'visualizer' ),
671 + 'edit_posts',
672 + admin_url( 'admin.php?page=' . Visualizer_Plugin::NAME )
673 + );
674 + add_submenu_page(
675 + Visualizer_Plugin::NAME,
676 + __( 'Add New Chart', 'visualizer' ),
677 + __( 'Add New Chart', 'visualizer' ),
678 + 'edit_posts',
679 + admin_url( 'admin.php?page=' . Visualizer_Plugin::NAME . '&vaction=addnew' )
680 + );
681 + add_submenu_page(
682 + Visualizer_Plugin::NAME,
683 + __( 'Support', 'visualizer' ),
684 + __( '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>',
685 + 'edit_posts',
686 + 'viz-support',
687 + array( $this, 'renderSupportPage' )
688 + );
689 +
690 + if ( ! Visualizer_Module::is_pro() ) {
691 + add_submenu_page(
692 + Visualizer_Plugin::NAME,
693 + __( 'Get Visualizer Pro', 'visualizer' ),
694 + __( 'Get Visualizer Pro', 'visualizer' ),
695 + 'edit_posts',
696 + 'viz-get-pro',
697 + '__return_null'
698 + );
699 + add_action( 'admin_footer', array( $this, 'handleGetProSubMenu' ) );
700 + }
701 + remove_submenu_page( Visualizer_Plugin::NAME, Visualizer_Plugin::NAME );
702 +
703 + add_action( "load-{$this->_libraryPage}", array( $this, 'addScreenOptions' ) );
551 704 }
552 705
553 706 /**
707 + * Handle get pro plugin submenu.
708 + */
709 + public function handleGetProSubMenu() {
710 + ?>
711 + <style type="text/css">
712 + #toplevel_page_visualizer ul.wp-submenu li.wp-first-item + li + li + li {
713 + background: #FF7E65;
714 + font-size: 14px;
715 + font-weight: 600;
716 + color: #fff;
717 + }
718 + #toplevel_page_visualizer ul.wp-submenu li.wp-first-item + li + li + li > a {
719 + color: #fff !important;
720 + }
721 + #toplevel_page_visualizer ul.wp-submenu li.wp-first-item + li + li + li > a:hover {
722 + box-shadow: inherit;
723 + }
724 + </style>
725 + <script type="text/javascript">
726 + jQuery( document ).ready( function() {
727 + jQuery( '#toplevel_page_visualizer' ).on( 'click', 'li:not(.wp-submenu-head, .wp-first-item):eq(2)', function( e ) {
728 + e.preventDefault();
729 + window.open( 'https://themeisle.com/plugins/visualizer-charts-and-graphs/upgrade/#pricing', '_blank' );
730 + } );
731 + } );
732 + </script>
733 + <?php
734 + }
735 +
736 + /**
737 + * Adds the screen options for pagination.
738 + */
739 + function addScreenOptions() {
740 + $screen = get_current_screen();
741 +
742 + // bail if it's some other page.
743 + if ( ! is_object( $screen ) || $screen->id !== $this->_libraryPage ) {
744 + return;
745 + }
746 +
747 + $args = array(
748 + 'label' => __( 'Number of charts per page:', 'visualizer' ),
749 + 'default' => 6,
750 + 'option' => 'visualizer_library_per_page',
751 + );
752 + add_screen_option( 'per_page', $args );
753 + }
754 +
755 + /**
756 + * Returns the screen option for pagination.
757 + */
758 + function setScreenOptions( $status, $option, $value ) {
759 + if ( 'visualizer_library_per_page' === $option ) {
760 + return $value;
761 + }
762 + }
763 +
764 + /**
765 + * Adds the display filters to be used in the meta_query while displaying the charts.
766 + */
767 + private function getDisplayFilters( &$query_args ) {
768 + $query = array();
769 +
770 + // add chart type filter to the query arguments
771 + $type = filter_input( INPUT_GET, 'type' );
772 + if ( $type && in_array( $type, Visualizer_Plugin::getChartTypes(), true ) ) {
773 + $query[] = array(
774 + 'key' => Visualizer_Plugin::CF_CHART_TYPE,
775 + 'value' => $type,
776 + 'compare' => '=',
777 + );
778 + }
779 +
780 + // add chart library filter to the query arguments
781 + $library = filter_input( INPUT_GET, 'library' );
782 + if ( $library ) {
783 + $query[] = array(
784 + 'key' => Visualizer_Plugin::CF_CHART_LIBRARY,
785 + 'value' => $library,
786 + 'compare' => '=',
787 + );
788 + }
789 +
790 + // add date filter to the query arguments
791 + $date = filter_input( INPUT_GET, 'date' );
792 + $possible = array_keys( Visualizer_Plugin::getSupportedDateFilter() );
793 + if ( $date && in_array( $date, $possible, true ) ) {
794 + $query_args['date_query'] = array(
795 + 'after' => "$date -1 day",
796 + 'inclusive' => true,
797 + );
798 + }
799 +
800 + // add source filter to the query arguments
801 + $source = filter_input( INPUT_GET, 'source' );
802 + if ( $source ) {
803 + $source = ucwords( $source );
804 + $source = "Visualizer_Source_{$source}";
805 + $query[] = array(
806 + 'key' => Visualizer_Plugin::CF_SOURCE,
807 + 'value' => $source,
808 + 'compare' => '=',
809 + );
810 + }
811 +
812 + $query_args['meta_query'] = $query;
813 +
814 + $orderby = filter_input( INPUT_GET, 'orderby' );
815 + $order = filter_input( INPUT_GET, 'order' );
816 + if ( $orderby ) {
817 + $query_args['order_by'] = $orderby;
818 + }
819 + $query_args['order'] = empty( $order ) ? 'desc' : $order;
820 + }
821 +
822 + /**
554 823 * Get the instance of WP_Query that fetches the charts as per the given criteria.
555 824 */
556 825 private function getQuery() {
557 826 static $q;
@@ -570,27 +839,32 @@
570 839 'default' => 1,
571 840 ),
572 841 )
573 842 );
843 +
844 + $per_page = 6;
845 + $screen = get_current_screen();
846 + if ( $screen ) {
847 + // retrieve the per_page option
848 + $screen_option = $screen->get_option( 'per_page', 'option' );
849 + // retrieve the value stored for the current user
850 + $user = get_current_user_id();
851 + $per_page = get_user_meta( $user, $screen_option, true );
852 + if ( empty( $per_page ) || $per_page < 1 ) {
853 + // nothing set, get the default value
854 + $per_page = $screen->get_option( 'per_page', 'default' );
855 + }
856 + }
857 +
574 858 // the initial query arguments to fetch charts
575 859 $query_args = array(
576 860 'post_type' => Visualizer_Plugin::CPT_VISUALIZER,
577 - 'posts_per_page' => 6,
861 + 'posts_per_page' => $per_page,
578 862 'paged' => $page,
579 863 );
580 - // add chart type filter to the query arguments
581 - $filter = filter_input( INPUT_GET, 'type' );
582 - if ( $filter && in_array( $filter, Visualizer_Plugin::getChartTypes() ) ) {
583 - $query_args['meta_query'] = array(
584 - array(
585 - 'key' => Visualizer_Plugin::CF_CHART_TYPE,
586 - 'value' => $filter,
587 - 'compare' => '=',
588 - ),
589 - );
590 - } else {
591 - $filter = 'all';
592 - }
864 +
865 + $this->getDisplayFilters( $query_args );
866 +
593 867 // Added by Ash/Upwork
594 868 $filterByMeta = filter_input( INPUT_GET, 's', FILTER_SANITIZE_STRING );
595 869 if ( $filterByMeta ) {
596 870 $query = array(
@@ -601,13 +875,25 @@
601 875 $meta = isset( $query_args['meta_query'] ) ? $query_args['meta_query'] : array();
602 876 $meta[] = $query;
603 877 $query_args['meta_query'] = $meta;
604 878 }
605 - $q = new WP_Query( $query_args );
879 + $q = new WP_Query( apply_filters( 'visualizer_query_args', $query_args ) );
606 880 return $q;
607 881 }
608 882
609 883 /**
884 + * Renders support page.
885 + *
886 + * @since 3.3.0
887 + *
888 + * @access public
889 + */
890 + public function renderSupportPage() {
891 + wp_enqueue_style( 'visualizer-upsell', VISUALIZER_ABSURL . 'css/upsell.css', array(), Visualizer_Plugin::VERSION );
892 + include_once VISUALIZER_ABSPATH . '/templates/support.php';
893 + }
894 +
895 + /**
610 896 * Renders visualizer library page.
611 897 *
612 898 * @since 1.0.0
613 899 *
@@ -630,9 +916,9 @@
630 916 )
631 917 );
632 918 // add chart type filter to the query arguments
633 919 $filter = filter_input( INPUT_GET, 'type' );
634 - if ( ! ( $filter && in_array( $filter, Visualizer_Plugin::getChartTypes() ) ) ) {
920 + if ( ! ( $filter && in_array( $filter, Visualizer_Plugin::getChartTypes(), true ) ) ) {
635 921 $filter = 'all';
636 922 }
637 923
638 924 $css = '';
@@ -653,12 +939,27 @@
653 939 if ( ! empty( $atts['settings'] ) ) {
654 940 $settings = apply_filters( $atts['settings'], $settings, $chart->ID, $type );
655 941 }
656 942
657 - unset( $settings['height'], $settings['width'] );
943 + if ( $settings ) {
944 + unset( $settings['height'], $settings['width'], $settings['chartArea'] );
945 + }
946 +
658 947 $series = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_SERIES, get_post_meta( $chart->ID, Visualizer_Plugin::CF_SERIES, true ), $chart->ID, $type );
659 - $data = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_DATA, unserialize( html_entity_decode( $chart->post_content ) ), $chart->ID, $type );
948 + $data = self::get_chart_data( $chart, $type );
660 949
950 + // Set default setting series when add manual chart data - Only during first creation.
951 + if ( isset( $settings['series'] ) && ! empty( $series ) ) {
952 + $count_series = count( $series ) - count( $settings['series'] );
953 + if ( $count_series > 1 ) {
954 + $clone_last_series = end( $settings['series'] );
955 + $clone_last_series = array_fill_keys( array_keys( $clone_last_series ), '' );
956 + foreach ( range( 1, $count_series ) as $item ) {
957 + $settings['series'][] = $clone_last_series;
958 + }
959 + }
960 + }
961 +
661 962 $library = $this->load_chart_type( $chart->ID );
662 963
663 964 $id = 'visualizer-' . $chart->ID;
664 965 $arguments = $this->get_inline_custom_css( $id, $settings );
@@ -686,26 +987,38 @@
686 987 'language' => $this->get_language(),
687 988 'map_api_key' => get_option( 'visualizer-map-api-key' ),
688 989 'charts' => $charts,
689 990 'urls' => array(
690 - 'base' => add_query_arg( 'vpage', false ),
691 - 'create' => add_query_arg(
692 - array(
693 - 'action' => Visualizer_Plugin::ACTION_CREATE_CHART,
694 - 'library' => 'yes',
695 - 'type' => isset( $_GET['type'] ) ? $_GET['type'] : '',
696 - ),
697 - $ajaxurl
991 + 'base' => esc_url( add_query_arg( array( 'vpage' => false, 'vaction' => false ) ) ),
992 + 'create' => esc_url(
993 + add_query_arg(
994 + array(
995 + 'action' => Visualizer_Plugin::ACTION_CREATE_CHART,
996 + 'library' => 'yes',
997 + 'type' => isset( $_GET['type'] ) ? $_GET['type'] : '',
998 + 'chart-library' => isset( $_GET['chart-library'] ) ? $_GET['chart-library'] : '',
999 + 'vaction' => false,
1000 + ),
1001 + $ajaxurl
1002 + )
698 1003 ),
699 - 'edit' => add_query_arg(
700 - array(
701 - 'action' => Visualizer_Plugin::ACTION_EDIT_CHART,
702 - 'library' => 'yes',
703 - ),
704 - $ajaxurl
1004 + 'edit' => esc_url(
1005 + add_query_arg(
1006 + array(
1007 + 'action' => Visualizer_Plugin::ACTION_EDIT_CHART,
1008 + 'library' => 'yes',
1009 + 'vaction' => false,
1010 + ),
1011 + $ajaxurl
1012 + )
705 1013 ),
706 1014 ),
707 1015 'page_type' => 'library',
1016 + 'is_front' => false,
1017 + 'i10n' => array(
1018 + 'copied' => __( 'The shortcode has been copied to your clipboard. Hit Ctrl-V/Cmd-V to paste it.', 'visualizer' ),
1019 + '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' ),
1020 + ),
708 1021 )
709 1022 );
710 1023 // render library page
711 1024 $render = new Visualizer_Render_Library();
@@ -714,9 +1027,9 @@
714 1027 $render->types = self::_getChartTypesLocalized( false, false, false, true );
715 1028 $render->custom_css = $css;
716 1029 $render->pagination = paginate_links(
717 1030 array(
718 - 'base' => add_query_arg( 'vpage', '%#%' ),
1031 + 'base' => add_query_arg( array( 'vpage' => '%#%', 'vaction' => false ) ),
719 1032 'format' => '',
720 1033 'current' => $page,
721 1034 'total' => $query->max_num_pages,
722 1035 'type' => 'array',
@@ -737,14 +1050,14 @@
737 1050 *
738 1051 * @return array Updated array of action links.
739 1052 */
740 1053 public function getPluginActionLinks( $links, $file ) {
741 - if ( $file == plugin_basename( VISUALIZER_BASEFILE ) ) {
1054 + if ( $file === plugin_basename( VISUALIZER_BASEFILE ) ) {
742 1055 array_unshift(
743 1056 $links,
744 1057 sprintf(
745 1058 '<a href="%s">%s</a>',
746 - admin_url( 'upload.php?page=' . Visualizer_Plugin::NAME ),
1059 + admin_url( 'admin.php?page=' . Visualizer_Plugin::NAME ),
747 1060 esc_html__( 'Library', 'visualizer' )
748 1061 )
749 1062 );
750 1063 }
@@ -764,17 +1077,17 @@
764 1077 *
765 1078 * @return array Updated array of plugin meta links.
766 1079 */
767 1080 public function getPluginMetaLinks( $plugin_meta, $plugin_file ) {
768 - if ( $plugin_file == plugin_basename( VISUALIZER_BASEFILE ) ) {
1081 + if ( $plugin_file === plugin_basename( VISUALIZER_BASEFILE ) ) {
769 1082 // knowledge base link
770 1083 $plugin_meta[] = sprintf(
771 - '<a href="https://github.com/codeinwp/visualizer/wiki" target="_blank">%s</a>',
772 - esc_html__( 'Knowledge Base', 'visualizer' )
1084 + '<a href="' . VISUALIZER_MAIN_DOC . '" target="_blank">%s</a>',
1085 + esc_html__( 'Docs', 'visualizer' )
773 1086 );
774 1087 // flattr link
775 1088 $plugin_meta[] = sprintf(
776 - '<a style="color:red" href="https://themeisle.com/plugins/visualizer-charts-and-graphs-pro-addon/" target="_blank">%s</a>',
1089 + '<a style="color:red" href="' . Visualizer_Plugin::PRO_TEASER_URL . '" target="_blank">%s</a>',
777 1090 esc_html__( 'Pro Addon', 'visualizer' )
778 1091 );
779 1092 }
780 1093
@@ -780,5 +1093,16 @@
780 1093
781 1094 return $plugin_meta;
782 1095 }
783 1096
1097 + /**
1098 + * If check is existing user.
1099 + *
1100 + * @return bool Default false
1101 + */
1102 + public static function proFeaturesLocked() {
1103 + if ( Visualizer_Module::is_pro() ) {
1104 + return true;
1105 + }
1106 + return 'yes' === get_option( 'visualizer-new-user', 'yes' ) ? false : true;
1107 + }
784 1108 }