PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.6.1
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.6.1
4.0.7 4.0.6 4.0.5 4.0.4 4.0.3 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.1 3.1.2 3.1.3 3.10.0 3.10.1 3.10.10 3.10.11 3.10.12 3.10.13 3.10.14 3.10.15 3.10.2 3.10.3 3.10.4 All 148 releases
← All changes | classes/Visualizer/Module/Admin.php +564 -71 3.0.73.6.1 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_Tabular::enqueue_assets( array( 'media-editor' ) ),
318 + );
319 +
320 + wp_enqueue_script( 'visualizer-media-model', VISUALIZER_ABSURL . 'js/media/model.js', $deps, Visualizer_Plugin::VERSION, true );
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,88 @@
223 389 );
224 390 }
225 391
226 392 $types = array_merge(
227 - $additional, array(
393 + $additional,
394 + array(
395 + 'tabular' => array(
396 + 'name' => esc_html__( 'Table', 'visualizer' ),
397 + 'enabled' => true,
398 + 'supports' => array( 'Google Charts', 'DataTable' ),
399 + ),
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 - 'table' => array(
266 - 'name' => esc_html__( 'Table', 'visualizer' ),
267 - 'enabled' => false,
268 - ),
269 453 'timeline' => array(
270 454 'name' => esc_html__( 'Timeline', 'visualizer' ),
271 455 'enabled' => false,
456 + 'supports' => array( 'Google Charts', 'ChartJS' ),
272 457 ),
273 458 'combo' => array(
274 459 'name' => esc_html__( 'Combo', 'visualizer' ),
275 460 'enabled' => false,
461 + 'supports' => array( 'Google Charts' ),
276 462 ),
463 + 'polarArea' => array(
464 + 'name' => esc_html__( 'Polar Area', 'visualizer' ),
465 + 'enabled' => false,
466 + 'supports' => array( 'ChartJS' ),
467 + ),
468 + 'radar' => array(
469 + 'name' => esc_html__( 'Radar/Spider', 'visualizer' ),
470 + 'enabled' => false,
471 + 'supports' => array( 'ChartJS' ),
472 + ),
277 473 )
278 474 );
279 475 $types = apply_filters( 'visualizer_pro_chart_types', $types );
280 476 if ( $enabledOnly ) {
@@ -283,8 +479,12 @@
283 479 if ( ! is_array( $array ) ) {
284 480 // support for old pro
285 481 $array = array( 'enabled' => true, 'name' => $array );
286 482 }
483 + // backward compatibility for PRO before v1.9.0
484 + if ( ! array_key_exists( 'supports', $array ) ) {
485 + $array['supports'] = array( 'Google Charts' );
486 + }
287 487 if ( ! $array['enabled'] ) {
288 488 continue;
289 489 }
290 490 $filtered[ $type ] = $array;
@@ -297,13 +497,74 @@
297 497 if ( ! is_array( $array ) ) {
298 498 // support for old pro
299 499 $array = array( 'enabled' => true, 'name' => $array );
300 500 }
501 + // backward compatibility for PRO before v1.9.0
502 + if ( ! array_key_exists( 'supports', $array ) ) {
503 + $array['supports'] = array( 'Google Charts' );
504 + }
301 505 $doubleD[ $type ] = $array['name'];
302 506 }
303 507 $types = $doubleD;
304 508 }
305 509
510 + return self::handleDeprecatedCharts( $types, $enabledOnly, $get2Darray, $where );
511 + }
512 +
513 + /**
514 + * Handle (soon-to-be) deprecated charts.
515 + */
516 + private static function handleDeprecatedCharts( $types, $enabledOnly, $get2Darray, $where ) {
517 + $deprecated = array();
518 +
519 + switch ( $where ) {
520 + case 'types':
521 + // fall-through
522 + case 'library':
523 + // if a user has a Gauge/Candlestick chart, then let them keep using it.
524 + if ( ! Visualizer_Module::is_pro() ) {
525 + if ( ! self::hasChartType( 'gauge' ) ) {
526 + if ( $get2Darray ) {
527 + $deprecated[] = 'gauge';
528 + } else {
529 + $types['gauge']['enabled'] = false;
530 + }
531 + }
532 + if ( ! self::hasChartType( 'candlestick' ) ) {
533 + if ( $get2Darray ) {
534 + $deprecated[] = 'candlestick';
535 + } else {
536 + $types['candlestick']['enabled'] = false;
537 + }
538 + }
539 + }
540 + break;
541 + default:
542 + // if a user has a Gauge/Candlestick chart, then let them keep using it.
543 + if ( ! Visualizer_Module::is_pro() ) {
544 + if ( ! self::hasChartType( 'gauge' ) ) {
545 + if ( $get2Darray ) {
546 + $deprecated[] = 'gauge';
547 + } else {
548 + $types['gauge']['enabled'] = false;
549 + }
550 + }
551 + if ( ! self::hasChartType( 'candlestick' ) ) {
552 + if ( $get2Darray ) {
553 + $deprecated[] = 'candlestick';
554 + } else {
555 + $types['candlestick']['enabled'] = false;
556 + }
557 + }
558 + }
559 + }
560 +
561 + if ( $deprecated ) {
562 + foreach ( $deprecated as $type ) {
563 + unset( $types[ $type ] );
564 + }
565 + }
566 +
306 567 return $types;
307 568 }
308 569
309 570 /**
@@ -313,11 +574,11 @@
313 574 * @global string $pagenow The name of the current page.
314 575 *
315 576 * @access public
316 577 */
317 - public function renderTempaltes() {
578 + public function renderTemplates() {
318 579 global $pagenow;
319 - if ( 'post.php' != $pagenow && 'post-new.php' != $pagenow ) {
580 + if ( 'post.php' !== $pagenow && 'post-new.php' !== $pagenow ) {
320 581 return;
321 582 }
322 583 $render = new Visualizer_Render_Templates();
323 584 $render->render();
@@ -335,26 +596,41 @@
335 596 *
336 597 * @param string $suffix The current page suffix.
337 598 */
338 599 public function enqueueLibraryScripts( $suffix ) {
339 - if ( $suffix == $this->_libraryPage ) {
600 + if ( $suffix === $this->_libraryPage ) {
340 601 wp_enqueue_style( 'visualizer-library', VISUALIZER_ABSURL . 'css/library.css', array(), Visualizer_Plugin::VERSION );
341 602 $this->_addFilter( 'media_upload_tabs', 'setupVisualizerTab' );
342 603 wp_enqueue_media();
343 604 wp_enqueue_script(
344 - 'visualizer-library', VISUALIZER_ABSURL . 'js/library.js', array(
605 + 'visualizer-library',
606 + VISUALIZER_ABSURL . 'js/library.js',
607 + array(
345 608 'jquery',
346 609 'media-views',
347 - ), Visualizer_Plugin::VERSION, true
610 + 'clipboard',
611 + ),
612 + Visualizer_Plugin::VERSION,
613 + true
348 614 );
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 - );
615 +
616 + wp_enqueue_script( 'visualizer-customization', $this->get_user_customization_js(), array(), null, true );
617 +
618 + $query = $this->getQuery();
619 + while ( $query->have_posts() ) {
620 + $chart = $query->next_post();
621 + $library = $this->load_chart_type( $chart->ID );
622 + if ( is_null( $library ) ) {
623 + continue;
624 + }
625 + wp_enqueue_script(
626 + "visualizer-render-$library",
627 + VISUALIZER_ABSURL . 'js/render-facade.js',
628 + apply_filters( 'visualizer_assets_render', array( 'visualizer-library', 'visualizer-customization' ), true ),
629 + Visualizer_Plugin::VERSION,
630 + true
631 + );
632 + }
357 633 }
358 634 }
359 635
360 636 /**
@@ -381,24 +657,140 @@
381 657 *
382 658 * @access public
383 659 */
384 660 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 );
661 + $svg_base64_icon = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iNzdweCIgaGVpZ2h0PSI3N3B4IiB2aWV3Qm94PSIwIDAgNzcgNzciIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICA8IS0tIEdlbmVyYXRvcjogU2tldGNoIDUyLjYgKDY3NDkxKSAtIGh0dHA6Ly93d3cuYm9oZW1pYW5jb2RpbmcuY29tL3NrZXRjaCAtLT4KICAgIDx0aXRsZT5Db21iaW5lZCBTaGFwZTwvdGl0bGU+CiAgICA8ZGVzYz5DcmVhdGVkIHdpdGggU2tldGNoLjwvZGVzYz4KICAgIDxnIGlkPSJQcm9kdWN0LVBhZ2UiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPgogICAgICAgIDxnIGlkPSJXb3JkUHJlc3MtcGx1Z2lucyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTE5MC4wMDAwMDAsIC00MzUuMDAwMDAwKSIgZmlsbD0iIzM5QzNEMiI+CiAgICAgICAgICAgIDxwYXRoIGQ9Ik0yMjguNSw1MTIgQzIwNy4yMzcwMzcsNTEyIDE5MCw0OTQuNzYyOTYzIDE5MCw0NzMuNSBDMTkwLDQ1Mi4yMzcwMzcgMjA3LjIzNzAzNyw0MzUgMjI4LjUsNDM1IEMyNDkuNzYyOTYzLDQzNSAyNjcsNDUyLjIzNzAzNyAyNjcsNDczLjUgQzI2Nyw0OTQuNzYyOTYzIDI0OS43NjI5NjMsNTEyIDIyOC41LDUxMiBaIE0yNDYuODQzNzUsNDgzLjU5MjA1OSBMMjE1LjYyNSw0ODMuNTkyMDU5IEwyMTUuNjI1LDQ2MC44MjY1NDQgQzIxNS42MjUsNDYwLjE2NDU0NyAyMTUuMTA3NTc4LDQ1OS42MjgzNTkgMjE0LjQ2ODc1LDQ1OS42MjgzNTkgTDIxMi4xNTYyNSw0NTkuNjI4MzU5IEMyMTEuNTE3NDIyLDQ1OS42MjgzNTkgMjExLDQ2MC4xNjQ1NDcgMjExLDQ2MC44MjY1NDQgTDIxMSw0ODUuOTg4NDI5IEMyMTEsNDg3LjMxMTY3NCAyMTIuMDM1NTY2LDQ4OC4zODQ3OTggMjEzLjMxMjUsNDg4LjM4NDc5OCBMMjQ2Ljg0Mzc1LDQ4OC4zODQ3OTggQzI0Ny40ODI1NzgsNDg4LjM4NDc5OCAyNDgsNDg3Ljg0ODYxMSAyNDgsNDg3LjE4NjYxMyBMMjQ4LDQ4NC43OTAyNDQgQzI0OCw0ODQuMTI4MjQ2IDI0Ny40ODI1NzgsNDgzLjU5MjA1OSAyNDYuODQzNzUsNDgzLjU5MjA1OSBaIE0yNDQuNTMxMjUsNDYyLjAyNDcyOSBMMjM1Ljk5OTU3LDQ2Mi4wMjQ3MjkgQzIzNC40NTQ1MzEsNDYyLjAyNDcyOSAyMzMuNjgwNTY2LDQ2My45NjA1NDcgMjM0Ljc3MzIyMyw0NjUuMDkyODMyIEwyMzcuMTE0NjI5LDQ2Ny41MTkxNTYgTDIzMS44MTI1LDQ3My4wMTQzMzIgTDIyNi41MTAzNzEsNDY3LjUxOTkwNSBDMjI1LjYwNzA1MSw0NjYuNTgzODIzIDIyNC4xNDI5NDksNDY2LjU4MzgyMyAyMjMuMjQwMzUyLDQ2Ny41MTk5MDUgTDIxOC4yNzY0MjYsNDcyLjY2Mzg2MyBDMjE3LjgyNDc2Niw0NzMuMTMxOTA0IDIxNy44MjQ3NjYsNDczLjg5MDUwNSAyMTguMjc2NDI2LDQ3NC4zNTg1NDYgTDIxOS45MTEwNzQsNDc2LjA1MjQ4IEMyMjAuMzYyNzM0LDQ3Ni41MjA1MjEgMjIxLjA5NDc4NSw0NzYuNTIwNTIxIDIyMS41NDY0NDUsNDc2LjA1MjQ4IEwyMjQuODc1LDQ3Mi42MDI0NTYgTDIzMC4xNzcxMjksNDc4LjA5Njg4MyBDMjMxLjA4MDQ0OSw0NzkuMDMyOTY1IDIzMi41NDQ1NTEsNDc5LjAzMjk2NSAyMzMuNDQ3MTQ4LDQ3OC4wOTY4ODMgTDI0MC4zODQ2NDgsNDcwLjkwNzc3MyBMMjQyLjcyNjA1NSw0NzMuMzM0MDk4IEMyNDMuODE4NzExLDQ3NC40NjYzODIgMjQ1LjY4Njc3Nyw0NzMuNjY0MzQ3IDI0NS42ODY3NzcsNDcyLjA2MzI3MyBMMjQ1LjY4Njc3Nyw0NjMuMjIyOTE0IEMyNDUuNjg3NSw0NjIuNTYwOTE3IDI0NS4xNzAwNzgsNDYyLjAyNDcyOSAyNDQuNTMxMjUsNDYyLjAyNDcyOSBaIiBpZD0iQ29tYmluZWQtU2hhcGUiPjwvcGF0aD4KICAgICAgICA8L2c+CiAgICA8L2c+Cjwvc3ZnPg==';
662 +
663 + $this->_libraryPage = add_menu_page( __( 'Visualizer', 'visualizer' ), __( 'Visualizer', 'visualizer' ), 'edit_posts', Visualizer_Plugin::NAME, array( $this, 'renderLibraryPage' ), $svg_base64_icon, 99.7666 );
664 +
665 + add_submenu_page(
666 + Visualizer_Plugin::NAME,
667 + __( 'Chart Library', 'visualizer' ),
668 + __( 'Chart Library', 'visualizer' ),
669 + 'edit_posts',
670 + admin_url( 'admin.php?page=' . Visualizer_Plugin::NAME )
671 + );
672 + add_submenu_page(
673 + Visualizer_Plugin::NAME,
674 + __( 'Add New Chart', 'visualizer' ),
675 + __( 'Add New Chart', 'visualizer' ),
676 + 'edit_posts',
677 + admin_url( 'admin.php?page=' . Visualizer_Plugin::NAME . '&vaction=addnew' )
678 + );
679 + add_submenu_page(
680 + Visualizer_Plugin::NAME,
681 + __( 'Support', 'visualizer' ),
682 + __( 'Support', 'visualizer' ) . '<span class="dashicons dashicons-editor-help more-features-icon" style="width: 17px; height: 17px; margin-left: 4px; color: #ffca54; font-size: 17px; vertical-align: -3px;"></span>',
683 + 'edit_posts',
684 + 'viz-support',
685 + array( $this, 'renderSupportPage' )
686 + );
687 + remove_submenu_page( Visualizer_Plugin::NAME, Visualizer_Plugin::NAME );
688 +
689 + add_action( "load-{$this->_libraryPage}", array( $this, 'addScreenOptions' ) );
388 690 }
389 691
390 692 /**
391 - * Renders visualizer library page.
392 - *
393 - * @since 1.0.0
394 - *
395 - * @access public
693 + * Adds the screen options for pagination.
396 694 */
397 - public function renderLibraryPage() {
695 + function addScreenOptions() {
696 + $screen = get_current_screen();
697 +
698 + // bail if it's some other page.
699 + if ( ! is_object( $screen ) || $screen->id !== $this->_libraryPage ) {
700 + return;
701 + }
702 +
703 + $args = array(
704 + 'label' => __( 'Number of charts per page:', 'visualizer' ),
705 + 'default' => 6,
706 + 'option' => 'visualizer_per_page_library',
707 + );
708 + add_screen_option( 'per_page', $args );
709 + }
710 +
711 + /**
712 + * Returns the screen option for pagination.
713 + */
714 + function setScreenOptions( $status, $option, $value ) {
715 + if ( 'visualizer_per_page_library' === $option ) {
716 + return $value;
717 + }
718 + }
719 +
720 + /**
721 + * Adds the display filters to be used in the meta_query while displaying the charts.
722 + */
723 + private function getDisplayFilters( &$query_args ) {
724 + $query = array();
725 +
726 + // add chart type filter to the query arguments
727 + $type = filter_input( INPUT_GET, 'type' );
728 + if ( $type && in_array( $type, Visualizer_Plugin::getChartTypes(), true ) ) {
729 + $query[] = array(
730 + 'key' => Visualizer_Plugin::CF_CHART_TYPE,
731 + 'value' => $type,
732 + 'compare' => '=',
733 + );
734 + }
735 +
736 + // add chart library filter to the query arguments
737 + $library = filter_input( INPUT_GET, 'library' );
738 + if ( $library ) {
739 + $query[] = array(
740 + 'key' => Visualizer_Plugin::CF_CHART_LIBRARY,
741 + 'value' => $library,
742 + 'compare' => '=',
743 + );
744 + }
745 +
746 + // add date filter to the query arguments
747 + $date = filter_input( INPUT_GET, 'date' );
748 + $possible = array_keys( Visualizer_Plugin::getSupportedDateFilter() );
749 + if ( $date && in_array( $date, $possible, true ) ) {
750 + $query_args['date_query'] = array(
751 + 'after' => "$date -1 day",
752 + 'inclusive' => true,
753 + );
754 + }
755 +
756 + // add source filter to the query arguments
757 + $source = filter_input( INPUT_GET, 'source' );
758 + if ( $source ) {
759 + $source = ucwords( $source );
760 + $source = "Visualizer_Source_{$source}";
761 + $query[] = array(
762 + 'key' => Visualizer_Plugin::CF_SOURCE,
763 + 'value' => $source,
764 + 'compare' => '=',
765 + );
766 + }
767 +
768 + $query_args['meta_query'] = $query;
769 +
770 + $orderby = filter_input( INPUT_GET, 'orderby' );
771 + $order = filter_input( INPUT_GET, 'order' );
772 + if ( $orderby ) {
773 + $query_args['order_by'] = $orderby;
774 + }
775 + $query_args['order'] = empty( $order ) ? 'desc' : $order;
776 + }
777 +
778 + /**
779 + * Get the instance of WP_Query that fetches the charts as per the given criteria.
780 + */
781 + private function getQuery() {
782 + static $q;
783 + if ( ! is_null( $q ) ) {
784 + return $q;
785 + }
786 +
398 787 // get current page
399 788 $page = filter_input(
400 - INPUT_GET, 'vpage', FILTER_VALIDATE_INT, array(
789 + INPUT_GET,
790 + 'vpage',
791 + FILTER_VALIDATE_INT,
792 + array(
401 793 'options' => array(
402 794 'min_range' => 1,
403 795 'default' => 1,
404 796 ),
@@ -403,27 +795,32 @@
403 795 'default' => 1,
404 796 ),
405 797 )
406 798 );
799 +
800 + $per_page = 6;
801 + $screen = get_current_screen();
802 + if ( $screen ) {
803 + // retrieve the per_page option
804 + $screen_option = $screen->get_option( 'per_page', 'option' );
805 + // retrieve the value stored for the current user
806 + $user = get_current_user_id();
807 + $per_page = get_user_meta( $user, $screen_option, true );
808 + if ( empty( $per_page ) || $per_page < 1 ) {
809 + // nothing set, get the default value
810 + $per_page = $screen->get_option( 'per_page', 'default' );
811 + }
812 + }
813 +
407 814 // the initial query arguments to fetch charts
408 815 $query_args = array(
409 816 'post_type' => Visualizer_Plugin::CPT_VISUALIZER,
410 - 'posts_per_page' => 6,
817 + 'posts_per_page' => $per_page,
411 818 'paged' => $page,
412 819 );
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 - }
820 +
821 + $this->getDisplayFilters( $query_args );
822 +
426 823 // Added by Ash/Upwork
427 824 $filterByMeta = filter_input( INPUT_GET, 's', FILTER_SANITIZE_STRING );
428 825 if ( $filterByMeta ) {
429 826 $query = array(
@@ -434,51 +831,146 @@
434 831 $meta = isset( $query_args['meta_query'] ) ? $query_args['meta_query'] : array();
435 832 $meta[] = $query;
436 833 $query_args['meta_query'] = $meta;
437 834 }
438 - // Added by Ash/Upwork
439 - // fetch charts
835 + $q = new WP_Query( apply_filters( 'visualizer_query_args', $query_args ) );
836 + return $q;
837 + }
838 +
839 + /**
840 + * Renders support page.
841 + *
842 + * @since 3.3.0
843 + *
844 + * @access public
845 + */
846 + public function renderSupportPage() {
847 + wp_enqueue_style( 'visualizer-upsell', VISUALIZER_ABSURL . 'css/upsell.css', array(), Visualizer_Plugin::VERSION );
848 + include_once VISUALIZER_ABSPATH . '/templates/support.php';
849 + }
850 +
851 + /**
852 + * Renders visualizer library page.
853 + *
854 + * @since 1.0.0
855 + *
856 + * @access public
857 + */
858 + public function renderLibraryPage() {
440 859 $charts = array();
441 - $query = new WP_Query( $query_args );
860 + $query = $this->getQuery();
861 +
862 + // get current page
863 + $page = filter_input(
864 + INPUT_GET,
865 + 'vpage',
866 + FILTER_VALIDATE_INT,
867 + array(
868 + 'options' => array(
869 + 'min_range' => 1,
870 + 'default' => 1,
871 + ),
872 + )
873 + );
874 + // add chart type filter to the query arguments
875 + $filter = filter_input( INPUT_GET, 'type' );
876 + if ( ! ( $filter && in_array( $filter, Visualizer_Plugin::getChartTypes(), true ) ) ) {
877 + $filter = 'all';
878 + }
879 +
880 + $css = '';
442 881 while ( $query->have_posts() ) {
443 882 $chart = $query->next_post();
883 +
884 + // if the user has updated a chart and instead of saving it, has closed the modal. If the user refreshes, they should get the original chart.
885 + $chart = $this->handleExistingRevisions( $chart->ID, $chart );
886 + // refresh a "live" db query chart.
887 + $chart = apply_filters( 'visualizer_schedule_refresh_chart', $chart, $chart->ID, false );
888 +
889 + $type = get_post_meta( $chart->ID, Visualizer_Plugin::CF_CHART_TYPE, true );
890 +
444 891 // fetch and update settings
445 892 $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 );
893 +
894 + $settings = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_SETTINGS, $settings, $chart->ID, $type );
895 + if ( ! empty( $atts['settings'] ) ) {
896 + $settings = apply_filters( $atts['settings'], $settings, $chart->ID, $type );
897 + }
898 +
899 + if ( $settings ) {
900 + unset( $settings['height'], $settings['width'], $settings['chartArea'] );
901 + }
902 +
448 903 $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 );
904 + $data = self::get_chart_data( $chart, $type );
905 +
906 + // Set default setting series when add manual chart data - Only during first creation.
907 + if ( isset( $settings['series'] ) && ! empty( $series ) ) {
908 + $count_series = count( $series ) - count( $settings['series'] );
909 + if ( $count_series > 1 ) {
910 + $clone_last_series = end( $settings['series'] );
911 + $clone_last_series = array_fill_keys( array_keys( $clone_last_series ), '' );
912 + foreach ( range( 1, $count_series ) as $item ) {
913 + $settings['series'][] = $clone_last_series;
914 + }
915 + }
916 + }
917 +
918 + $library = $this->load_chart_type( $chart->ID );
919 +
920 + $id = 'visualizer-' . $chart->ID;
921 + $arguments = $this->get_inline_custom_css( $id, $settings );
922 + if ( ! empty( $arguments ) ) {
923 + $css .= $arguments[0];
924 + $settings = $arguments[1];
925 + }
926 +
450 927 // add chart to the array
451 - $charts[ 'visualizer-' . $chart->ID ] = array(
928 + $charts[ $id ] = array(
452 929 'id' => $chart->ID,
453 930 'type' => $type,
454 931 'series' => $series,
455 932 'settings' => $settings,
456 933 'data' => $data,
934 + 'library' => $library,
457 935 );
458 936 }
459 937 // enqueue charts array
460 938 $ajaxurl = admin_url( 'admin-ajax.php' );
461 939 wp_localize_script(
462 - 'visualizer-library', 'visualizer', array(
940 + 'visualizer-library',
941 + 'visualizer',
942 + array(
463 943 'language' => $this->get_language(),
464 944 'map_api_key' => get_option( 'visualizer-map-api-key' ),
465 945 'charts' => $charts,
466 946 'urls' => array(
467 - 'base' => add_query_arg( 'vpage', false ),
947 + 'base' => add_query_arg( array( 'vpage' => false, 'vaction' => false ) ),
468 948 'create' => add_query_arg(
469 949 array(
470 950 'action' => Visualizer_Plugin::ACTION_CREATE_CHART,
471 951 'library' => 'yes',
472 - ), $ajaxurl
952 + 'type' => isset( $_GET['type'] ) ? $_GET['type'] : '',
953 + 'chart-library' => isset( $_GET['chart-library'] ) ? $_GET['chart-library'] : '',
954 + 'vaction' => false,
955 + ),
956 + $ajaxurl
473 957 ),
474 958 'edit' => add_query_arg(
475 959 array(
476 960 'action' => Visualizer_Plugin::ACTION_EDIT_CHART,
477 961 'library' => 'yes',
478 - ), $ajaxurl
962 + 'vaction' => false,
963 + ),
964 + $ajaxurl
479 965 ),
480 966 ),
967 + 'page_type' => 'library',
968 + 'is_front' => false,
969 + 'i10n' => array(
970 + 'copied' => __( 'The shortcode has been copied to your clipboard. Hit Ctrl-V/Cmd-V to paste it.', 'visualizer' ),
971 + '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' ),
972 + ),
481 973 )
482 974 );
483 975 // render library page
484 976 $render = new Visualizer_Render_Library();
@@ -483,12 +975,13 @@
483 975 // render library page
484 976 $render = new Visualizer_Render_Library();
485 977 $render->charts = $charts;
486 978 $render->type = $filter;
487 - $render->types = self::_getChartTypesLocalized();
979 + $render->types = self::_getChartTypesLocalized( false, false, false, true );
980 + $render->custom_css = $css;
488 981 $render->pagination = paginate_links(
489 982 array(
490 - 'base' => add_query_arg( 'vpage', '%#%' ),
983 + 'base' => add_query_arg( array( 'vpage' => '%#%', 'vaction' => false ) ),
491 984 'format' => '',
492 985 'current' => $page,
493 986 'total' => $query->max_num_pages,
494 987 'type' => 'array',
@@ -509,14 +1002,14 @@
509 1002 *
510 1003 * @return array Updated array of action links.
511 1004 */
512 1005 public function getPluginActionLinks( $links, $file ) {
513 - if ( $file == plugin_basename( VISUALIZER_BASEFILE ) ) {
1006 + if ( $file === plugin_basename( VISUALIZER_BASEFILE ) ) {
514 1007 array_unshift(
515 1008 $links,
516 1009 sprintf(
517 1010 '<a href="%s">%s</a>',
518 - admin_url( 'upload.php?page=' . Visualizer_Plugin::NAME ),
1011 + admin_url( 'admin.php?page=' . Visualizer_Plugin::NAME ),
519 1012 esc_html__( 'Library', 'visualizer' )
520 1013 )
521 1014 );
522 1015 }
@@ -536,17 +1029,17 @@
536 1029 *
537 1030 * @return array Updated array of plugin meta links.
538 1031 */
539 1032 public function getPluginMetaLinks( $plugin_meta, $plugin_file ) {
540 - if ( $plugin_file == plugin_basename( VISUALIZER_BASEFILE ) ) {
1033 + if ( $plugin_file === plugin_basename( VISUALIZER_BASEFILE ) ) {
541 1034 // knowledge base link
542 1035 $plugin_meta[] = sprintf(
543 - '<a href="https://github.com/codeinwp/visualizer/wiki" target="_blank">%s</a>',
544 - esc_html__( 'Knowledge Base', 'visualizer' )
1036 + '<a href="' . VISUALIZER_MAIN_DOC . '" target="_blank">%s</a>',
1037 + esc_html__( 'Docs', 'visualizer' )
545 1038 );
546 1039 // flattr link
547 1040 $plugin_meta[] = sprintf(
548 - '<a style="color:red" href="https://themeisle.com/plugins/visualizer-charts-and-graphs-pro-addon/" target="_blank">%s</a>',
1041 + '<a style="color:red" href="' . Visualizer_Plugin::PRO_TEASER_URL . '" target="_blank">%s</a>',
549 1042 esc_html__( 'Pro Addon', 'visualizer' )
550 1043 );
551 1044 }
552 1045