PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.9.2
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.9.2
4.0.8 4.0.7 4.0.6 4.0.5 4.0.4 4.0.3 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.1 3.1.2 3.1.3 3.10.0 3.10.1 3.10.10 3.10.11 3.10.12 3.10.13 3.10.14 3.10.15 3.10.2 3.10.3 All 149 releases
← All changes | classes/Visualizer/Module/Admin.php +483 -88 3.1.13.9.2 View file →
@@ -53,25 +53,109 @@
53 53 parent::__construct( $plugin );
54 54 $this->_addAction( 'load-post.php', 'enqueueMediaScripts' );
55 55 $this->_addAction( 'load-post-new.php', 'enqueueMediaScripts' );
56 56 $this->_addAction( 'admin_footer', 'renderTemplates' );
57 - $this->_addAction( 'admin_enqueue_scripts', 'enqueueLibraryScripts', null, 8 );
57 + $this->_addAction( 'admin_enqueue_scripts', 'enqueueLibraryScripts', null, 0 );
58 58 $this->_addAction( 'admin_menu', 'registerAdminMenu' );
59 59 $this->_addFilter( 'media_view_strings', 'setupMediaViewStrings' );
60 60 $this->_addFilter( 'plugin_action_links', 'getPluginActionLinks', 10, 2 );
61 + $this->_addFilter( 'plugin_row_meta', 'getPluginMetaLinks', 10, 2 );
61 62 $this->_addFilter( 'visualizer_logger_data', 'getLoggerData' );
62 - $this->_addFilter( 'visualizer_get_chart_counts', 'getChartCountsByTypeAndMeta' );
63 63 $this->_addFilter( 'visualizer_feedback_review_trigger', 'feedbackReviewTrigger' );
64 64
65 + // screen pagination
66 + $this->_addFilter( 'set-screen-option', 'setScreenOptions', 10, 3 );
67 +
65 68 // revision support.
66 69 $this->_addFilter( 'wp_revisions_to_keep', 'limitRevisions', null, 10, 2 );
67 70 $this->_addAction( '_wp_put_post_revision', 'addRevision', null, 10, 1 );
68 71 $this->_addAction( 'wp_restore_post_revision', 'restoreRevision', null, 10, 2 );
69 72
73 + $this->_addAction( 'visualizer_chart_schedules_spl', 'addSplChartSchedules', null, 10, 3 );
74 +
70 75 $this->_addAction( 'admin_init', 'init' );
76 +
77 + $this->_addAction( 'visualizer_chart_languages', 'addMultilingualSupport' );
78 +
79 + if ( defined( 'TI_CYPRESS_TESTING' ) ) {
80 + $this->load_cypress_hooks();
81 + }
82 +
71 83 }
72 84
73 85 /**
86 + * Define the hooks that are needed for cypress.
87 + *
88 + * @since 3.4.0
89 + * @access private
90 + */
91 + private function load_cypress_hooks() {
92 + // all charts should load on the same page without pagination.
93 + add_filter(
94 + 'visualizer_query_args', function( $args ) {
95 + $args['posts_per_page'] = 20;
96 + return $args;
97 + }, 10, 1
98 + );
99 + }
100 +
101 + /**
102 + * Add disabled `optgroup` schedules to the drop downs.
103 + *
104 + * @since ?
105 + *
106 + * @access public
107 + *
108 + * @param string $feature The feature for which to add schedules.
109 + * @param int $chart_id The chart ID.
110 + * @param int $plan The plan number.
111 + */
112 + public function addSplChartSchedules( $feature, $chart_id, $plan ) {
113 + if ( apply_filters( 'visualizer_is_business', false ) ) {
114 + return;
115 + }
116 +
117 + $license = __( 'PRO', 'visualizer' );
118 + if ( Visualizer_Module::is_pro() ) {
119 + switch ( $plan ) {
120 + case 1:
121 + $license = __( 'Developer', 'visualizer' );
122 + break;
123 + }
124 + }
125 +
126 + $hours = array(
127 + '0' => __( 'Live', 'visualizer' ),
128 + '1' => __( 'Each hour', 'visualizer' ),
129 + '12' => __( 'Each 12 hours', 'visualizer' ),
130 + '24' => __( 'Each day', 'visualizer' ),
131 + '72' => __( 'Each 3 days', 'visualizer' ),
132 + );
133 +
134 + switch ( $feature ) {
135 + case 'json':
136 + case 'csv':
137 + // no more schedules if pro is already active.
138 + if ( Visualizer_Module::is_pro() ) {
139 + return;
140 + }
141 + break;
142 + case 'wp':
143 + // fall-through.
144 + case 'db':
145 + break;
146 + default:
147 + return;
148 + }
149 +
150 + echo '<optgroup disabled label="' . sprintf( __( 'More in the %s version', 'visualizer' ), $license ) . '">';
151 + foreach ( $hours as $hour => $desc ) {
152 + echo '<option disabled>' . $desc . '</option>';
153 + }
154 + echo '</optgroup>';
155 + }
156 +
157 + /**
74 158 * No limits on revisions.
75 159 */
76 160 public function limitRevisions( $num, $post ) {
77 161 if ( Visualizer_Plugin::CPT_VISUALIZER === $post->post_type ) {
@@ -132,16 +216,31 @@
132 216 *
133 217 * @access public
134 218 */
135 219 public function init() {
220 + // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
136 221 if ( current_user_can( 'edit_posts' ) && current_user_can( 'edit_pages' ) && 'true' == get_user_option( 'rich_editing' ) ) {
137 222 $this->_addFilter( 'mce_external_languages', 'add_tinymce_lang', 10, 1 );
138 223 $this->_addFilter( 'mce_external_plugins', 'tinymce_plugin', 10, 1 );
139 224 $this->_addFilter( 'mce_buttons', 'register_mce_button', 10, 1 );
225 + $this->_addFilter( 'tiny_mce_before_init', 'get_strings_for_block', 10, 1 );
140 226 }
141 227 }
142 228
143 229 /**
230 + * Add the strings required for the TinyMCE buttons for the classic block (not the classic editor).
231 + *
232 + * @since ?
233 + * @access friendly
234 + */
235 + function get_strings_for_block( $settings ) {
236 + $class = new Visualizer_Module_Language();
237 + $strings = $class->get_strings();
238 + $array = array( 'visualizer_tinymce_plugin' => json_encode( $strings ) );
239 + return array_merge( $settings, $array );
240 + }
241 +
242 + /**
144 243 * Load plugin translation for - TinyMCE API
145 244 *
146 245 * @access public
147 246 * @param array $arr The tinymce_lang array.
@@ -214,10 +313,12 @@
214 313 if ( post_type_supports( $typenow, 'editor' ) ) {
215 314 wp_enqueue_style( 'visualizer-media', VISUALIZER_ABSURL . 'css/media.css', array( 'media-views' ), Visualizer_Plugin::VERSION );
216 315
217 316 // Load all the assets for the different libraries we support.
218 - $deps = Visualizer_Render_Sidebar_Google::enqueue_assets( array( 'media-editor' ) );
219 - $deps += Visualizer_Render_Sidebar_Type_DataTable::enqueue_assets( array( 'media-editor' ) );
317 + $deps = array(
318 + Visualizer_Render_Sidebar_Google::enqueue_assets( array( 'media-editor' ) ),
319 + Visualizer_Render_Sidebar_Type_DataTable_Tabular::enqueue_assets( array( 'media-editor' ) ),
320 + );
220 321
221 322 wp_enqueue_script( 'visualizer-media-model', VISUALIZER_ABSURL . 'js/media/model.js', $deps, Visualizer_Plugin::VERSION, true );
222 323 wp_enqueue_script( 'visualizer-media-collection', VISUALIZER_ABSURL . 'js/media/collection.js', array( 'visualizer-media-model' ), Visualizer_Plugin::VERSION, true );
223 324 wp_enqueue_script( 'visualizer-media-controller', VISUALIZER_ABSURL . 'js/media/controller.js', array( 'visualizer-media-collection' ), Visualizer_Plugin::VERSION, true );
@@ -265,9 +366,9 @@
265 366 'filters' => $chart_types,
266 367 'types' => array_keys( $chart_types ),
267 368 ),
268 369 'nonce' => wp_create_nonce(),
269 - 'buildurl' => add_query_arg( 'action', Visualizer_Plugin::ACTION_CREATE_CHART, admin_url( 'admin-ajax.php' ) ),
370 + 'buildurl' => esc_url( add_query_arg( 'action', Visualizer_Plugin::ACTION_CREATE_CHART, admin_url( 'admin-ajax.php' ) ) ),
270 371 );
271 372
272 373 return $strings;
273 374 }
@@ -289,64 +390,91 @@
289 390 'enabled' => true,
290 391 );
291 392 }
292 393
394 + $enabled = self::proFeaturesLocked();
395 +
293 396 $types = array_merge(
294 397 $additional,
295 398 array(
296 - 'dataTable' => array(
297 - 'name' => esc_html__( 'Table (New)', 'visualizer' ),
399 + 'tabular' => array(
400 + 'name' => esc_html__( 'Table', 'visualizer' ),
298 401 'enabled' => true,
402 + 'supports' => $enabled ? array( 'Google Charts', 'DataTable' ) : array( 'DataTable' ),
299 403 ),
300 404 'pie' => array(
301 - 'name' => esc_html__( 'Pie', 'visualizer' ),
405 + 'name' => esc_html__( 'Pie/Donut', 'visualizer' ),
302 406 'enabled' => true,
407 + 'supports' => $enabled ? array( 'Google Charts', 'ChartJS' ) : array( 'Google Charts' ),
303 408 ),
304 409 'line' => array(
305 410 'name' => esc_html__( 'Line', 'visualizer' ),
306 411 'enabled' => true,
412 + 'supports' => $enabled ? array( 'Google Charts', 'ChartJS' ) : array( 'Google Charts' ),
307 413 ),
414 + 'bar' => array(
415 + 'name' => esc_html__( 'Bar', 'visualizer' ),
416 + 'enabled' => true,
417 + 'supports' => $enabled ? array( 'Google Charts', 'ChartJS' ) : array( 'Google Charts' ),
418 + ),
308 419 'area' => array(
309 420 'name' => esc_html__( 'Area', 'visualizer' ),
310 - 'enabled' => true,
421 + 'enabled' => $enabled,
422 + // in ChartJS, the fill option is used to make Line chart an area: https://www.chartjs.org/docs/latest/charts/area.html
423 + 'supports' => array( 'Google Charts' ),
311 424 ),
312 425 'geo' => array(
313 426 'name' => esc_html__( 'Geo', 'visualizer' ),
314 - 'enabled' => true,
427 + 'enabled' => $enabled,
428 + 'supports' => array( 'Google Charts' ),
315 429 ),
316 - 'bar' => array(
317 - 'name' => esc_html__( 'Bar', 'visualizer' ),
318 - 'enabled' => true,
319 - ),
320 430 'column' => array(
321 431 'name' => esc_html__( 'Column', 'visualizer' ),
322 - 'enabled' => true,
432 + 'enabled' => $enabled,
433 + 'supports' => array( 'Google Charts', 'ChartJS' ),
323 434 ),
435 + 'bubble' => array(
436 + 'name' => esc_html__( 'Bubble', 'visualizer' ),
437 + 'enabled' => $enabled,
438 + // chartjs' bubble is ugly looking (and it won't work off the default bubble.csv) so it is being excluded for the time being.
439 + 'supports' => array( 'Google Charts' ),
440 + ),
324 441 'scatter' => array(
325 442 'name' => esc_html__( 'Scatter', 'visualizer' ),
326 - 'enabled' => true,
443 + 'enabled' => $enabled,
444 + 'supports' => array( 'Google Charts' ),
327 445 ),
328 446 'gauge' => array(
329 447 'name' => esc_html__( 'Gauge', 'visualizer' ),
330 - 'enabled' => true,
448 + 'enabled' => $enabled,
449 + 'supports' => array( 'Google Charts' ),
331 450 ),
332 451 'candlestick' => array(
333 452 'name' => esc_html__( 'Candlestick', 'visualizer' ),
334 - 'enabled' => true,
453 + 'enabled' => $enabled,
454 + 'supports' => array( 'Google Charts' ),
335 455 ),
336 456 // pro types
337 - 'table' => array(
338 - 'name' => esc_html__( 'Table (Deprecated)', 'visualizer' ),
339 - 'enabled' => false,
340 - ),
341 457 'timeline' => array(
342 458 'name' => esc_html__( 'Timeline', 'visualizer' ),
343 459 'enabled' => false,
460 + 'supports' => array( 'Google Charts', 'ChartJS' ),
344 461 ),
345 462 'combo' => array(
346 463 'name' => esc_html__( 'Combo', 'visualizer' ),
347 464 'enabled' => false,
465 + 'supports' => array( 'Google Charts' ),
348 466 ),
467 + 'polarArea' => array(
468 + 'name' => esc_html__( 'Polar Area', 'visualizer' ),
469 + 'enabled' => false,
470 + 'supports' => array( 'ChartJS' ),
471 + ),
472 + 'radar' => array(
473 + 'name' => esc_html__( 'Radar/Spider', 'visualizer' ),
474 + 'enabled' => false,
475 + 'supports' => array( 'ChartJS' ),
476 + ),
349 477 )
350 478 );
351 479 $types = apply_filters( 'visualizer_pro_chart_types', $types );
352 480 if ( $enabledOnly ) {
@@ -355,8 +483,12 @@
355 483 if ( ! is_array( $array ) ) {
356 484 // support for old pro
357 485 $array = array( 'enabled' => true, 'name' => $array );
358 486 }
487 + // backward compatibility for PRO before v1.9.0
488 + if ( ! array_key_exists( 'supports', $array ) ) {
489 + $array['supports'] = array( 'Google Charts' );
490 + }
359 491 if ( ! $array['enabled'] ) {
360 492 continue;
361 493 }
362 494 $filtered[ $type ] = $array;
@@ -369,8 +501,12 @@
369 501 if ( ! is_array( $array ) ) {
370 502 // support for old pro
371 503 $array = array( 'enabled' => true, 'name' => $array );
372 504 }
505 + // backward compatibility for PRO before v1.9.0
506 + if ( ! array_key_exists( 'supports', $array ) ) {
507 + $array['supports'] = array( 'Google Charts' );
508 + }
373 509 $doubleD[ $type ] = $array['name'];
374 510 }
375 511 $types = $doubleD;
376 512 }
@@ -384,21 +520,13 @@
384 520 private static function handleDeprecatedCharts( $types, $enabledOnly, $get2Darray, $where ) {
385 521 $deprecated = array();
386 522
387 523 switch ( $where ) {
524 + case 'types':
525 + // fall-through
388 526 case 'library':
389 - // if the user has a Google Table chart, show it as deprecated otherwise remove the option from the library.
390 - if ( ! self::hasChartType( 'table' ) ) {
391 - $deprecated[] = 'table';
392 - if ( $get2Darray ) {
393 - $types['dataTable'] = esc_html__( 'Table', 'visualizer' );
394 - } else {
395 - $types['dataTable']['name'] = esc_html__( 'Table', 'visualizer' );
396 - }
397 - }
398 -
399 527 // if a user has a Gauge/Candlestick chart, then let them keep using it.
400 - if ( ! VISUALIZER_PRO ) {
528 + if ( ! Visualizer_Module::is_pro() ) {
401 529 if ( ! self::hasChartType( 'gauge' ) ) {
402 530 if ( $get2Darray ) {
403 531 $deprecated[] = 'gauge';
404 532 } else {
@@ -414,20 +542,10 @@
414 542 }
415 543 }
416 544 break;
417 545 default:
418 - // remove the option to create a Google Table chart.
419 - $deprecated[] = 'table';
420 -
421 - // rename the new table chart type.
422 - if ( $get2Darray ) {
423 - $types['dataTable'] = esc_html__( 'Table', 'visualizer' );
424 - } else {
425 - $types['dataTable']['name'] = esc_html__( 'Table', 'visualizer' );
426 - }
427 -
428 546 // if a user has a Gauge/Candlestick chart, then let them keep using it.
429 - if ( ! VISUALIZER_PRO ) {
547 + if ( ! Visualizer_Module::is_pro() ) {
430 548 if ( ! self::hasChartType( 'gauge' ) ) {
431 549 if ( $get2Darray ) {
432 550 $deprecated[] = 'gauge';
433 551 } else {
@@ -462,9 +580,9 @@
462 580 * @access public
463 581 */
464 582 public function renderTemplates() {
465 583 global $pagenow;
466 - if ( 'post.php' != $pagenow && 'post-new.php' != $pagenow ) {
584 + if ( 'post.php' !== $pagenow && 'post-new.php' !== $pagenow ) {
467 585 return;
468 586 }
469 587 $render = new Visualizer_Render_Templates();
470 588 $render->render();
@@ -482,9 +600,9 @@
482 600 *
483 601 * @param string $suffix The current page suffix.
484 602 */
485 603 public function enqueueLibraryScripts( $suffix ) {
486 - if ( $suffix == $this->_libraryPage ) {
604 + if ( $suffix === $this->_libraryPage ) {
487 605 wp_enqueue_style( 'visualizer-library', VISUALIZER_ABSURL . 'css/library.css', array(), Visualizer_Plugin::VERSION );
488 606 $this->_addFilter( 'media_upload_tabs', 'setupVisualizerTab' );
489 607 wp_enqueue_media();
490 608 wp_enqueue_script(
@@ -492,8 +610,9 @@
492 610 VISUALIZER_ABSURL . 'js/library.js',
493 611 array(
494 612 'jquery',
495 613 'media-views',
614 + 'clipboard',
496 615 ),
497 616 Visualizer_Plugin::VERSION,
498 617 true
499 618 );
@@ -542,14 +661,184 @@
542 661 *
543 662 * @access public
544 663 */
545 664 public function registerAdminMenu() {
546 - $title = esc_html__( 'Visualizer Library', 'visualizer' );
547 - $callback = array( $this, 'renderLibraryPage' );
548 - $this->_libraryPage = add_submenu_page( 'upload.php', $title, $title, 'edit_posts', Visualizer_Plugin::NAME, $callback );
665 + $svg_base64_icon = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iNzdweCIgaGVpZ2h0PSI3N3B4IiB2aWV3Qm94PSIwIDAgNzcgNzciIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICA8IS0tIEdlbmVyYXRvcjogU2tldGNoIDUyLjYgKDY3NDkxKSAtIGh0dHA6Ly93d3cuYm9oZW1pYW5jb2RpbmcuY29tL3NrZXRjaCAtLT4KICAgIDx0aXRsZT5Db21iaW5lZCBTaGFwZTwvdGl0bGU+CiAgICA8ZGVzYz5DcmVhdGVkIHdpdGggU2tldGNoLjwvZGVzYz4KICAgIDxnIGlkPSJQcm9kdWN0LVBhZ2UiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPgogICAgICAgIDxnIGlkPSJXb3JkUHJlc3MtcGx1Z2lucyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTE5MC4wMDAwMDAsIC00MzUuMDAwMDAwKSIgZmlsbD0iIzM5QzNEMiI+CiAgICAgICAgICAgIDxwYXRoIGQ9Ik0yMjguNSw1MTIgQzIwNy4yMzcwMzcsNTEyIDE5MCw0OTQuNzYyOTYzIDE5MCw0NzMuNSBDMTkwLDQ1Mi4yMzcwMzcgMjA3LjIzNzAzNyw0MzUgMjI4LjUsNDM1IEMyNDkuNzYyOTYzLDQzNSAyNjcsNDUyLjIzNzAzNyAyNjcsNDczLjUgQzI2Nyw0OTQuNzYyOTYzIDI0OS43NjI5NjMsNTEyIDIyOC41LDUxMiBaIE0yNDYuODQzNzUsNDgzLjU5MjA1OSBMMjE1LjYyNSw0ODMuNTkyMDU5IEwyMTUuNjI1LDQ2MC44MjY1NDQgQzIxNS42MjUsNDYwLjE2NDU0NyAyMTUuMTA3NTc4LDQ1OS42MjgzNTkgMjE0LjQ2ODc1LDQ1OS42MjgzNTkgTDIxMi4xNTYyNSw0NTkuNjI4MzU5IEMyMTEuNTE3NDIyLDQ1OS42MjgzNTkgMjExLDQ2MC4xNjQ1NDcgMjExLDQ2MC44MjY1NDQgTDIxMSw0ODUuOTg4NDI5IEMyMTEsNDg3LjMxMTY3NCAyMTIuMDM1NTY2LDQ4OC4zODQ3OTggMjEzLjMxMjUsNDg4LjM4NDc5OCBMMjQ2Ljg0Mzc1LDQ4OC4zODQ3OTggQzI0Ny40ODI1NzgsNDg4LjM4NDc5OCAyNDgsNDg3Ljg0ODYxMSAyNDgsNDg3LjE4NjYxMyBMMjQ4LDQ4NC43OTAyNDQgQzI0OCw0ODQuMTI4MjQ2IDI0Ny40ODI1NzgsNDgzLjU5MjA1OSAyNDYuODQzNzUsNDgzLjU5MjA1OSBaIE0yNDQuNTMxMjUsNDYyLjAyNDcyOSBMMjM1Ljk5OTU3LDQ2Mi4wMjQ3MjkgQzIzNC40NTQ1MzEsNDYyLjAyNDcyOSAyMzMuNjgwNTY2LDQ2My45NjA1NDcgMjM0Ljc3MzIyMyw0NjUuMDkyODMyIEwyMzcuMTE0NjI5LDQ2Ny41MTkxNTYgTDIzMS44MTI1LDQ3My4wMTQzMzIgTDIyNi41MTAzNzEsNDY3LjUxOTkwNSBDMjI1LjYwNzA1MSw0NjYuNTgzODIzIDIyNC4xNDI5NDksNDY2LjU4MzgyMyAyMjMuMjQwMzUyLDQ2Ny41MTk5MDUgTDIxOC4yNzY0MjYsNDcyLjY2Mzg2MyBDMjE3LjgyNDc2Niw0NzMuMTMxOTA0IDIxNy44MjQ3NjYsNDczLjg5MDUwNSAyMTguMjc2NDI2LDQ3NC4zNTg1NDYgTDIxOS45MTEwNzQsNDc2LjA1MjQ4IEMyMjAuMzYyNzM0LDQ3Ni41MjA1MjEgMjIxLjA5NDc4NSw0NzYuNTIwNTIxIDIyMS41NDY0NDUsNDc2LjA1MjQ4IEwyMjQuODc1LDQ3Mi42MDI0NTYgTDIzMC4xNzcxMjksNDc4LjA5Njg4MyBDMjMxLjA4MDQ0OSw0NzkuMDMyOTY1IDIzMi41NDQ1NTEsNDc5LjAzMjk2NSAyMzMuNDQ3MTQ4LDQ3OC4wOTY4ODMgTDI0MC4zODQ2NDgsNDcwLjkwNzc3MyBMMjQyLjcyNjA1NSw0NzMuMzM0MDk4IEMyNDMuODE4NzExLDQ3NC40NjYzODIgMjQ1LjY4Njc3Nyw0NzMuNjY0MzQ3IDI0NS42ODY3NzcsNDcyLjA2MzI3MyBMMjQ1LjY4Njc3Nyw0NjMuMjIyOTE0IEMyNDUuNjg3NSw0NjIuNTYwOTE3IDI0NS4xNzAwNzgsNDYyLjAyNDcyOSAyNDQuNTMxMjUsNDYyLjAyNDcyOSBaIiBpZD0iQ29tYmluZWQtU2hhcGUiPjwvcGF0aD4KICAgICAgICA8L2c+CiAgICA8L2c+Cjwvc3ZnPg==';
666 +
667 + $this->_libraryPage = add_menu_page( __( 'Visualizer', 'visualizer' ), __( 'Visualizer', 'visualizer' ), 'edit_posts', Visualizer_Plugin::NAME, array( $this, 'renderLibraryPage' ), $svg_base64_icon, 99.7666 );
668 +
669 + add_submenu_page(
670 + Visualizer_Plugin::NAME,
671 + __( 'Chart Library', 'visualizer' ),
672 + __( 'Chart Library', 'visualizer' ),
673 + 'edit_posts',
674 + admin_url( 'admin.php?page=' . Visualizer_Plugin::NAME )
675 + );
676 + add_submenu_page(
677 + Visualizer_Plugin::NAME,
678 + __( 'Add New Chart', 'visualizer' ),
679 + __( 'Add New Chart', 'visualizer' ),
680 + 'edit_posts',
681 + admin_url( 'admin.php?page=' . Visualizer_Plugin::NAME . '&vaction=addnew' )
682 + );
683 + add_submenu_page(
684 + Visualizer_Plugin::NAME,
685 + __( 'Support', 'visualizer' ),
686 + __( 'Support', 'visualizer' ) . '<span class="dashicons dashicons-editor-help more-features-icon" style="width: 17px; height: 17px; margin-left: 4px; color: #ffca54; font-size: 17px; vertical-align: -3px;"></span>',
687 + 'edit_posts',
688 + 'viz-support',
689 + array( $this, 'renderSupportPage' )
690 + );
691 +
692 + if ( ! Visualizer_Module::is_pro() ) {
693 + add_submenu_page(
694 + Visualizer_Plugin::NAME,
695 + __( 'Get Visualizer Pro', 'visualizer' ),
696 + __( 'Get Visualizer Pro', 'visualizer' ),
697 + 'edit_posts',
698 + 'viz-get-pro',
699 + '__return_null'
700 + );
701 + add_action( 'admin_footer', array( $this, 'handleGetProSubMenu' ) );
702 + }
703 + remove_submenu_page( Visualizer_Plugin::NAME, Visualizer_Plugin::NAME );
704 +
705 + add_action( "load-{$this->_libraryPage}", array( $this, 'addScreenOptions' ) );
549 706 }
550 707
551 708 /**
709 + * Handle get pro plugin submenu.
710 + */
711 + public function handleGetProSubMenu() {
712 + ?>
713 + <style type="text/css">
714 + #toplevel_page_visualizer ul.wp-submenu li.wp-first-item + li + li + li {
715 + background: #FF7E65;
716 + font-size: 14px;
717 + font-weight: 600;
718 + color: #fff;
719 + }
720 + #toplevel_page_visualizer ul.wp-submenu li.wp-first-item + li + li + li > a {
721 + color: #fff !important;
722 + }
723 + #toplevel_page_visualizer ul.wp-submenu li.wp-first-item + li + li + li > a:hover {
724 + box-shadow: inherit;
725 + }
726 + </style>
727 + <script type="text/javascript">
728 + jQuery( document ).ready( function() {
729 + jQuery( '#toplevel_page_visualizer' ).on( 'click', 'li:not(.wp-submenu-head, .wp-first-item):eq(2)', function( e ) {
730 + e.preventDefault();
731 + window.open( '<?php echo tsdk_utmify( 'https://themeisle.com/plugins/visualizer-charts-and-graphs/upgrade/', 'toplevel' ); ?>', '_blank' );
732 + } );
733 + } );
734 + </script>
735 + <?php
736 + }
737 +
738 + /**
739 + * Adds the screen options for pagination.
740 + */
741 + function addScreenOptions() {
742 + $screen = get_current_screen();
743 +
744 + // bail if it's some other page.
745 + if ( ! is_object( $screen ) || $screen->id !== $this->_libraryPage ) {
746 + return;
747 + }
748 +
749 + $args = array(
750 + 'label' => __( 'Number of charts per page:', 'visualizer' ),
751 + 'default' => 6,
752 + 'option' => 'visualizer_library_per_page',
753 + );
754 + add_screen_option( 'per_page', $args );
755 + }
756 +
757 + /**
758 + * Returns the screen option for pagination.
759 + */
760 + function setScreenOptions( $status, $option, $value ) {
761 + if ( 'visualizer_library_per_page' === $option ) {
762 + return $value;
763 + }
764 + }
765 +
766 + /**
767 + * Adds the display filters to be used in the meta_query while displaying the charts.
768 + */
769 + private function getDisplayFilters( &$query_args ) {
770 + $query = array();
771 + global $sitepress;
772 + if ( Visualizer_Module::is_pro() && ( function_exists( 'icl_get_languages' ) && $sitepress instanceof \SitePress ) ) {
773 + $current_lang = icl_get_current_language();
774 + if ( in_array( $current_lang, array( 'all', icl_get_default_language() ), true ) ) {
775 + $query[] = array(
776 + 'key' => 'chart_lang',
777 + 'compare' => 'NOT EXISTS',
778 + );
779 + } else {
780 + $query[] = array(
781 + 'key' => 'chart_lang',
782 + 'value' => $current_lang,
783 + 'compare' => '=',
784 + );
785 + }
786 + }
787 +
788 + // add chart type filter to the query arguments
789 + $type = filter_input( INPUT_GET, 'type' );
790 + if ( $type && in_array( $type, Visualizer_Plugin::getChartTypes(), true ) ) {
791 + $query[] = array(
792 + 'key' => Visualizer_Plugin::CF_CHART_TYPE,
793 + 'value' => $type,
794 + 'compare' => '=',
795 + );
796 + }
797 +
798 + // add chart library filter to the query arguments
799 + $library = filter_input( INPUT_GET, 'library' );
800 + if ( $library ) {
801 + $query[] = array(
802 + 'key' => Visualizer_Plugin::CF_CHART_LIBRARY,
803 + 'value' => $library,
804 + 'compare' => '=',
805 + );
806 + }
807 +
808 + // add date filter to the query arguments
809 + $date = filter_input( INPUT_GET, 'date' );
810 + $possible = array_keys( Visualizer_Plugin::getSupportedDateFilter() );
811 + if ( $date && in_array( $date, $possible, true ) ) {
812 + $query_args['date_query'] = array(
813 + 'after' => "$date -1 day",
814 + 'inclusive' => true,
815 + );
816 + }
817 +
818 + // add source filter to the query arguments
819 + $source = filter_input( INPUT_GET, 'source' );
820 + if ( $source ) {
821 + $source = ucwords( $source );
822 + $source = "Visualizer_Source_{$source}";
823 + $query[] = array(
824 + 'key' => Visualizer_Plugin::CF_SOURCE,
825 + 'value' => $source,
826 + 'compare' => '=',
827 + );
828 + }
829 +
830 + $query_args['meta_query'] = $query;
831 +
832 + $orderby = filter_input( INPUT_GET, 'orderby' );
833 + $order = filter_input( INPUT_GET, 'order' );
834 + if ( $orderby ) {
835 + $query_args['order_by'] = $orderby;
836 + }
837 + $query_args['order'] = empty( $order ) ? 'desc' : $order;
838 + }
839 +
840 + /**
552 841 * Get the instance of WP_Query that fetches the charts as per the given criteria.
553 842 */
554 843 private function getQuery() {
555 844 static $q;
@@ -568,27 +857,32 @@
568 857 'default' => 1,
569 858 ),
570 859 )
571 860 );
861 +
862 + $per_page = 6;
863 + $screen = get_current_screen();
864 + if ( $screen ) {
865 + // retrieve the per_page option
866 + $screen_option = $screen->get_option( 'per_page', 'option' );
867 + // retrieve the value stored for the current user
868 + $user = get_current_user_id();
869 + $per_page = get_user_meta( $user, $screen_option, true );
870 + if ( empty( $per_page ) || $per_page < 1 ) {
871 + // nothing set, get the default value
872 + $per_page = $screen->get_option( 'per_page', 'default' );
873 + }
874 + }
875 +
572 876 // the initial query arguments to fetch charts
573 877 $query_args = array(
574 878 'post_type' => Visualizer_Plugin::CPT_VISUALIZER,
575 - 'posts_per_page' => 6,
879 + 'posts_per_page' => $per_page,
576 880 'paged' => $page,
577 881 );
578 - // add chart type filter to the query arguments
579 - $filter = filter_input( INPUT_GET, 'type' );
580 - if ( $filter && in_array( $filter, Visualizer_Plugin::getChartTypes() ) ) {
581 - $query_args['meta_query'] = array(
582 - array(
583 - 'key' => Visualizer_Plugin::CF_CHART_TYPE,
584 - 'value' => $filter,
585 - 'compare' => '=',
586 - ),
587 - );
588 - } else {
589 - $filter = 'all';
590 - }
882 +
883 + $this->getDisplayFilters( $query_args );
884 +
591 885 // Added by Ash/Upwork
592 886 $filterByMeta = filter_input( INPUT_GET, 's', FILTER_SANITIZE_STRING );
593 887 if ( $filterByMeta ) {
594 888 $query = array(
@@ -599,13 +893,25 @@
599 893 $meta = isset( $query_args['meta_query'] ) ? $query_args['meta_query'] : array();
600 894 $meta[] = $query;
601 895 $query_args['meta_query'] = $meta;
602 896 }
603 - $q = new WP_Query( $query_args );
897 + $q = new WP_Query( apply_filters( 'visualizer_query_args', $query_args ) );
604 898 return $q;
605 899 }
606 900
607 901 /**
902 + * Renders support page.
903 + *
904 + * @since 3.3.0
905 + *
906 + * @access public
907 + */
908 + public function renderSupportPage() {
909 + wp_enqueue_style( 'visualizer-upsell', VISUALIZER_ABSURL . 'css/upsell.css', array(), Visualizer_Plugin::VERSION );
910 + include_once VISUALIZER_ABSPATH . '/templates/support.php';
911 + }
912 +
913 + /**
608 914 * Renders visualizer library page.
609 915 *
610 916 * @since 1.0.0
611 917 *
@@ -628,9 +934,9 @@
628 934 )
629 935 );
630 936 // add chart type filter to the query arguments
631 937 $filter = filter_input( INPUT_GET, 'type' );
632 - if ( ! ( $filter && in_array( $filter, Visualizer_Plugin::getChartTypes() ) ) ) {
938 + if ( ! ( $filter && in_array( $filter, Visualizer_Plugin::getChartTypes(), true ) ) ) {
633 939 $filter = 'all';
634 940 }
635 941
636 942 $css = '';
@@ -651,12 +957,27 @@
651 957 if ( ! empty( $atts['settings'] ) ) {
652 958 $settings = apply_filters( $atts['settings'], $settings, $chart->ID, $type );
653 959 }
654 960
655 - unset( $settings['height'], $settings['width'] );
961 + if ( $settings ) {
962 + unset( $settings['height'], $settings['width'], $settings['chartArea'] );
963 + }
964 +
656 965 $series = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_SERIES, get_post_meta( $chart->ID, Visualizer_Plugin::CF_SERIES, true ), $chart->ID, $type );
657 - $data = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_DATA, unserialize( html_entity_decode( $chart->post_content ) ), $chart->ID, $type );
966 + $data = self::get_chart_data( $chart, $type );
658 967
968 + // Set default setting series when add manual chart data - Only during first creation.
969 + if ( isset( $settings['series'] ) && ! empty( $series ) ) {
970 + $count_series = count( $series ) - count( $settings['series'] );
971 + if ( $count_series > 1 ) {
972 + $clone_last_series = end( $settings['series'] );
973 + $clone_last_series = array_fill_keys( array_keys( $clone_last_series ), '' );
974 + foreach ( range( 1, $count_series ) as $item ) {
975 + $settings['series'][] = $clone_last_series;
976 + }
977 + }
978 + }
979 +
659 980 $library = $this->load_chart_type( $chart->ID );
660 981
661 982 $id = 'visualizer-' . $chart->ID;
662 983 $arguments = $this->get_inline_custom_css( $id, $settings );
@@ -664,8 +985,15 @@
664 985 $css .= $arguments[0];
665 986 $settings = $arguments[1];
666 987 }
667 988
989 + if ( isset( $settings['controls']['ui']['labelStacking'] ) ) {
990 + unset( $settings['controls']['ui']['labelStacking'] );
991 + }
992 + if ( isset( $settings['controls']['ui']['orientation'] ) ) {
993 + unset( $settings['controls']['ui']['orientation'] );
994 + }
995 +
668 996 // add chart to the array
669 997 $charts[ $id ] = array(
670 998 'id' => $chart->ID,
671 999 'type' => $type,
@@ -684,26 +1012,38 @@
684 1012 'language' => $this->get_language(),
685 1013 'map_api_key' => get_option( 'visualizer-map-api-key' ),
686 1014 'charts' => $charts,
687 1015 'urls' => array(
688 - 'base' => add_query_arg( 'vpage', false ),
689 - 'create' => add_query_arg(
690 - array(
691 - 'action' => Visualizer_Plugin::ACTION_CREATE_CHART,
692 - 'library' => 'yes',
693 - 'type' => isset( $_GET['type'] ) ? $_GET['type'] : '',
694 - ),
695 - $ajaxurl
1016 + 'base' => esc_url( add_query_arg( array( 'vpage' => false, 'vaction' => false ) ) ),
1017 + 'create' => esc_url(
1018 + add_query_arg(
1019 + array(
1020 + 'action' => Visualizer_Plugin::ACTION_CREATE_CHART,
1021 + 'library' => 'yes',
1022 + 'type' => isset( $_GET['type'] ) ? $_GET['type'] : '',
1023 + 'chart-library' => isset( $_GET['chart-library'] ) ? $_GET['chart-library'] : '',
1024 + 'vaction' => false,
1025 + ),
1026 + $ajaxurl
1027 + )
696 1028 ),
697 - 'edit' => add_query_arg(
698 - array(
699 - 'action' => Visualizer_Plugin::ACTION_EDIT_CHART,
700 - 'library' => 'yes',
701 - ),
702 - $ajaxurl
1029 + 'edit' => esc_url(
1030 + add_query_arg(
1031 + array(
1032 + 'action' => Visualizer_Plugin::ACTION_EDIT_CHART,
1033 + 'library' => 'yes',
1034 + 'vaction' => false,
1035 + ),
1036 + $ajaxurl
1037 + )
703 1038 ),
704 1039 ),
705 1040 'page_type' => 'library',
1041 + 'is_front' => false,
1042 + 'i10n' => array(
1043 + 'copied' => __( 'The shortcode has been copied to your clipboard. Hit Ctrl-V/Cmd-V to paste it.', 'visualizer' ),
1044 + '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' ),
1045 + ),
706 1046 )
707 1047 );
708 1048 // render library page
709 1049 $render = new Visualizer_Render_Library();
@@ -712,9 +1052,9 @@
712 1052 $render->types = self::_getChartTypesLocalized( false, false, false, true );
713 1053 $render->custom_css = $css;
714 1054 $render->pagination = paginate_links(
715 1055 array(
716 - 'base' => add_query_arg( 'vpage', '%#%' ),
1056 + 'base' => add_query_arg( array( 'vpage' => '%#%', 'vaction' => false ) ),
717 1057 'format' => '',
718 1058 'current' => $page,
719 1059 'total' => $query->max_num_pages,
720 1060 'type' => 'array',
@@ -735,14 +1075,14 @@
735 1075 *
736 1076 * @return array Updated array of action links.
737 1077 */
738 1078 public function getPluginActionLinks( $links, $file ) {
739 - if ( $file == plugin_basename( VISUALIZER_BASEFILE ) ) {
1079 + if ( $file === plugin_basename( VISUALIZER_BASEFILE ) ) {
740 1080 array_unshift(
741 1081 $links,
742 1082 sprintf(
743 1083 '<a href="%s">%s</a>',
744 - admin_url( 'upload.php?page=' . Visualizer_Plugin::NAME ),
1084 + admin_url( 'admin.php?page=' . Visualizer_Plugin::NAME ),
745 1085 esc_html__( 'Library', 'visualizer' )
746 1086 )
747 1087 );
748 1088 }
@@ -762,17 +1102,17 @@
762 1102 *
763 1103 * @return array Updated array of plugin meta links.
764 1104 */
765 1105 public function getPluginMetaLinks( $plugin_meta, $plugin_file ) {
766 - if ( $plugin_file == plugin_basename( VISUALIZER_BASEFILE ) ) {
1106 + if ( $plugin_file === plugin_basename( VISUALIZER_BASEFILE ) ) {
767 1107 // knowledge base link
768 1108 $plugin_meta[] = sprintf(
769 - '<a href="https://github.com/codeinwp/visualizer/wiki" target="_blank">%s</a>',
770 - esc_html__( 'Knowledge Base', 'visualizer' )
1109 + '<a href="' . VISUALIZER_MAIN_DOC . '" target="_blank">%s</a>',
1110 + esc_html__( 'Docs', 'visualizer' )
771 1111 );
772 1112 // flattr link
773 1113 $plugin_meta[] = sprintf(
774 - '<a style="color:red" href="https://themeisle.com/plugins/visualizer-charts-and-graphs-pro-addon/" target="_blank">%s</a>',
1114 + '<a style="color:red" href="' . tsdk_utmify( Visualizer_Plugin::PRO_TEASER_URL, 'pluginrow' ) . '" target="_blank">%s</a>',
775 1115 esc_html__( 'Pro Addon', 'visualizer' )
776 1116 );
777 1117 }
778 1118
@@ -778,5 +1118,60 @@
778 1118
779 1119 return $plugin_meta;
780 1120 }
781 1121
1122 + /**
1123 + * If check is existing user.
1124 + *
1125 + * @return bool Default false
1126 + */
1127 + public static function proFeaturesLocked() {
1128 + if ( Visualizer_Module::is_pro() ) {
1129 + return true;
1130 + }
1131 + return 'yes' === get_option( 'visualizer-new-user', 'yes' ) ? false : true;
1132 + }
1133 +
1134 + /**
1135 + * Multilingual Support.
1136 + *
1137 + * @param int $chart_id Chart ID.
1138 + * @return bool Default false
1139 + */
1140 + public function addMultilingualSupport( $chart_id ) {
1141 + global $sitepress;
1142 + if ( Visualizer_Module::is_pro() ) {
1143 + return;
1144 + }
1145 + if ( function_exists( 'icl_get_languages' ) && $sitepress instanceof \SitePress ) {
1146 + $language = icl_get_languages();
1147 + $current_lang = icl_get_current_language();
1148 + $default_lang = icl_get_default_language();
1149 + $post_info = wpml_get_language_information( null, $chart_id );
1150 + $translations = array();
1151 + if ( ! empty( $post_info ) && ( $default_lang === $post_info['language_code'] ) ) {
1152 + $trid = $sitepress->get_element_trid( $chart_id, 'post_' . Visualizer_Plugin::CPT_VISUALIZER );
1153 + $translations = $sitepress->get_element_translations( $trid );
1154 + }
1155 + if ( empty( $translations ) ) {
1156 + return;
1157 + }
1158 + ?>
1159 + <hr><div class="visualizer-languages-list only-pro">
1160 + <?php
1161 + foreach ( $language as $lang ) {
1162 + $lang_code = $lang['code'];
1163 + if ( $current_lang !== $lang_code ) {
1164 + ?>
1165 + <a href="javascript:;">
1166 + <img src="<?php echo esc_url( $lang['country_flag_url'] ); ?>" alt="<?php echo esc_attr( $lang['translated_name'] ); ?>">
1167 + </a>
1168 + <?php
1169 + }
1170 + }
1171 + ?>
1172 + <a href="<?php echo tsdk_utmify( Visualizer_Plugin::PRO_TEASER_URL, 'wpml-support', 'visualizer_render_char' ); ?>"target="_blank"><?php esc_html_e( 'Upgrade to PRO to active this translation for charts', 'visualizer' ); ?></a>
1173 + </div>
1174 + <?php
1175 + }
1176 + }
782 1177 }