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 +572 -68 3.0.73.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,16 +309,23 @@
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 );
160 324 wp_localize_script(
161 - 'visualizer-media-view', 'visualizer', array(
325 + 'visualizer-media-view',
326 + 'visualizer',
327 + array(
162 328 'i10n' => array(
163 329 'insert' => __( 'Insert', 'visualizer' ),
164 330 ),
165 331 )
@@ -213,9 +379,9 @@
213 379 * @static
214 380 * @access private
215 381 * @return array The associated array of chart types with localized names.
216 382 */
217 - 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 ) {
218 384 $additional = array();
219 385 if ( $add_select ) {
220 386 $additional['select'] = array(
221 387 'name' => esc_html__( 'All', 'visualizer' ),
@@ -223,58 +389,93 @@
223 389 );
224 390 }
225 391
226 392 $types = array_merge(
227 - $additional, array(
393 + $additional,
394 + array(
395 + 'dataTable' => array(
396 + 'name' => esc_html__( 'Table', 'visualizer' ),
397 + 'enabled' => true,
398 + 'supports' => array( 'DataTable' ),
399 + ),
228 400 'pie' => array(
229 - 'name' => esc_html__( 'Pie', 'visualizer' ),
401 + 'name' => esc_html__( 'Pie/Donut', 'visualizer' ),
230 402 'enabled' => true,
403 + 'supports' => array( 'Google Charts', 'ChartJS' ),
231 404 ),
232 405 'line' => array(
233 406 'name' => esc_html__( 'Line', 'visualizer' ),
234 407 'enabled' => true,
408 + 'supports' => array( 'Google Charts', 'ChartJS' ),
235 409 ),
236 410 'area' => array(
237 411 'name' => esc_html__( 'Area', 'visualizer' ),
238 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' ),
239 415 ),
240 416 'geo' => array(
241 417 'name' => esc_html__( 'Geo', 'visualizer' ),
242 418 'enabled' => true,
419 + 'supports' => array( 'Google Charts' ),
243 420 ),
244 421 'bar' => array(
245 422 'name' => esc_html__( 'Bar', 'visualizer' ),
246 423 'enabled' => true,
424 + 'supports' => array( 'Google Charts', 'ChartJS' ),
247 425 ),
248 426 'column' => array(
249 427 'name' => esc_html__( 'Column', 'visualizer' ),
250 428 'enabled' => true,
429 + 'supports' => array( 'Google Charts', 'ChartJS' ),
251 430 ),
252 - 'gauge' => array(
253 - 'name' => esc_html__( 'Gauge', 'visualizer' ),
431 + 'bubble' => array(
432 + 'name' => esc_html__( 'Bubble', 'visualizer' ),
254 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' ),
255 436 ),
256 437 'scatter' => array(
257 438 'name' => esc_html__( 'Scatter', 'visualizer' ),
258 439 'enabled' => true,
440 + 'supports' => array( 'Google Charts' ),
259 441 ),
442 + 'gauge' => array(
443 + 'name' => esc_html__( 'Gauge', 'visualizer' ),
444 + 'enabled' => true,
445 + 'supports' => array( 'Google Charts' ),
446 + ),
260 447 'candlestick' => array(
261 448 'name' => esc_html__( 'Candlestick', 'visualizer' ),
262 449 'enabled' => true,
450 + 'supports' => array( 'Google Charts' ),
263 451 ),
264 452 // pro types
265 453 'table' => array(
266 - 'name' => esc_html__( 'Table', 'visualizer' ),
454 + 'name' => esc_html__( 'Table (Deprecated)', 'visualizer' ),
267 455 'enabled' => false,
456 + 'supports' => array( 'Google Charts' ),
268 457 ),
269 458 'timeline' => array(
270 459 'name' => esc_html__( 'Timeline', 'visualizer' ),
271 460 'enabled' => false,
461 + 'supports' => array( 'Google Charts', 'ChartJS' ),
272 462 ),
273 463 'combo' => array(
274 464 'name' => esc_html__( 'Combo', 'visualizer' ),
275 465 'enabled' => false,
466 + 'supports' => array( 'Google Charts' ),
276 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 + ),
277 478 )
278 479 );
279 480 $types = apply_filters( 'visualizer_pro_chart_types', $types );
280 481 if ( $enabledOnly ) {
@@ -283,8 +484,12 @@
283 484 if ( ! is_array( $array ) ) {
284 485 // support for old pro
285 486 $array = array( 'enabled' => true, 'name' => $array );
286 487 }
488 + // backward compatibility for PRO before v1.9.0
489 + if ( ! array_key_exists( 'supports', $array ) ) {
490 + $array['supports'] = array( 'Google Charts' );
491 + }
287 492 if ( ! $array['enabled'] ) {
288 493 continue;
289 494 }
290 495 $filtered[ $type ] = $array;
@@ -297,13 +502,94 @@
297 502 if ( ! is_array( $array ) ) {
298 503 // support for old pro
299 504 $array = array( 'enabled' => true, 'name' => $array );
300 505 }
506 + // backward compatibility for PRO before v1.9.0
507 + if ( ! array_key_exists( 'supports', $array ) ) {
508 + $array['supports'] = array( 'Google Charts' );
509 + }
301 510 $doubleD[ $type ] = $array['name'];
302 511 }
303 512 $types = $doubleD;
304 513 }
305 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 +
306 592 return $types;
307 593 }
308 594
309 595 /**
@@ -313,11 +599,11 @@
313 599 * @global string $pagenow The name of the current page.
314 600 *
315 601 * @access public
316 602 */
317 - public function renderTempaltes() {
603 + public function renderTemplates() {
318 604 global $pagenow;
319 - if ( 'post.php' != $pagenow && 'post-new.php' != $pagenow ) {
605 + if ( 'post.php' !== $pagenow && 'post-new.php' !== $pagenow ) {
320 606 return;
321 607 }
322 608 $render = new Visualizer_Render_Templates();
323 609 $render->render();
@@ -335,26 +621,40 @@
335 621 *
336 622 * @param string $suffix The current page suffix.
337 623 */
338 624 public function enqueueLibraryScripts( $suffix ) {
339 - if ( $suffix == $this->_libraryPage ) {
625 + if ( $suffix === $this->_libraryPage ) {
340 626 wp_enqueue_style( 'visualizer-library', VISUALIZER_ABSURL . 'css/library.css', array(), Visualizer_Plugin::VERSION );
341 627 $this->_addFilter( 'media_upload_tabs', 'setupVisualizerTab' );
342 628 wp_enqueue_media();
343 629 wp_enqueue_script(
344 - 'visualizer-library', VISUALIZER_ABSURL . 'js/library.js', array(
630 + 'visualizer-library',
631 + VISUALIZER_ABSURL . 'js/library.js',
632 + array(
345 633 'jquery',
346 634 'media-views',
347 - ), Visualizer_Plugin::VERSION, true
635 + ),
636 + Visualizer_Plugin::VERSION,
637 + true
348 638 );
349 - wp_enqueue_script( 'google-jsapi-new', '//www.gstatic.com/charts/loader.js', array(), null, true );
350 - wp_enqueue_script( 'google-jsapi-old', '//www.google.com/jsapi', array( 'google-jsapi-new' ), null, true );
351 - wp_enqueue_script(
352 - 'visualizer-render', VISUALIZER_ABSURL . 'js/render.js', array(
353 - 'google-jsapi-old',
354 - 'visualizer-library',
355 - ), Visualizer_Plugin::VERSION, true
356 - );
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 + }
357 657 }
358 658 }
359 659
360 660 /**
@@ -381,24 +681,140 @@
381 681 *
382 682 * @access public
383 683 */
384 684 public function registerAdminMenu() {
385 - $title = esc_html__( 'Visualizer Library', 'visualizer' );
386 - $callback = array( $this, 'renderLibraryPage' );
387 - $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' ) );
388 714 }
389 715
390 716 /**
391 - * Renders visualizer library page.
392 - *
393 - * @since 1.0.0
394 - *
395 - * @access public
717 + * Adds the screen options for pagination.
396 718 */
397 - 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 +
398 811 // get current page
399 812 $page = filter_input(
400 - INPUT_GET, 'vpage', FILTER_VALIDATE_INT, array(
813 + INPUT_GET,
814 + 'vpage',
815 + FILTER_VALIDATE_INT,
816 + array(
401 817 'options' => array(
402 818 'min_range' => 1,
403 819 'default' => 1,
404 820 ),
@@ -403,27 +819,32 @@
403 819 'default' => 1,
404 820 ),
405 821 )
406 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 +
407 838 // the initial query arguments to fetch charts
408 839 $query_args = array(
409 840 'post_type' => Visualizer_Plugin::CPT_VISUALIZER,
410 - 'posts_per_page' => 6,
841 + 'posts_per_page' => $per_page,
411 842 'paged' => $page,
412 843 );
413 - // add chart type filter to the query arguments
414 - $filter = filter_input( INPUT_GET, 'type' );
415 - if ( $filter && in_array( $filter, Visualizer_Plugin::getChartTypes() ) ) {
416 - $query_args['meta_query'] = array(
417 - array(
418 - 'key' => Visualizer_Plugin::CF_CHART_TYPE,
419 - 'value' => $filter,
420 - 'compare' => '=',
421 - ),
422 - );
423 - } else {
424 - $filter = 'all';
425 - }
844 +
845 + $this->getDisplayFilters( $query_args );
846 +
426 847 // Added by Ash/Upwork
427 848 $filterByMeta = filter_input( INPUT_GET, 's', FILTER_SANITIZE_STRING );
428 849 if ( $filterByMeta ) {
429 850 $query = array(
@@ -434,51 +855,133 @@
434 855 $meta = isset( $query_args['meta_query'] ) ? $query_args['meta_query'] : array();
435 856 $meta[] = $query;
436 857 $query_args['meta_query'] = $meta;
437 858 }
438 - // Added by Ash/Upwork
439 - // 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() {
440 883 $charts = array();
441 - $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 = '';
442 905 while ( $query->have_posts() ) {
443 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 +
444 915 // fetch and update settings
445 916 $settings = get_post_meta( $chart->ID, Visualizer_Plugin::CF_SETTINGS, true );
446 - unset( $settings['height'], $settings['width'] );
447 - $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 +
448 927 $series = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_SERIES, get_post_meta( $chart->ID, Visualizer_Plugin::CF_SERIES, true ), $chart->ID, $type );
449 - $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 +
450 939 // add chart to the array
451 - $charts[ 'visualizer-' . $chart->ID ] = array(
940 + $charts[ $id ] = array(
452 941 'id' => $chart->ID,
453 942 'type' => $type,
454 943 'series' => $series,
455 944 'settings' => $settings,
456 945 'data' => $data,
946 + 'library' => $library,
457 947 );
458 948 }
459 949 // enqueue charts array
460 950 $ajaxurl = admin_url( 'admin-ajax.php' );
461 951 wp_localize_script(
462 - 'visualizer-library', 'visualizer', array(
952 + 'visualizer-library',
953 + 'visualizer',
954 + array(
463 955 'language' => $this->get_language(),
464 956 'map_api_key' => get_option( 'visualizer-map-api-key' ),
465 957 'charts' => $charts,
466 958 'urls' => array(
467 - 'base' => add_query_arg( 'vpage', false ),
959 + 'base' => add_query_arg( array( 'vpage' => false, 'vaction' => false ) ),
468 960 'create' => add_query_arg(
469 961 array(
470 962 'action' => Visualizer_Plugin::ACTION_CREATE_CHART,
471 963 'library' => 'yes',
472 - ), $ajaxurl
964 + 'type' => isset( $_GET['type'] ) ? $_GET['type'] : '',
965 + 'chart-library' => isset( $_GET['chart-library'] ) ? $_GET['chart-library'] : '',
966 + 'vaction' => false,
967 + ),
968 + $ajaxurl
473 969 ),
474 970 'edit' => add_query_arg(
475 971 array(
476 972 'action' => Visualizer_Plugin::ACTION_EDIT_CHART,
477 973 'library' => 'yes',
478 - ), $ajaxurl
974 + 'vaction' => false,
975 + ),
976 + $ajaxurl
479 977 ),
480 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 + ),
481 984 )
482 985 );
483 986 // render library page
484 987 $render = new Visualizer_Render_Library();
@@ -483,12 +986,13 @@
483 986 // render library page
484 987 $render = new Visualizer_Render_Library();
485 988 $render->charts = $charts;
486 989 $render->type = $filter;
487 - $render->types = self::_getChartTypesLocalized();
990 + $render->types = self::_getChartTypesLocalized( false, false, false, true );
991 + $render->custom_css = $css;
488 992 $render->pagination = paginate_links(
489 993 array(
490 - 'base' => add_query_arg( 'vpage', '%#%' ),
994 + 'base' => add_query_arg( array( 'vpage' => '%#%', 'vaction' => false ) ),
491 995 'format' => '',
492 996 'current' => $page,
493 997 'total' => $query->max_num_pages,
494 998 'type' => 'array',
@@ -509,14 +1013,14 @@
509 1013 *
510 1014 * @return array Updated array of action links.
511 1015 */
512 1016 public function getPluginActionLinks( $links, $file ) {
513 - if ( $file == plugin_basename( VISUALIZER_BASEFILE ) ) {
1017 + if ( $file === plugin_basename( VISUALIZER_BASEFILE ) ) {
514 1018 array_unshift(
515 1019 $links,
516 1020 sprintf(
517 1021 '<a href="%s">%s</a>',
518 - admin_url( 'upload.php?page=' . Visualizer_Plugin::NAME ),
1022 + admin_url( 'admin.php?page=' . Visualizer_Plugin::NAME ),
519 1023 esc_html__( 'Library', 'visualizer' )
520 1024 )
521 1025 );
522 1026 }
@@ -536,17 +1040,17 @@
536 1040 *
537 1041 * @return array Updated array of plugin meta links.
538 1042 */
539 1043 public function getPluginMetaLinks( $plugin_meta, $plugin_file ) {
540 - if ( $plugin_file == plugin_basename( VISUALIZER_BASEFILE ) ) {
1044 + if ( $plugin_file === plugin_basename( VISUALIZER_BASEFILE ) ) {
541 1045 // knowledge base link
542 1046 $plugin_meta[] = sprintf(
543 - '<a href="https://github.com/codeinwp/visualizer/wiki" target="_blank">%s</a>',
544 - esc_html__( 'Knowledge Base', 'visualizer' )
1047 + '<a href="' . VISUALIZER_MAIN_DOC . '" target="_blank">%s</a>',
1048 + esc_html__( 'Docs', 'visualizer' )
545 1049 );
546 1050 // flattr link
547 1051 $plugin_meta[] = sprintf(
548 - '<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>',
549 1053 esc_html__( 'Pro Addon', 'visualizer' )
550 1054 );
551 1055 }
552 1056