PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.7.3
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.7.3
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 +595 -80 3.0.63.7.3 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_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 );
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' ),
@@ -215,59 +388,91 @@
215 388 'enabled' => true,
216 389 );
217 390 }
218 391
392 + $enabled = self::proFeaturesLocked();
393 +
219 394 $types = array_merge(
220 - $additional, array(
395 + $additional,
396 + array(
397 + 'tabular' => array(
398 + 'name' => esc_html__( 'Table', 'visualizer' ),
399 + 'enabled' => true,
400 + 'supports' => $enabled ? array( 'Google Charts', 'DataTable' ) : array( 'DataTable' ),
401 + ),
221 402 'pie' => array(
222 - 'name' => esc_html__( 'Pie', 'visualizer' ),
403 + 'name' => esc_html__( 'Pie/Donut', 'visualizer' ),
223 404 'enabled' => true,
405 + 'supports' => $enabled ? array( 'Google Charts', 'ChartJS' ) : array( 'Google Charts' ),
224 406 ),
225 407 'line' => array(
226 408 'name' => esc_html__( 'Line', 'visualizer' ),
227 409 'enabled' => true,
410 + 'supports' => $enabled ? array( 'Google Charts', 'ChartJS' ) : array( 'Google Charts' ),
228 411 ),
412 + 'bar' => array(
413 + 'name' => esc_html__( 'Bar', 'visualizer' ),
414 + 'enabled' => true,
415 + 'supports' => $enabled ? array( 'Google Charts', 'ChartJS' ) : array( 'Google Charts' ),
416 + ),
229 417 'area' => array(
230 418 'name' => esc_html__( 'Area', 'visualizer' ),
231 - 'enabled' => true,
419 + 'enabled' => $enabled,
420 + // in ChartJS, the fill option is used to make Line chart an area: https://www.chartjs.org/docs/latest/charts/area.html
421 + 'supports' => array( 'Google Charts' ),
232 422 ),
233 423 'geo' => array(
234 424 'name' => esc_html__( 'Geo', 'visualizer' ),
235 - 'enabled' => true,
425 + 'enabled' => $enabled,
426 + 'supports' => array( 'Google Charts' ),
236 427 ),
237 - 'bar' => array(
238 - 'name' => esc_html__( 'Bar', 'visualizer' ),
239 - 'enabled' => true,
240 - ),
241 428 'column' => array(
242 429 'name' => esc_html__( 'Column', 'visualizer' ),
243 - 'enabled' => true,
430 + 'enabled' => $enabled,
431 + 'supports' => array( 'Google Charts', 'ChartJS' ),
244 432 ),
245 - 'gauge' => array(
246 - 'name' => esc_html__( 'Gauge', 'visualizer' ),
247 - 'enabled' => true,
433 + 'bubble' => array(
434 + 'name' => esc_html__( 'Bubble', 'visualizer' ),
435 + 'enabled' => $enabled,
436 + // chartjs' bubble is ugly looking (and it won't work off the default bubble.csv) so it is being excluded for the time being.
437 + 'supports' => array( 'Google Charts' ),
248 438 ),
249 439 'scatter' => array(
250 440 'name' => esc_html__( 'Scatter', 'visualizer' ),
251 - 'enabled' => true,
441 + 'enabled' => $enabled,
442 + 'supports' => array( 'Google Charts' ),
252 443 ),
444 + 'gauge' => array(
445 + 'name' => esc_html__( 'Gauge', 'visualizer' ),
446 + 'enabled' => $enabled,
447 + 'supports' => array( 'Google Charts' ),
448 + ),
253 449 'candlestick' => array(
254 450 'name' => esc_html__( 'Candlestick', 'visualizer' ),
255 - 'enabled' => true,
451 + 'enabled' => $enabled,
452 + 'supports' => array( 'Google Charts' ),
256 453 ),
257 454 // pro types
258 - 'table' => array(
259 - 'name' => esc_html__( 'Table', 'visualizer' ),
260 - 'enabled' => false,
261 - ),
262 455 'timeline' => array(
263 456 'name' => esc_html__( 'Timeline', 'visualizer' ),
264 457 'enabled' => false,
458 + 'supports' => array( 'Google Charts', 'ChartJS' ),
265 459 ),
266 460 'combo' => array(
267 461 'name' => esc_html__( 'Combo', 'visualizer' ),
268 462 'enabled' => false,
463 + 'supports' => array( 'Google Charts' ),
269 464 ),
465 + 'polarArea' => array(
466 + 'name' => esc_html__( 'Polar Area', 'visualizer' ),
467 + 'enabled' => false,
468 + 'supports' => array( 'ChartJS' ),
469 + ),
470 + 'radar' => array(
471 + 'name' => esc_html__( 'Radar/Spider', 'visualizer' ),
472 + 'enabled' => false,
473 + 'supports' => array( 'ChartJS' ),
474 + ),
270 475 )
271 476 );
272 477 $types = apply_filters( 'visualizer_pro_chart_types', $types );
273 478 if ( $enabledOnly ) {
@@ -276,8 +481,12 @@
276 481 if ( ! is_array( $array ) ) {
277 482 // support for old pro
278 483 $array = array( 'enabled' => true, 'name' => $array );
279 484 }
485 + // backward compatibility for PRO before v1.9.0
486 + if ( ! array_key_exists( 'supports', $array ) ) {
487 + $array['supports'] = array( 'Google Charts' );
488 + }
280 489 if ( ! $array['enabled'] ) {
281 490 continue;
282 491 }
283 492 $filtered[ $type ] = $array;
@@ -290,13 +499,74 @@
290 499 if ( ! is_array( $array ) ) {
291 500 // support for old pro
292 501 $array = array( 'enabled' => true, 'name' => $array );
293 502 }
503 + // backward compatibility for PRO before v1.9.0
504 + if ( ! array_key_exists( 'supports', $array ) ) {
505 + $array['supports'] = array( 'Google Charts' );
506 + }
294 507 $doubleD[ $type ] = $array['name'];
295 508 }
296 509 $types = $doubleD;
297 510 }
298 511
512 + return self::handleDeprecatedCharts( $types, $enabledOnly, $get2Darray, $where );
513 + }
514 +
515 + /**
516 + * Handle (soon-to-be) deprecated charts.
517 + */
518 + private static function handleDeprecatedCharts( $types, $enabledOnly, $get2Darray, $where ) {
519 + $deprecated = array();
520 +
521 + switch ( $where ) {
522 + case 'types':
523 + // fall-through
524 + case 'library':
525 + // if a user has a Gauge/Candlestick chart, then let them keep using it.
526 + if ( ! Visualizer_Module::is_pro() ) {
527 + if ( ! self::hasChartType( 'gauge' ) ) {
528 + if ( $get2Darray ) {
529 + $deprecated[] = 'gauge';
530 + } else {
531 + $types['gauge']['enabled'] = false;
532 + }
533 + }
534 + if ( ! self::hasChartType( 'candlestick' ) ) {
535 + if ( $get2Darray ) {
536 + $deprecated[] = 'candlestick';
537 + } else {
538 + $types['candlestick']['enabled'] = false;
539 + }
540 + }
541 + }
542 + break;
543 + default:
544 + // if a user has a Gauge/Candlestick chart, then let them keep using it.
545 + if ( ! Visualizer_Module::is_pro() ) {
546 + if ( ! self::hasChartType( 'gauge' ) ) {
547 + if ( $get2Darray ) {
548 + $deprecated[] = 'gauge';
549 + } else {
550 + $types['gauge']['enabled'] = false;
551 + }
552 + }
553 + if ( ! self::hasChartType( 'candlestick' ) ) {
554 + if ( $get2Darray ) {
555 + $deprecated[] = 'candlestick';
556 + } else {
557 + $types['candlestick']['enabled'] = false;
558 + }
559 + }
560 + }
561 + }
562 +
563 + if ( $deprecated ) {
564 + foreach ( $deprecated as $type ) {
565 + unset( $types[ $type ] );
566 + }
567 + }
568 +
299 569 return $types;
300 570 }
301 571
302 572 /**
@@ -306,11 +576,11 @@
306 576 * @global string $pagenow The name of the current page.
307 577 *
308 578 * @access public
309 579 */
310 - public function renderTempaltes() {
580 + public function renderTemplates() {
311 581 global $pagenow;
312 - if ( 'post.php' != $pagenow && 'post-new.php' != $pagenow ) {
582 + if ( 'post.php' !== $pagenow && 'post-new.php' !== $pagenow ) {
313 583 return;
314 584 }
315 585 $render = new Visualizer_Render_Templates();
316 586 $render->render();
@@ -328,26 +598,41 @@
328 598 *
329 599 * @param string $suffix The current page suffix.
330 600 */
331 601 public function enqueueLibraryScripts( $suffix ) {
332 - if ( $suffix == $this->_libraryPage ) {
602 + if ( $suffix === $this->_libraryPage ) {
333 603 wp_enqueue_style( 'visualizer-library', VISUALIZER_ABSURL . 'css/library.css', array(), Visualizer_Plugin::VERSION );
334 604 $this->_addFilter( 'media_upload_tabs', 'setupVisualizerTab' );
335 605 wp_enqueue_media();
336 606 wp_enqueue_script(
337 - 'visualizer-library', VISUALIZER_ABSURL . 'js/library.js', array(
607 + 'visualizer-library',
608 + VISUALIZER_ABSURL . 'js/library.js',
609 + array(
338 610 'jquery',
339 611 'media-views',
340 - ), Visualizer_Plugin::VERSION, true
612 + 'clipboard',
613 + ),
614 + Visualizer_Plugin::VERSION,
615 + true
341 616 );
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 - );
617 +
618 + wp_enqueue_script( 'visualizer-customization', $this->get_user_customization_js(), array(), null, true );
619 +
620 + $query = $this->getQuery();
621 + while ( $query->have_posts() ) {
622 + $chart = $query->next_post();
623 + $library = $this->load_chart_type( $chart->ID );
624 + if ( is_null( $library ) ) {
625 + continue;
626 + }
627 + wp_enqueue_script(
628 + "visualizer-render-$library",
629 + VISUALIZER_ABSURL . 'js/render-facade.js',
630 + apply_filters( 'visualizer_assets_render', array( 'visualizer-library', 'visualizer-customization' ), true ),
631 + Visualizer_Plugin::VERSION,
632 + true
633 + );
634 + }
350 635 }
351 636 }
352 637
353 638 /**
@@ -374,24 +659,140 @@
374 659 *
375 660 * @access public
376 661 */
377 662 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 );
663 + $svg_base64_icon = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iNzdweCIgaGVpZ2h0PSI3N3B4IiB2aWV3Qm94PSIwIDAgNzcgNzciIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICA8IS0tIEdlbmVyYXRvcjogU2tldGNoIDUyLjYgKDY3NDkxKSAtIGh0dHA6Ly93d3cuYm9oZW1pYW5jb2RpbmcuY29tL3NrZXRjaCAtLT4KICAgIDx0aXRsZT5Db21iaW5lZCBTaGFwZTwvdGl0bGU+CiAgICA8ZGVzYz5DcmVhdGVkIHdpdGggU2tldGNoLjwvZGVzYz4KICAgIDxnIGlkPSJQcm9kdWN0LVBhZ2UiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPgogICAgICAgIDxnIGlkPSJXb3JkUHJlc3MtcGx1Z2lucyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTE5MC4wMDAwMDAsIC00MzUuMDAwMDAwKSIgZmlsbD0iIzM5QzNEMiI+CiAgICAgICAgICAgIDxwYXRoIGQ9Ik0yMjguNSw1MTIgQzIwNy4yMzcwMzcsNTEyIDE5MCw0OTQuNzYyOTYzIDE5MCw0NzMuNSBDMTkwLDQ1Mi4yMzcwMzcgMjA3LjIzNzAzNyw0MzUgMjI4LjUsNDM1IEMyNDkuNzYyOTYzLDQzNSAyNjcsNDUyLjIzNzAzNyAyNjcsNDczLjUgQzI2Nyw0OTQuNzYyOTYzIDI0OS43NjI5NjMsNTEyIDIyOC41LDUxMiBaIE0yNDYuODQzNzUsNDgzLjU5MjA1OSBMMjE1LjYyNSw0ODMuNTkyMDU5IEwyMTUuNjI1LDQ2MC44MjY1NDQgQzIxNS42MjUsNDYwLjE2NDU0NyAyMTUuMTA3NTc4LDQ1OS42MjgzNTkgMjE0LjQ2ODc1LDQ1OS42MjgzNTkgTDIxMi4xNTYyNSw0NTkuNjI4MzU5IEMyMTEuNTE3NDIyLDQ1OS42MjgzNTkgMjExLDQ2MC4xNjQ1NDcgMjExLDQ2MC44MjY1NDQgTDIxMSw0ODUuOTg4NDI5IEMyMTEsNDg3LjMxMTY3NCAyMTIuMDM1NTY2LDQ4OC4zODQ3OTggMjEzLjMxMjUsNDg4LjM4NDc5OCBMMjQ2Ljg0Mzc1LDQ4OC4zODQ3OTggQzI0Ny40ODI1NzgsNDg4LjM4NDc5OCAyNDgsNDg3Ljg0ODYxMSAyNDgsNDg3LjE4NjYxMyBMMjQ4LDQ4NC43OTAyNDQgQzI0OCw0ODQuMTI4MjQ2IDI0Ny40ODI1NzgsNDgzLjU5MjA1OSAyNDYuODQzNzUsNDgzLjU5MjA1OSBaIE0yNDQuNTMxMjUsNDYyLjAyNDcyOSBMMjM1Ljk5OTU3LDQ2Mi4wMjQ3MjkgQzIzNC40NTQ1MzEsNDYyLjAyNDcyOSAyMzMuNjgwNTY2LDQ2My45NjA1NDcgMjM0Ljc3MzIyMyw0NjUuMDkyODMyIEwyMzcuMTE0NjI5LDQ2Ny41MTkxNTYgTDIzMS44MTI1LDQ3My4wMTQzMzIgTDIyNi41MTAzNzEsNDY3LjUxOTkwNSBDMjI1LjYwNzA1MSw0NjYuNTgzODIzIDIyNC4xNDI5NDksNDY2LjU4MzgyMyAyMjMuMjQwMzUyLDQ2Ny41MTk5MDUgTDIxOC4yNzY0MjYsNDcyLjY2Mzg2MyBDMjE3LjgyNDc2Niw0NzMuMTMxOTA0IDIxNy44MjQ3NjYsNDczLjg5MDUwNSAyMTguMjc2NDI2LDQ3NC4zNTg1NDYgTDIxOS45MTEwNzQsNDc2LjA1MjQ4IEMyMjAuMzYyNzM0LDQ3Ni41MjA1MjEgMjIxLjA5NDc4NSw0NzYuNTIwNTIxIDIyMS41NDY0NDUsNDc2LjA1MjQ4IEwyMjQuODc1LDQ3Mi42MDI0NTYgTDIzMC4xNzcxMjksNDc4LjA5Njg4MyBDMjMxLjA4MDQ0OSw0NzkuMDMyOTY1IDIzMi41NDQ1NTEsNDc5LjAzMjk2NSAyMzMuNDQ3MTQ4LDQ3OC4wOTY4ODMgTDI0MC4zODQ2NDgsNDcwLjkwNzc3MyBMMjQyLjcyNjA1NSw0NzMuMzM0MDk4IEMyNDMuODE4NzExLDQ3NC40NjYzODIgMjQ1LjY4Njc3Nyw0NzMuNjY0MzQ3IDI0NS42ODY3NzcsNDcyLjA2MzI3MyBMMjQ1LjY4Njc3Nyw0NjMuMjIyOTE0IEMyNDUuNjg3NSw0NjIuNTYwOTE3IDI0NS4xNzAwNzgsNDYyLjAyNDcyOSAyNDQuNTMxMjUsNDYyLjAyNDcyOSBaIiBpZD0iQ29tYmluZWQtU2hhcGUiPjwvcGF0aD4KICAgICAgICA8L2c+CiAgICA8L2c+Cjwvc3ZnPg==';
664 +
665 + $this->_libraryPage = add_menu_page( __( 'Visualizer', 'visualizer' ), __( 'Visualizer', 'visualizer' ), 'edit_posts', Visualizer_Plugin::NAME, array( $this, 'renderLibraryPage' ), $svg_base64_icon, 99.7666 );
666 +
667 + add_submenu_page(
668 + Visualizer_Plugin::NAME,
669 + __( 'Chart Library', 'visualizer' ),
670 + __( 'Chart Library', 'visualizer' ),
671 + 'edit_posts',
672 + admin_url( 'admin.php?page=' . Visualizer_Plugin::NAME )
673 + );
674 + add_submenu_page(
675 + Visualizer_Plugin::NAME,
676 + __( 'Add New Chart', 'visualizer' ),
677 + __( 'Add New Chart', 'visualizer' ),
678 + 'edit_posts',
679 + admin_url( 'admin.php?page=' . Visualizer_Plugin::NAME . '&vaction=addnew' )
680 + );
681 + add_submenu_page(
682 + Visualizer_Plugin::NAME,
683 + __( 'Support', 'visualizer' ),
684 + __( 'Support', 'visualizer' ) . '<span class="dashicons dashicons-editor-help more-features-icon" style="width: 17px; height: 17px; margin-left: 4px; color: #ffca54; font-size: 17px; vertical-align: -3px;"></span>',
685 + 'edit_posts',
686 + 'viz-support',
687 + array( $this, 'renderSupportPage' )
688 + );
689 + remove_submenu_page( Visualizer_Plugin::NAME, Visualizer_Plugin::NAME );
690 +
691 + add_action( "load-{$this->_libraryPage}", array( $this, 'addScreenOptions' ) );
381 692 }
382 693
383 694 /**
384 - * Renders visualizer library page.
385 - *
386 - * @since 1.0.0
387 - *
388 - * @access public
695 + * Adds the screen options for pagination.
389 696 */
390 - public function renderLibraryPage() {
697 + function addScreenOptions() {
698 + $screen = get_current_screen();
699 +
700 + // bail if it's some other page.
701 + if ( ! is_object( $screen ) || $screen->id !== $this->_libraryPage ) {
702 + return;
703 + }
704 +
705 + $args = array(
706 + 'label' => __( 'Number of charts per page:', 'visualizer' ),
707 + 'default' => 6,
708 + 'option' => 'visualizer_library_per_page',
709 + );
710 + add_screen_option( 'per_page', $args );
711 + }
712 +
713 + /**
714 + * Returns the screen option for pagination.
715 + */
716 + function setScreenOptions( $status, $option, $value ) {
717 + if ( 'visualizer_library_per_page' === $option ) {
718 + return $value;
719 + }
720 + }
721 +
722 + /**
723 + * Adds the display filters to be used in the meta_query while displaying the charts.
724 + */
725 + private function getDisplayFilters( &$query_args ) {
726 + $query = array();
727 +
728 + // add chart type filter to the query arguments
729 + $type = filter_input( INPUT_GET, 'type' );
730 + if ( $type && in_array( $type, Visualizer_Plugin::getChartTypes(), true ) ) {
731 + $query[] = array(
732 + 'key' => Visualizer_Plugin::CF_CHART_TYPE,
733 + 'value' => $type,
734 + 'compare' => '=',
735 + );
736 + }
737 +
738 + // add chart library filter to the query arguments
739 + $library = filter_input( INPUT_GET, 'library' );
740 + if ( $library ) {
741 + $query[] = array(
742 + 'key' => Visualizer_Plugin::CF_CHART_LIBRARY,
743 + 'value' => $library,
744 + 'compare' => '=',
745 + );
746 + }
747 +
748 + // add date filter to the query arguments
749 + $date = filter_input( INPUT_GET, 'date' );
750 + $possible = array_keys( Visualizer_Plugin::getSupportedDateFilter() );
751 + if ( $date && in_array( $date, $possible, true ) ) {
752 + $query_args['date_query'] = array(
753 + 'after' => "$date -1 day",
754 + 'inclusive' => true,
755 + );
756 + }
757 +
758 + // add source filter to the query arguments
759 + $source = filter_input( INPUT_GET, 'source' );
760 + if ( $source ) {
761 + $source = ucwords( $source );
762 + $source = "Visualizer_Source_{$source}";
763 + $query[] = array(
764 + 'key' => Visualizer_Plugin::CF_SOURCE,
765 + 'value' => $source,
766 + 'compare' => '=',
767 + );
768 + }
769 +
770 + $query_args['meta_query'] = $query;
771 +
772 + $orderby = filter_input( INPUT_GET, 'orderby' );
773 + $order = filter_input( INPUT_GET, 'order' );
774 + if ( $orderby ) {
775 + $query_args['order_by'] = $orderby;
776 + }
777 + $query_args['order'] = empty( $order ) ? 'desc' : $order;
778 + }
779 +
780 + /**
781 + * Get the instance of WP_Query that fetches the charts as per the given criteria.
782 + */
783 + private function getQuery() {
784 + static $q;
785 + if ( ! is_null( $q ) ) {
786 + return $q;
787 + }
788 +
391 789 // get current page
392 790 $page = filter_input(
393 - INPUT_GET, 'vpage', FILTER_VALIDATE_INT, array(
791 + INPUT_GET,
792 + 'vpage',
793 + FILTER_VALIDATE_INT,
794 + array(
394 795 'options' => array(
395 796 'min_range' => 1,
396 797 'default' => 1,
397 798 ),
@@ -396,27 +797,32 @@
396 797 'default' => 1,
397 798 ),
398 799 )
399 800 );
801 +
802 + $per_page = 6;
803 + $screen = get_current_screen();
804 + if ( $screen ) {
805 + // retrieve the per_page option
806 + $screen_option = $screen->get_option( 'per_page', 'option' );
807 + // retrieve the value stored for the current user
808 + $user = get_current_user_id();
809 + $per_page = get_user_meta( $user, $screen_option, true );
810 + if ( empty( $per_page ) || $per_page < 1 ) {
811 + // nothing set, get the default value
812 + $per_page = $screen->get_option( 'per_page', 'default' );
813 + }
814 + }
815 +
400 816 // the initial query arguments to fetch charts
401 817 $query_args = array(
402 818 'post_type' => Visualizer_Plugin::CPT_VISUALIZER,
403 - 'posts_per_page' => 6,
819 + 'posts_per_page' => $per_page,
404 820 'paged' => $page,
405 821 );
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 - }
822 +
823 + $this->getDisplayFilters( $query_args );
824 +
419 825 // Added by Ash/Upwork
420 826 $filterByMeta = filter_input( INPUT_GET, 's', FILTER_SANITIZE_STRING );
421 827 if ( $filterByMeta ) {
422 828 $query = array(
@@ -427,49 +833,146 @@
427 833 $meta = isset( $query_args['meta_query'] ) ? $query_args['meta_query'] : array();
428 834 $meta[] = $query;
429 835 $query_args['meta_query'] = $meta;
430 836 }
431 - // Added by Ash/Upwork
432 - // fetch charts
837 + $q = new WP_Query( apply_filters( 'visualizer_query_args', $query_args ) );
838 + return $q;
839 + }
840 +
841 + /**
842 + * Renders support page.
843 + *
844 + * @since 3.3.0
845 + *
846 + * @access public
847 + */
848 + public function renderSupportPage() {
849 + wp_enqueue_style( 'visualizer-upsell', VISUALIZER_ABSURL . 'css/upsell.css', array(), Visualizer_Plugin::VERSION );
850 + include_once VISUALIZER_ABSPATH . '/templates/support.php';
851 + }
852 +
853 + /**
854 + * Renders visualizer library page.
855 + *
856 + * @since 1.0.0
857 + *
858 + * @access public
859 + */
860 + public function renderLibraryPage() {
433 861 $charts = array();
434 - $query = new WP_Query( $query_args );
862 + $query = $this->getQuery();
863 +
864 + // get current page
865 + $page = filter_input(
866 + INPUT_GET,
867 + 'vpage',
868 + FILTER_VALIDATE_INT,
869 + array(
870 + 'options' => array(
871 + 'min_range' => 1,
872 + 'default' => 1,
873 + ),
874 + )
875 + );
876 + // add chart type filter to the query arguments
877 + $filter = filter_input( INPUT_GET, 'type' );
878 + if ( ! ( $filter && in_array( $filter, Visualizer_Plugin::getChartTypes(), true ) ) ) {
879 + $filter = 'all';
880 + }
881 +
882 + $css = '';
435 883 while ( $query->have_posts() ) {
436 884 $chart = $query->next_post();
885 +
886 + // 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.
887 + $chart = $this->handleExistingRevisions( $chart->ID, $chart );
888 + // refresh a "live" db query chart.
889 + $chart = apply_filters( 'visualizer_schedule_refresh_chart', $chart, $chart->ID, false );
890 +
891 + $type = get_post_meta( $chart->ID, Visualizer_Plugin::CF_CHART_TYPE, true );
892 +
437 893 // fetch and update settings
438 894 $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 );
895 +
896 + $settings = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_SETTINGS, $settings, $chart->ID, $type );
897 + if ( ! empty( $atts['settings'] ) ) {
898 + $settings = apply_filters( $atts['settings'], $settings, $chart->ID, $type );
899 + }
900 +
901 + if ( $settings ) {
902 + unset( $settings['height'], $settings['width'], $settings['chartArea'] );
903 + }
904 +
441 905 $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 );
906 + $data = self::get_chart_data( $chart, $type );
907 +
908 + // Set default setting series when add manual chart data - Only during first creation.
909 + if ( isset( $settings['series'] ) && ! empty( $series ) ) {
910 + $count_series = count( $series ) - count( $settings['series'] );
911 + if ( $count_series > 1 ) {
912 + $clone_last_series = end( $settings['series'] );
913 + $clone_last_series = array_fill_keys( array_keys( $clone_last_series ), '' );
914 + foreach ( range( 1, $count_series ) as $item ) {
915 + $settings['series'][] = $clone_last_series;
916 + }
917 + }
918 + }
919 +
920 + $library = $this->load_chart_type( $chart->ID );
921 +
922 + $id = 'visualizer-' . $chart->ID;
923 + $arguments = $this->get_inline_custom_css( $id, $settings );
924 + if ( ! empty( $arguments ) ) {
925 + $css .= $arguments[0];
926 + $settings = $arguments[1];
927 + }
928 +
443 929 // add chart to the array
444 - $charts[ 'visualizer-' . $chart->ID ] = array(
930 + $charts[ $id ] = array(
445 931 'id' => $chart->ID,
446 932 'type' => $type,
447 933 'series' => $series,
448 934 'settings' => $settings,
449 935 'data' => $data,
936 + 'library' => $library,
450 937 );
451 938 }
452 939 // enqueue charts array
453 940 $ajaxurl = admin_url( 'admin-ajax.php' );
454 941 wp_localize_script(
455 - 'visualizer-library', 'visualizer', array(
942 + 'visualizer-library',
943 + 'visualizer',
944 + array(
945 + 'language' => $this->get_language(),
946 + 'map_api_key' => get_option( 'visualizer-map-api-key' ),
456 947 'charts' => $charts,
457 948 'urls' => array(
458 - 'base' => add_query_arg( 'vpage', false ),
949 + 'base' => add_query_arg( array( 'vpage' => false, 'vaction' => false ) ),
459 950 'create' => add_query_arg(
460 951 array(
461 952 'action' => Visualizer_Plugin::ACTION_CREATE_CHART,
462 953 'library' => 'yes',
463 - ), $ajaxurl
954 + 'type' => isset( $_GET['type'] ) ? $_GET['type'] : '',
955 + 'chart-library' => isset( $_GET['chart-library'] ) ? $_GET['chart-library'] : '',
956 + 'vaction' => false,
957 + ),
958 + $ajaxurl
464 959 ),
465 960 'edit' => add_query_arg(
466 961 array(
467 962 'action' => Visualizer_Plugin::ACTION_EDIT_CHART,
468 963 'library' => 'yes',
469 - ), $ajaxurl
964 + 'vaction' => false,
965 + ),
966 + $ajaxurl
470 967 ),
471 968 ),
969 + 'page_type' => 'library',
970 + 'is_front' => false,
971 + 'i10n' => array(
972 + 'copied' => __( 'The shortcode has been copied to your clipboard. Hit Ctrl-V/Cmd-V to paste it.', 'visualizer' ),
973 + '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' ),
974 + ),
472 975 )
473 976 );
474 977 // render library page
475 978 $render = new Visualizer_Render_Library();
@@ -474,12 +977,13 @@
474 977 // render library page
475 978 $render = new Visualizer_Render_Library();
476 979 $render->charts = $charts;
477 980 $render->type = $filter;
478 - $render->types = self::_getChartTypesLocalized();
981 + $render->types = self::_getChartTypesLocalized( false, false, false, true );
982 + $render->custom_css = $css;
479 983 $render->pagination = paginate_links(
480 984 array(
481 - 'base' => add_query_arg( 'vpage', '%#%' ),
985 + 'base' => add_query_arg( array( 'vpage' => '%#%', 'vaction' => false ) ),
482 986 'format' => '',
483 987 'current' => $page,
484 988 'total' => $query->max_num_pages,
485 989 'type' => 'array',
@@ -500,14 +1004,14 @@
500 1004 *
501 1005 * @return array Updated array of action links.
502 1006 */
503 1007 public function getPluginActionLinks( $links, $file ) {
504 - if ( $file == plugin_basename( VISUALIZER_BASEFILE ) ) {
1008 + if ( $file === plugin_basename( VISUALIZER_BASEFILE ) ) {
505 1009 array_unshift(
506 1010 $links,
507 1011 sprintf(
508 1012 '<a href="%s">%s</a>',
509 - admin_url( 'upload.php?page=' . Visualizer_Plugin::NAME ),
1013 + admin_url( 'admin.php?page=' . Visualizer_Plugin::NAME ),
510 1014 esc_html__( 'Library', 'visualizer' )
511 1015 )
512 1016 );
513 1017 }
@@ -527,17 +1031,17 @@
527 1031 *
528 1032 * @return array Updated array of plugin meta links.
529 1033 */
530 1034 public function getPluginMetaLinks( $plugin_meta, $plugin_file ) {
531 - if ( $plugin_file == plugin_basename( VISUALIZER_BASEFILE ) ) {
1035 + if ( $plugin_file === plugin_basename( VISUALIZER_BASEFILE ) ) {
532 1036 // knowledge base link
533 1037 $plugin_meta[] = sprintf(
534 - '<a href="https://github.com/codeinwp/visualizer/wiki" target="_blank">%s</a>',
535 - esc_html__( 'Knowledge Base', 'visualizer' )
1038 + '<a href="' . VISUALIZER_MAIN_DOC . '" target="_blank">%s</a>',
1039 + esc_html__( 'Docs', 'visualizer' )
536 1040 );
537 1041 // flattr link
538 1042 $plugin_meta[] = sprintf(
539 - '<a style="color:red" href="https://themeisle.com/plugins/visualizer-charts-and-graphs-pro-addon/" target="_blank">%s</a>',
1043 + '<a style="color:red" href="' . Visualizer_Plugin::PRO_TEASER_URL . '" target="_blank">%s</a>',
540 1044 esc_html__( 'Pro Addon', 'visualizer' )
541 1045 );
542 1046 }
543 1047
@@ -543,5 +1047,16 @@
543 1047
544 1048 return $plugin_meta;
545 1049 }
546 1050
1051 + /**
1052 + * If check is existing user.
1053 + *
1054 + * @return bool Default false
1055 + */
1056 + public static function proFeaturesLocked() {
1057 + if ( Visualizer_Module::is_pro() ) {
1058 + return true;
1059 + }
1060 + return 'yes' === get_option( 'visualizer-new-user', 'yes' ) ? false : true;
1061 + }
547 1062 }