PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.4.4
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.4.4
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 +580 -67 3.0.63.4.4 View file →
@@ -52,34 +52,193 @@
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 +
68 + // revision support.
69 + $this->_addFilter( 'wp_revisions_to_keep', 'limitRevisions', null, 10, 2 );
70 + $this->_addAction( '_wp_put_post_revision', 'addRevision', null, 10, 1 );
71 + $this->_addAction( 'wp_restore_post_revision', 'restoreRevision', null, 10, 2 );
72 +
73 + $this->_addAction( 'visualizer_chart_schedules_spl', 'addSplChartSchedules', null, 10, 3 );
74 +
65 75 $this->_addAction( 'admin_init', 'init' );
76 +
77 + if ( defined( 'TI_CYPRESS_TESTING' ) ) {
78 + $this->load_cypress_hooks();
79 + }
80 +
66 81 }
67 82
68 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 + /**
156 + * No limits on revisions.
157 + */
158 + public function limitRevisions( $num, $post ) {
159 + if ( Visualizer_Plugin::CPT_VISUALIZER === $post->post_type ) {
160 + return -1;
161 + }
162 + return $num;
163 + }
164 +
165 + /**
166 + * Add a revision.
167 + */
168 + public function addRevision( $revision_id ) {
169 + $parent_id = wp_is_post_revision( $revision_id );
170 + if ( Visualizer_Plugin::CPT_VISUALIZER === get_post_type( $parent_id ) ) {
171 + // add the meta data to this revision.
172 + $meta = get_post_meta( $parent_id, '', true );
173 +
174 + if ( $meta ) {
175 + foreach ( $meta as $key => $value ) {
176 + if ( 0 === strpos( $key, 'visualizer' ) ) {
177 + add_metadata( 'post', $revision_id, $key, maybe_unserialize( $value[0] ) );
178 + }
179 + }
180 + }
181 + }
182 + }
183 +
184 + /**
185 + * Restore a revision.
186 + */
187 + public function restoreRevision( $post_id, $revision_id ) {
188 + if ( Visualizer_Plugin::CPT_VISUALIZER === get_post_type( $post_id ) ) {
189 + // get the meta information from the revision.
190 + $meta = get_metadata( 'post', $revision_id, '', true );
191 +
192 + // delete all meta information from the post before adding.
193 + $post_meta = get_post_meta( $post_id, '', true );
194 + if ( $post_meta ) {
195 + foreach ( $meta as $key => $value ) {
196 + if ( 0 === strpos( $key, 'visualizer' ) ) {
197 + delete_post_meta( $post_id, $key );
198 + }
199 + }
200 + }
201 +
202 + if ( $meta ) {
203 + foreach ( $meta as $key => $value ) {
204 + if ( 0 === strpos( $key, 'visualizer' ) ) {
205 + add_post_meta( $post_id, $key, maybe_unserialize( $value[0] ) );
206 + }
207 + }
208 + }
209 + }
210 + }
211 +
212 + /**
69 213 * Admin init.
70 214 *
71 215 * @access public
72 216 */
73 217 public function init() {
218 + // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
74 219 if ( current_user_can( 'edit_posts' ) && current_user_can( 'edit_pages' ) && 'true' == get_user_option( 'rich_editing' ) ) {
75 220 $this->_addFilter( 'mce_external_languages', 'add_tinymce_lang', 10, 1 );
76 221 $this->_addFilter( 'mce_external_plugins', 'tinymce_plugin', 10, 1 );
77 222 $this->_addFilter( 'mce_buttons', 'register_mce_button', 10, 1 );
223 + $this->_addFilter( 'tiny_mce_before_init', 'get_strings_for_block', 10, 1 );
78 224 }
79 225 }
80 226
81 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 + /**
82 241 * Load plugin translation for - TinyMCE API
83 242 *
84 243 * @access public
85 244 * @param array $arr The tinymce_lang array.
@@ -150,14 +309,28 @@
150 309 public function enqueueMediaScripts() {
151 310 global $typenow;
152 311 if ( post_type_supports( $typenow, 'editor' ) ) {
153 312 wp_enqueue_style( 'visualizer-media', VISUALIZER_ABSURL . 'css/media.css', array( 'media-views' ), Visualizer_Plugin::VERSION );
154 - wp_enqueue_script( 'visualizer-google-jsapi-new', '//www.gstatic.com/charts/loader.js', array( 'media-editor' ), null, true );
155 - wp_enqueue_script( 'visualizer-google-jsapi-old', '//www.google.com/jsapi', array( 'visualizer-google-jsapi-new' ), null, true );
156 - 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_DataTable::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 );
157 321 wp_enqueue_script( 'visualizer-media-collection', VISUALIZER_ABSURL . 'js/media/collection.js', array( 'visualizer-media-model' ), Visualizer_Plugin::VERSION, true );
158 322 wp_enqueue_script( 'visualizer-media-controller', VISUALIZER_ABSURL . 'js/media/controller.js', array( 'visualizer-media-collection' ), Visualizer_Plugin::VERSION, true );
159 323 wp_enqueue_script( 'visualizer-media-view', VISUALIZER_ABSURL . 'js/media/view.js', array( 'visualizer-media-controller' ), Visualizer_Plugin::VERSION, true );
324 + wp_localize_script(
325 + 'visualizer-media-view',
326 + 'visualizer',
327 + array(
328 + 'i10n' => array(
329 + 'insert' => __( 'Insert', 'visualizer' ),
330 + ),
331 + )
332 + );
160 333 wp_enqueue_script( 'visualizer-media-toolbar', VISUALIZER_ABSURL . 'js/media/toolbar.js', array( 'visualizer-media-view' ), Visualizer_Plugin::VERSION, true );
161 334 wp_enqueue_script( 'visualizer-media', VISUALIZER_ABSURL . 'js/media.js', array( 'visualizer-media-toolbar' ), Visualizer_Plugin::VERSION, true );
162 335 }
163 336 }
@@ -206,9 +379,9 @@
206 379 * @static
207 380 * @access private
208 381 * @return array The associated array of chart types with localized names.
209 382 */
210 - 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 ) {
211 384 $additional = array();
212 385 if ( $add_select ) {
213 386 $additional['select'] = array(
214 387 'name' => esc_html__( 'All', 'visualizer' ),
@@ -216,58 +389,93 @@
216 389 );
217 390 }
218 391
219 392 $types = array_merge(
220 - $additional, array(
393 + $additional,
394 + array(
395 + 'dataTable' => array(
396 + 'name' => esc_html__( 'Table', 'visualizer' ),
397 + 'enabled' => true,
398 + 'supports' => array( 'DataTable' ),
399 + ),
221 400 'pie' => array(
222 - 'name' => esc_html__( 'Pie', 'visualizer' ),
401 + 'name' => esc_html__( 'Pie/Donut', 'visualizer' ),
223 402 'enabled' => true,
403 + 'supports' => array( 'Google Charts', 'ChartJS' ),
224 404 ),
225 405 'line' => array(
226 406 'name' => esc_html__( 'Line', 'visualizer' ),
227 407 'enabled' => true,
408 + 'supports' => array( 'Google Charts', 'ChartJS' ),
228 409 ),
229 410 'area' => array(
230 411 'name' => esc_html__( 'Area', 'visualizer' ),
231 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' ),
232 415 ),
233 416 'geo' => array(
234 417 'name' => esc_html__( 'Geo', 'visualizer' ),
235 418 'enabled' => true,
419 + 'supports' => array( 'Google Charts' ),
236 420 ),
237 421 'bar' => array(
238 422 'name' => esc_html__( 'Bar', 'visualizer' ),
239 423 'enabled' => true,
424 + 'supports' => array( 'Google Charts', 'ChartJS' ),
240 425 ),
241 426 'column' => array(
242 427 'name' => esc_html__( 'Column', 'visualizer' ),
243 428 'enabled' => true,
429 + 'supports' => array( 'Google Charts', 'ChartJS' ),
244 430 ),
245 - 'gauge' => array(
246 - 'name' => esc_html__( 'Gauge', 'visualizer' ),
431 + 'bubble' => array(
432 + 'name' => esc_html__( 'Bubble', 'visualizer' ),
247 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' ),
248 436 ),
249 437 'scatter' => array(
250 438 'name' => esc_html__( 'Scatter', 'visualizer' ),
251 439 'enabled' => true,
440 + 'supports' => array( 'Google Charts' ),
252 441 ),
442 + 'gauge' => array(
443 + 'name' => esc_html__( 'Gauge', 'visualizer' ),
444 + 'enabled' => true,
445 + 'supports' => array( 'Google Charts' ),
446 + ),
253 447 'candlestick' => array(
254 448 'name' => esc_html__( 'Candlestick', 'visualizer' ),
255 449 'enabled' => true,
450 + 'supports' => array( 'Google Charts' ),
256 451 ),
257 452 // pro types
258 453 'table' => array(
259 - 'name' => esc_html__( 'Table', 'visualizer' ),
454 + 'name' => esc_html__( 'Table (Deprecated)', 'visualizer' ),
260 455 'enabled' => false,
456 + 'supports' => array( 'Google Charts' ),
261 457 ),
262 458 'timeline' => array(
263 459 'name' => esc_html__( 'Timeline', 'visualizer' ),
264 460 'enabled' => false,
461 + 'supports' => array( 'Google Charts', 'ChartJS' ),
265 462 ),
266 463 'combo' => array(
267 464 'name' => esc_html__( 'Combo', 'visualizer' ),
268 465 'enabled' => false,
466 + 'supports' => array( 'Google Charts' ),
269 467 ),
468 + 'polarArea' => array(
469 + 'name' => esc_html__( 'Polar Area', 'visualizer' ),
470 + 'enabled' => false,
471 + 'supports' => array( 'ChartJS' ),
472 + ),
473 + 'radar' => array(
474 + 'name' => esc_html__( 'Radar/Spider', 'visualizer' ),
475 + 'enabled' => false,
476 + 'supports' => array( 'ChartJS' ),
477 + ),
270 478 )
271 479 );
272 480 $types = apply_filters( 'visualizer_pro_chart_types', $types );
273 481 if ( $enabledOnly ) {
@@ -276,8 +484,12 @@
276 484 if ( ! is_array( $array ) ) {
277 485 // support for old pro
278 486 $array = array( 'enabled' => true, 'name' => $array );
279 487 }
488 + // backward compatibility for PRO before v1.9.0
489 + if ( ! array_key_exists( 'supports', $array ) ) {
490 + $array['supports'] = array( 'Google Charts' );
491 + }
280 492 if ( ! $array['enabled'] ) {
281 493 continue;
282 494 }
283 495 $filtered[ $type ] = $array;
@@ -290,13 +502,94 @@
290 502 if ( ! is_array( $array ) ) {
291 503 // support for old pro
292 504 $array = array( 'enabled' => true, 'name' => $array );
293 505 }
506 + // backward compatibility for PRO before v1.9.0
507 + if ( ! array_key_exists( 'supports', $array ) ) {
508 + $array['supports'] = array( 'Google Charts' );
509 + }
294 510 $doubleD[ $type ] = $array['name'];
295 511 }
296 512 $types = $doubleD;
297 513 }
298 514
515 + return self::handleDeprecatedCharts( $types, $enabledOnly, $get2Darray, $where );
516 + }
517 +
518 + /**
519 + * Handle (soon-to-be) deprecated charts.
520 + */
521 + private static function handleDeprecatedCharts( $types, $enabledOnly, $get2Darray, $where ) {
522 + $deprecated = array();
523 +
524 + switch ( $where ) {
525 + case 'types':
526 + // fall-through
527 + case 'library':
528 + // if the user has a Google Table chart, show it as deprecated otherwise remove the option from the library.
529 + if ( ! self::hasChartType( 'table' ) ) {
530 + $deprecated[] = 'table';
531 + if ( $get2Darray ) {
532 + $types['dataTable'] = esc_html__( 'Table', 'visualizer' );
533 + } else {
534 + $types['dataTable']['name'] = esc_html__( 'Table', 'visualizer' );
535 + }
536 + }
537 +
538 + // if a user has a Gauge/Candlestick chart, then let them keep using it.
539 + if ( ! Visualizer_Module::is_pro() ) {
540 + if ( ! self::hasChartType( 'gauge' ) ) {
541 + if ( $get2Darray ) {
542 + $deprecated[] = 'gauge';
543 + } else {
544 + $types['gauge']['enabled'] = false;
545 + }
546 + }
547 + if ( ! self::hasChartType( 'candlestick' ) ) {
548 + if ( $get2Darray ) {
549 + $deprecated[] = 'candlestick';
550 + } else {
551 + $types['candlestick']['enabled'] = false;
552 + }
553 + }
554 + }
555 + break;
556 + default:
557 + // remove the option to create a Google Table chart.
558 + $deprecated[] = 'table';
559 +
560 + // rename the new table chart type.
561 + if ( $get2Darray ) {
562 + $types['dataTable'] = esc_html__( 'Table', 'visualizer' );
563 + } else {
564 + $types['dataTable']['name'] = esc_html__( 'Table', 'visualizer' );
565 + }
566 +
567 + // if a user has a Gauge/Candlestick chart, then let them keep using it.
568 + if ( ! Visualizer_Module::is_pro() ) {
569 + if ( ! self::hasChartType( 'gauge' ) ) {
570 + if ( $get2Darray ) {
571 + $deprecated[] = 'gauge';
572 + } else {
573 + $types['gauge']['enabled'] = false;
574 + }
575 + }
576 + if ( ! self::hasChartType( 'candlestick' ) ) {
577 + if ( $get2Darray ) {
578 + $deprecated[] = 'candlestick';
579 + } else {
580 + $types['candlestick']['enabled'] = false;
581 + }
582 + }
583 + }
584 + }
585 +
586 + if ( $deprecated ) {
587 + foreach ( $deprecated as $type ) {
588 + unset( $types[ $type ] );
589 + }
590 + }
591 +
299 592 return $types;
300 593 }
301 594
302 595 /**
@@ -306,11 +599,11 @@
306 599 * @global string $pagenow The name of the current page.
307 600 *
308 601 * @access public
309 602 */
310 - public function renderTempaltes() {
603 + public function renderTemplates() {
311 604 global $pagenow;
312 - if ( 'post.php' != $pagenow && 'post-new.php' != $pagenow ) {
605 + if ( 'post.php' !== $pagenow && 'post-new.php' !== $pagenow ) {
313 606 return;
314 607 }
315 608 $render = new Visualizer_Render_Templates();
316 609 $render->render();
@@ -328,26 +621,40 @@
328 621 *
329 622 * @param string $suffix The current page suffix.
330 623 */
331 624 public function enqueueLibraryScripts( $suffix ) {
332 - if ( $suffix == $this->_libraryPage ) {
625 + if ( $suffix === $this->_libraryPage ) {
333 626 wp_enqueue_style( 'visualizer-library', VISUALIZER_ABSURL . 'css/library.css', array(), Visualizer_Plugin::VERSION );
334 627 $this->_addFilter( 'media_upload_tabs', 'setupVisualizerTab' );
335 628 wp_enqueue_media();
336 629 wp_enqueue_script(
337 - 'visualizer-library', VISUALIZER_ABSURL . 'js/library.js', array(
630 + 'visualizer-library',
631 + VISUALIZER_ABSURL . 'js/library.js',
632 + array(
338 633 'jquery',
339 634 'media-views',
340 - ), Visualizer_Plugin::VERSION, true
635 + ),
636 + Visualizer_Plugin::VERSION,
637 + true
341 638 );
342 - wp_enqueue_script( 'google-jsapi-new', '//www.gstatic.com/charts/loader.js', array(), null, true );
343 - wp_enqueue_script( 'google-jsapi-old', '//www.google.com/jsapi', array( 'google-jsapi-new' ), null, true );
344 - wp_enqueue_script(
345 - 'visualizer-render', VISUALIZER_ABSURL . 'js/render.js', array(
346 - 'google-jsapi-old',
347 - 'visualizer-library',
348 - ), Visualizer_Plugin::VERSION, true
349 - );
639 +
640 + wp_enqueue_script( 'visualizer-customization', $this->get_user_customization_js(), array(), null, true );
641 +
642 + $query = $this->getQuery();
643 + while ( $query->have_posts() ) {
644 + $chart = $query->next_post();
645 + $library = $this->load_chart_type( $chart->ID );
646 + if ( is_null( $library ) ) {
647 + continue;
648 + }
649 + wp_enqueue_script(
650 + "visualizer-render-$library",
651 + VISUALIZER_ABSURL . 'js/render-facade.js',
652 + apply_filters( 'visualizer_assets_render', array( 'visualizer-library', 'visualizer-customization' ), true ),
653 + Visualizer_Plugin::VERSION,
654 + true
655 + );
656 + }
350 657 }
351 658 }
352 659
353 660 /**
@@ -374,24 +681,140 @@
374 681 *
375 682 * @access public
376 683 */
377 684 public function registerAdminMenu() {
378 - $title = esc_html__( 'Visualizer Library', 'visualizer' );
379 - $callback = array( $this, 'renderLibraryPage' );
380 - $this->_libraryPage = add_submenu_page( 'upload.php', $title, $title, 'edit_posts', Visualizer_Plugin::NAME, $callback );
685 + $svg_base64_icon = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iNzdweCIgaGVpZ2h0PSI3N3B4IiB2aWV3Qm94PSIwIDAgNzcgNzciIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICA8IS0tIEdlbmVyYXRvcjogU2tldGNoIDUyLjYgKDY3NDkxKSAtIGh0dHA6Ly93d3cuYm9oZW1pYW5jb2RpbmcuY29tL3NrZXRjaCAtLT4KICAgIDx0aXRsZT5Db21iaW5lZCBTaGFwZTwvdGl0bGU+CiAgICA8ZGVzYz5DcmVhdGVkIHdpdGggU2tldGNoLjwvZGVzYz4KICAgIDxnIGlkPSJQcm9kdWN0LVBhZ2UiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPgogICAgICAgIDxnIGlkPSJXb3JkUHJlc3MtcGx1Z2lucyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTE5MC4wMDAwMDAsIC00MzUuMDAwMDAwKSIgZmlsbD0iIzM5QzNEMiI+CiAgICAgICAgICAgIDxwYXRoIGQ9Ik0yMjguNSw1MTIgQzIwNy4yMzcwMzcsNTEyIDE5MCw0OTQuNzYyOTYzIDE5MCw0NzMuNSBDMTkwLDQ1Mi4yMzcwMzcgMjA3LjIzNzAzNyw0MzUgMjI4LjUsNDM1IEMyNDkuNzYyOTYzLDQzNSAyNjcsNDUyLjIzNzAzNyAyNjcsNDczLjUgQzI2Nyw0OTQuNzYyOTYzIDI0OS43NjI5NjMsNTEyIDIyOC41LDUxMiBaIE0yNDYuODQzNzUsNDgzLjU5MjA1OSBMMjE1LjYyNSw0ODMuNTkyMDU5IEwyMTUuNjI1LDQ2MC44MjY1NDQgQzIxNS42MjUsNDYwLjE2NDU0NyAyMTUuMTA3NTc4LDQ1OS42MjgzNTkgMjE0LjQ2ODc1LDQ1OS42MjgzNTkgTDIxMi4xNTYyNSw0NTkuNjI4MzU5IEMyMTEuNTE3NDIyLDQ1OS42MjgzNTkgMjExLDQ2MC4xNjQ1NDcgMjExLDQ2MC44MjY1NDQgTDIxMSw0ODUuOTg4NDI5IEMyMTEsNDg3LjMxMTY3NCAyMTIuMDM1NTY2LDQ4OC4zODQ3OTggMjEzLjMxMjUsNDg4LjM4NDc5OCBMMjQ2Ljg0Mzc1LDQ4OC4zODQ3OTggQzI0Ny40ODI1NzgsNDg4LjM4NDc5OCAyNDgsNDg3Ljg0ODYxMSAyNDgsNDg3LjE4NjYxMyBMMjQ4LDQ4NC43OTAyNDQgQzI0OCw0ODQuMTI4MjQ2IDI0Ny40ODI1NzgsNDgzLjU5MjA1OSAyNDYuODQzNzUsNDgzLjU5MjA1OSBaIE0yNDQuNTMxMjUsNDYyLjAyNDcyOSBMMjM1Ljk5OTU3LDQ2Mi4wMjQ3MjkgQzIzNC40NTQ1MzEsNDYyLjAyNDcyOSAyMzMuNjgwNTY2LDQ2My45NjA1NDcgMjM0Ljc3MzIyMyw0NjUuMDkyODMyIEwyMzcuMTE0NjI5LDQ2Ny41MTkxNTYgTDIzMS44MTI1LDQ3My4wMTQzMzIgTDIyNi41MTAzNzEsNDY3LjUxOTkwNSBDMjI1LjYwNzA1MSw0NjYuNTgzODIzIDIyNC4xNDI5NDksNDY2LjU4MzgyMyAyMjMuMjQwMzUyLDQ2Ny41MTk5MDUgTDIxOC4yNzY0MjYsNDcyLjY2Mzg2MyBDMjE3LjgyNDc2Niw0NzMuMTMxOTA0IDIxNy44MjQ3NjYsNDczLjg5MDUwNSAyMTguMjc2NDI2LDQ3NC4zNTg1NDYgTDIxOS45MTEwNzQsNDc2LjA1MjQ4IEMyMjAuMzYyNzM0LDQ3Ni41MjA1MjEgMjIxLjA5NDc4NSw0NzYuNTIwNTIxIDIyMS41NDY0NDUsNDc2LjA1MjQ4IEwyMjQuODc1LDQ3Mi42MDI0NTYgTDIzMC4xNzcxMjksNDc4LjA5Njg4MyBDMjMxLjA4MDQ0OSw0NzkuMDMyOTY1IDIzMi41NDQ1NTEsNDc5LjAzMjk2NSAyMzMuNDQ3MTQ4LDQ3OC4wOTY4ODMgTDI0MC4zODQ2NDgsNDcwLjkwNzc3MyBMMjQyLjcyNjA1NSw0NzMuMzM0MDk4IEMyNDMuODE4NzExLDQ3NC40NjYzODIgMjQ1LjY4Njc3Nyw0NzMuNjY0MzQ3IDI0NS42ODY3NzcsNDcyLjA2MzI3MyBMMjQ1LjY4Njc3Nyw0NjMuMjIyOTE0IEMyNDUuNjg3NSw0NjIuNTYwOTE3IDI0NS4xNzAwNzgsNDYyLjAyNDcyOSAyNDQuNTMxMjUsNDYyLjAyNDcyOSBaIiBpZD0iQ29tYmluZWQtU2hhcGUiPjwvcGF0aD4KICAgICAgICA8L2c+CiAgICA8L2c+Cjwvc3ZnPg==';
686 +
687 + $this->_libraryPage = add_menu_page( __( 'Visualizer', 'visualizer' ), __( 'Visualizer', 'visualizer' ), 'edit_posts', Visualizer_Plugin::NAME, array( $this, 'renderLibraryPage' ), $svg_base64_icon, 99.7666 );
688 +
689 + add_submenu_page(
690 + Visualizer_Plugin::NAME,
691 + __( 'Chart Library', 'visualizer' ),
692 + __( 'Chart Library', 'visualizer' ),
693 + 'edit_posts',
694 + admin_url( 'admin.php?page=' . Visualizer_Plugin::NAME )
695 + );
696 + add_submenu_page(
697 + Visualizer_Plugin::NAME,
698 + __( 'Add New Chart', 'visualizer' ),
699 + __( 'Add New Chart', 'visualizer' ),
700 + 'edit_posts',
701 + admin_url( 'admin.php?page=' . Visualizer_Plugin::NAME . '&vaction=addnew' )
702 + );
703 + add_submenu_page(
704 + Visualizer_Plugin::NAME,
705 + __( 'Support', 'visualizer' ),
706 + __( '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>',
707 + 'edit_posts',
708 + 'viz-support',
709 + array( $this, 'renderSupportPage' )
710 + );
711 + remove_submenu_page( Visualizer_Plugin::NAME, Visualizer_Plugin::NAME );
712 +
713 + add_action( "load-{$this->_libraryPage}", array( $this, 'addScreenOptions' ) );
381 714 }
382 715
383 716 /**
384 - * Renders visualizer library page.
385 - *
386 - * @since 1.0.0
387 - *
388 - * @access public
717 + * Adds the screen options for pagination.
389 718 */
390 - public function renderLibraryPage() {
719 + function addScreenOptions() {
720 + $screen = get_current_screen();
721 +
722 + // bail if it's some other page.
723 + if ( ! is_object( $screen ) || $screen->id !== $this->_libraryPage ) {
724 + return;
725 + }
726 +
727 + $args = array(
728 + 'label' => __( 'Number of charts per page:', 'visualizer' ),
729 + 'default' => 6,
730 + 'option' => 'visualizer_per_page_library',
731 + );
732 + add_screen_option( 'per_page', $args );
733 + }
734 +
735 + /**
736 + * Returns the screen option for pagination.
737 + */
738 + function setScreenOptions( $status, $option, $value ) {
739 + if ( 'visualizer_per_page_library' === $option ) {
740 + return $value;
741 + }
742 + }
743 +
744 + /**
745 + * Adds the display filters to be used in the meta_query while displaying the charts.
746 + */
747 + private function getDisplayFilters( &$query_args ) {
748 + $query = array();
749 +
750 + // add chart type filter to the query arguments
751 + $type = filter_input( INPUT_GET, 'type' );
752 + if ( $type && in_array( $type, Visualizer_Plugin::getChartTypes(), true ) ) {
753 + $query[] = array(
754 + 'key' => Visualizer_Plugin::CF_CHART_TYPE,
755 + 'value' => $type,
756 + 'compare' => '=',
757 + );
758 + }
759 +
760 + // add chart library filter to the query arguments
761 + $library = filter_input( INPUT_GET, 'library' );
762 + if ( $library ) {
763 + $query[] = array(
764 + 'key' => Visualizer_Plugin::CF_CHART_LIBRARY,
765 + 'value' => $library,
766 + 'compare' => '=',
767 + );
768 + }
769 +
770 + // add date filter to the query arguments
771 + $date = filter_input( INPUT_GET, 'date' );
772 + $possible = array_keys( Visualizer_Plugin::getSupportedDateFilter() );
773 + if ( $date && in_array( $date, $possible, true ) ) {
774 + $query_args['date_query'] = array(
775 + 'after' => "$date -1 day",
776 + 'inclusive' => true,
777 + );
778 + }
779 +
780 + // add source filter to the query arguments
781 + $source = filter_input( INPUT_GET, 'source' );
782 + if ( $source ) {
783 + $source = ucwords( $source );
784 + $source = "Visualizer_Source_{$source}";
785 + $query[] = array(
786 + 'key' => Visualizer_Plugin::CF_SOURCE,
787 + 'value' => $source,
788 + 'compare' => '=',
789 + );
790 + }
791 +
792 + $query_args['meta_query'] = $query;
793 +
794 + $orderby = filter_input( INPUT_GET, 'orderby' );
795 + $order = filter_input( INPUT_GET, 'order' );
796 + if ( $orderby ) {
797 + $query_args['order_by'] = $orderby;
798 + }
799 + $query_args['order'] = empty( $order ) ? 'desc' : $order;
800 + }
801 +
802 + /**
803 + * Get the instance of WP_Query that fetches the charts as per the given criteria.
804 + */
805 + private function getQuery() {
806 + static $q;
807 + if ( ! is_null( $q ) ) {
808 + return $q;
809 + }
810 +
391 811 // get current page
392 812 $page = filter_input(
393 - INPUT_GET, 'vpage', FILTER_VALIDATE_INT, array(
813 + INPUT_GET,
814 + 'vpage',
815 + FILTER_VALIDATE_INT,
816 + array(
394 817 'options' => array(
395 818 'min_range' => 1,
396 819 'default' => 1,
397 820 ),
@@ -396,27 +819,32 @@
396 819 'default' => 1,
397 820 ),
398 821 )
399 822 );
823 +
824 + $per_page = 6;
825 + $screen = get_current_screen();
826 + if ( $screen ) {
827 + // retrieve the per_page option
828 + $screen_option = $screen->get_option( 'per_page', 'option' );
829 + // retrieve the value stored for the current user
830 + $user = get_current_user_id();
831 + $per_page = get_user_meta( $user, $screen_option, true );
832 + if ( empty( $per_page ) || $per_page < 1 ) {
833 + // nothing set, get the default value
834 + $per_page = $screen->get_option( 'per_page', 'default' );
835 + }
836 + }
837 +
400 838 // the initial query arguments to fetch charts
401 839 $query_args = array(
402 840 'post_type' => Visualizer_Plugin::CPT_VISUALIZER,
403 - 'posts_per_page' => 6,
841 + 'posts_per_page' => $per_page,
404 842 'paged' => $page,
405 843 );
406 - // add chart type filter to the query arguments
407 - $filter = filter_input( INPUT_GET, 'type' );
408 - if ( $filter && in_array( $filter, Visualizer_Plugin::getChartTypes() ) ) {
409 - $query_args['meta_query'] = array(
410 - array(
411 - 'key' => Visualizer_Plugin::CF_CHART_TYPE,
412 - 'value' => $filter,
413 - 'compare' => '=',
414 - ),
415 - );
416 - } else {
417 - $filter = 'all';
418 - }
844 +
845 + $this->getDisplayFilters( $query_args );
846 +
419 847 // Added by Ash/Upwork
420 848 $filterByMeta = filter_input( INPUT_GET, 's', FILTER_SANITIZE_STRING );
421 849 if ( $filterByMeta ) {
422 850 $query = array(
@@ -427,49 +855,133 @@
427 855 $meta = isset( $query_args['meta_query'] ) ? $query_args['meta_query'] : array();
428 856 $meta[] = $query;
429 857 $query_args['meta_query'] = $meta;
430 858 }
431 - // Added by Ash/Upwork
432 - // fetch charts
859 + $q = new WP_Query( apply_filters( 'visualizer_query_args', $query_args ) );
860 + return $q;
861 + }
862 +
863 + /**
864 + * Renders support page.
865 + *
866 + * @since 3.3.0
867 + *
868 + * @access public
869 + */
870 + public function renderSupportPage() {
871 + wp_enqueue_style( 'visualizer-upsell', VISUALIZER_ABSURL . 'css/upsell.css', array(), Visualizer_Plugin::VERSION );
872 + include_once VISUALIZER_ABSPATH . '/templates/support.php';
873 + }
874 +
875 + /**
876 + * Renders visualizer library page.
877 + *
878 + * @since 1.0.0
879 + *
880 + * @access public
881 + */
882 + public function renderLibraryPage() {
433 883 $charts = array();
434 - $query = new WP_Query( $query_args );
884 + $query = $this->getQuery();
885 +
886 + // get current page
887 + $page = filter_input(
888 + INPUT_GET,
889 + 'vpage',
890 + FILTER_VALIDATE_INT,
891 + array(
892 + 'options' => array(
893 + 'min_range' => 1,
894 + 'default' => 1,
895 + ),
896 + )
897 + );
898 + // add chart type filter to the query arguments
899 + $filter = filter_input( INPUT_GET, 'type' );
900 + if ( ! ( $filter && in_array( $filter, Visualizer_Plugin::getChartTypes(), true ) ) ) {
901 + $filter = 'all';
902 + }
903 +
904 + $css = '';
435 905 while ( $query->have_posts() ) {
436 906 $chart = $query->next_post();
907 +
908 + // 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.
909 + $chart = $this->handleExistingRevisions( $chart->ID, $chart );
910 + // refresh a "live" db query chart.
911 + $chart = apply_filters( 'visualizer_schedule_refresh_chart', $chart, $chart->ID, false );
912 +
913 + $type = get_post_meta( $chart->ID, Visualizer_Plugin::CF_CHART_TYPE, true );
914 +
437 915 // fetch and update settings
438 916 $settings = get_post_meta( $chart->ID, Visualizer_Plugin::CF_SETTINGS, true );
439 - unset( $settings['height'], $settings['width'] );
440 - $type = get_post_meta( $chart->ID, Visualizer_Plugin::CF_CHART_TYPE, true );
917 +
918 + $settings = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_SETTINGS, $settings, $chart->ID, $type );
919 + if ( ! empty( $atts['settings'] ) ) {
920 + $settings = apply_filters( $atts['settings'], $settings, $chart->ID, $type );
921 + }
922 +
923 + if ( $settings ) {
924 + unset( $settings['height'], $settings['width'], $settings['chartArea'] );
925 + }
926 +
441 927 $series = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_SERIES, get_post_meta( $chart->ID, Visualizer_Plugin::CF_SERIES, true ), $chart->ID, $type );
442 - $data = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_DATA, unserialize( html_entity_decode( $chart->post_content ) ), $chart->ID, $type );
928 + $data = self::get_chart_data( $chart, $type );
929 +
930 + $library = $this->load_chart_type( $chart->ID );
931 +
932 + $id = 'visualizer-' . $chart->ID;
933 + $arguments = $this->get_inline_custom_css( $id, $settings );
934 + if ( ! empty( $arguments ) ) {
935 + $css .= $arguments[0];
936 + $settings = $arguments[1];
937 + }
938 +
443 939 // add chart to the array
444 - $charts[ 'visualizer-' . $chart->ID ] = array(
940 + $charts[ $id ] = array(
445 941 'id' => $chart->ID,
446 942 'type' => $type,
447 943 'series' => $series,
448 944 'settings' => $settings,
449 945 'data' => $data,
946 + 'library' => $library,
450 947 );
451 948 }
452 949 // enqueue charts array
453 950 $ajaxurl = admin_url( 'admin-ajax.php' );
454 951 wp_localize_script(
455 - 'visualizer-library', 'visualizer', array(
952 + 'visualizer-library',
953 + 'visualizer',
954 + array(
955 + 'language' => $this->get_language(),
956 + 'map_api_key' => get_option( 'visualizer-map-api-key' ),
456 957 'charts' => $charts,
457 958 'urls' => array(
458 - 'base' => add_query_arg( 'vpage', false ),
959 + 'base' => add_query_arg( array( 'vpage' => false, 'vaction' => false ) ),
459 960 'create' => add_query_arg(
460 961 array(
461 962 'action' => Visualizer_Plugin::ACTION_CREATE_CHART,
462 963 'library' => 'yes',
463 - ), $ajaxurl
964 + 'type' => isset( $_GET['type'] ) ? $_GET['type'] : '',
965 + 'chart-library' => isset( $_GET['chart-library'] ) ? $_GET['chart-library'] : '',
966 + 'vaction' => false,
967 + ),
968 + $ajaxurl
464 969 ),
465 970 'edit' => add_query_arg(
466 971 array(
467 972 'action' => Visualizer_Plugin::ACTION_EDIT_CHART,
468 973 'library' => 'yes',
469 - ), $ajaxurl
974 + 'vaction' => false,
975 + ),
976 + $ajaxurl
470 977 ),
471 978 ),
979 + 'page_type' => 'library',
980 + 'is_front' => false,
981 + 'i10n' => array(
982 + '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' ),
983 + ),
472 984 )
473 985 );
474 986 // render library page
475 987 $render = new Visualizer_Render_Library();
@@ -474,12 +986,13 @@
474 986 // render library page
475 987 $render = new Visualizer_Render_Library();
476 988 $render->charts = $charts;
477 989 $render->type = $filter;
478 - $render->types = self::_getChartTypesLocalized();
990 + $render->types = self::_getChartTypesLocalized( false, false, false, true );
991 + $render->custom_css = $css;
479 992 $render->pagination = paginate_links(
480 993 array(
481 - 'base' => add_query_arg( 'vpage', '%#%' ),
994 + 'base' => add_query_arg( array( 'vpage' => '%#%', 'vaction' => false ) ),
482 995 'format' => '',
483 996 'current' => $page,
484 997 'total' => $query->max_num_pages,
485 998 'type' => 'array',
@@ -500,14 +1013,14 @@
500 1013 *
501 1014 * @return array Updated array of action links.
502 1015 */
503 1016 public function getPluginActionLinks( $links, $file ) {
504 - if ( $file == plugin_basename( VISUALIZER_BASEFILE ) ) {
1017 + if ( $file === plugin_basename( VISUALIZER_BASEFILE ) ) {
505 1018 array_unshift(
506 1019 $links,
507 1020 sprintf(
508 1021 '<a href="%s">%s</a>',
509 - admin_url( 'upload.php?page=' . Visualizer_Plugin::NAME ),
1022 + admin_url( 'admin.php?page=' . Visualizer_Plugin::NAME ),
510 1023 esc_html__( 'Library', 'visualizer' )
511 1024 )
512 1025 );
513 1026 }
@@ -527,17 +1040,17 @@
527 1040 *
528 1041 * @return array Updated array of plugin meta links.
529 1042 */
530 1043 public function getPluginMetaLinks( $plugin_meta, $plugin_file ) {
531 - if ( $plugin_file == plugin_basename( VISUALIZER_BASEFILE ) ) {
1044 + if ( $plugin_file === plugin_basename( VISUALIZER_BASEFILE ) ) {
532 1045 // knowledge base link
533 1046 $plugin_meta[] = sprintf(
534 - '<a href="https://github.com/codeinwp/visualizer/wiki" target="_blank">%s</a>',
535 - esc_html__( 'Knowledge Base', 'visualizer' )
1047 + '<a href="' . VISUALIZER_MAIN_DOC . '" target="_blank">%s</a>',
1048 + esc_html__( 'Docs', 'visualizer' )
536 1049 );
537 1050 // flattr link
538 1051 $plugin_meta[] = sprintf(
539 - '<a style="color:red" href="https://themeisle.com/plugins/visualizer-charts-and-graphs-pro-addon/" target="_blank">%s</a>',
1052 + '<a style="color:red" href="' . Visualizer_Plugin::PRO_TEASER_URL . '" target="_blank">%s</a>',
540 1053 esc_html__( 'Pro Addon', 'visualizer' )
541 1054 );
542 1055 }
543 1056