PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.4.2
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.4.2
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
visualizer / classes / Visualizer / Module / Admin.php

Admin.php in Visualizer – Tables & Charts Manager with Built-in AI Generator 3.4.2, at classes/Visualizer/Module/Admin.php

963 lines 31.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 // +----------------------------------------------------------------------+
3 // | Copyright 2013 Madpixels (email : visualizer@madpixels.net) |
4 // +----------------------------------------------------------------------+
5 // | This program is free software; you can redistribute it and/or modify |
6 // | it under the terms of the GNU General Public License, version 2, as |
7 // | published by the Free Software Foundation. |
8 // | |
9 // | This program is distributed in the hope that it will be useful, |
10 // | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 // | GNU General Public License for more details. |
13 // | |
14 // | You should have received a copy of the GNU General Public License |
15 // | along with this program; if not, write to the Free Software |
16 // | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, |
17 // | MA 02110-1301 USA |
18 // +----------------------------------------------------------------------+
19 // | Author: Eugene Manuilov <eugene@manuilov.org> |
20 // +----------------------------------------------------------------------+
21 /**
22 * The module for all admin stuff.
23 *
24 * @category Visualizer
25 * @package Module
26 *
27 * @since 1.0.0
28 */
29 class Visualizer_Module_Admin extends Visualizer_Module {
30
31 const NAME = __CLASS__;
32
33 /**
34 * Library page suffix.
35 *
36 * @since 1.0.0
37 *
38 * @access private
39 * @var string
40 */
41 private $_libraryPage;
42
43 /**
44 * Constructor.
45 *
46 * @since 1.0.0
47 *
48 * @access public
49 *
50 * @param Visualizer_Plugin $plugin The instance of the plugin.
51 */
52 public function __construct( Visualizer_Plugin $plugin ) {
53 parent::__construct( $plugin );
54 $this->_addAction( 'load-post.php', 'enqueueMediaScripts' );
55 $this->_addAction( 'load-post-new.php', 'enqueueMediaScripts' );
56 $this->_addAction( 'admin_footer', 'renderTemplates' );
57 $this->_addAction( 'admin_enqueue_scripts', 'enqueueLibraryScripts', null, 8 );
58 $this->_addAction( 'admin_menu', 'registerAdminMenu' );
59 $this->_addFilter( 'media_view_strings', 'setupMediaViewStrings' );
60 $this->_addFilter( 'plugin_action_links', 'getPluginActionLinks', 10, 2 );
61 $this->_addFilter( 'plugin_row_meta', 'getPluginMetaLinks', 10, 2 );
62 $this->_addFilter( 'visualizer_logger_data', 'getLoggerData' );
63 $this->_addFilter( 'visualizer_get_chart_counts', 'getChartCountsByTypeAndMeta' );
64 $this->_addFilter( 'visualizer_feedback_review_trigger', 'feedbackReviewTrigger' );
65
66 // revision support.
67 $this->_addFilter( 'wp_revisions_to_keep', 'limitRevisions', null, 10, 2 );
68 $this->_addAction( '_wp_put_post_revision', 'addRevision', null, 10, 1 );
69 $this->_addAction( 'wp_restore_post_revision', 'restoreRevision', null, 10, 2 );
70
71 $this->_addAction( 'visualizer_chart_schedules_spl', 'addSplChartSchedules', null, 10, 3 );
72
73 $this->_addAction( 'admin_init', 'init' );
74
75 if ( defined( 'TI_CYPRESS_TESTING' ) ) {
76 $this->load_cypress_hooks();
77 }
78
79 }
80
81 /**
82 * Define the hooks that are needed for cypress.
83 *
84 * @since 3.4.0
85 * @access private
86 */
87 private function load_cypress_hooks() {
88 // all charts should load on the same page without pagination.
89 add_filter(
90 'visualizer_query_args', function( $args ) {
91 $args['posts_per_page'] = 20;
92 return $args;
93 }, 10, 1
94 );
95 }
96
97 /**
98 * Add disabled `optgroup` schedules to the drop downs.
99 *
100 * @since ?
101 *
102 * @access public
103 *
104 * @param string $feature The feature for which to add schedules.
105 * @param int $chart_id The chart ID.
106 * @param int $plan The plan number.
107 */
108 public function addSplChartSchedules( $feature, $chart_id, $plan ) {
109 if ( apply_filters( 'visualizer_is_business', false ) ) {
110 return;
111 }
112
113 $license = __( 'PRO', 'visualizer' );
114 if ( Visualizer_Module::is_pro() ) {
115 switch ( $plan ) {
116 case 1:
117 $license = __( 'Developer', 'visualizer' );
118 break;
119 }
120 }
121
122 $hours = array(
123 '0' => __( 'Live', 'visualizer' ),
124 '1' => __( 'Each hour', 'visualizer' ),
125 '12' => __( 'Each 12 hours', 'visualizer' ),
126 '24' => __( 'Each day', 'visualizer' ),
127 '72' => __( 'Each 3 days', 'visualizer' ),
128 );
129
130 switch ( $feature ) {
131 case 'json':
132 case 'csv':
133 // no more schedules if pro is already active.
134 if ( Visualizer_Module::is_pro() ) {
135 return;
136 }
137 break;
138 case 'wp':
139 // fall-through.
140 case 'db':
141 break;
142 default:
143 return;
144 }
145
146 echo '<optgroup disabled label="' . sprintf( __( 'More in the %s version', 'visualizer' ), $license ) . '">';
147 foreach ( $hours as $hour => $desc ) {
148 echo '<option disabled>' . $desc . '</option>';
149 }
150 echo '</optgroup>';
151 }
152
153 /**
154 * No limits on revisions.
155 */
156 public function limitRevisions( $num, $post ) {
157 if ( Visualizer_Plugin::CPT_VISUALIZER === $post->post_type ) {
158 return -1;
159 }
160 return $num;
161 }
162
163 /**
164 * Add a revision.
165 */
166 public function addRevision( $revision_id ) {
167 $parent_id = wp_is_post_revision( $revision_id );
168 if ( Visualizer_Plugin::CPT_VISUALIZER === get_post_type( $parent_id ) ) {
169 // add the meta data to this revision.
170 $meta = get_post_meta( $parent_id, '', true );
171
172 if ( $meta ) {
173 foreach ( $meta as $key => $value ) {
174 if ( 0 === strpos( $key, 'visualizer' ) ) {
175 add_metadata( 'post', $revision_id, $key, maybe_unserialize( $value[0] ) );
176 }
177 }
178 }
179 }
180 }
181
182 /**
183 * Restore a revision.
184 */
185 public function restoreRevision( $post_id, $revision_id ) {
186 if ( Visualizer_Plugin::CPT_VISUALIZER === get_post_type( $post_id ) ) {
187 // get the meta information from the revision.
188 $meta = get_metadata( 'post', $revision_id, '', true );
189
190 // delete all meta information from the post before adding.
191 $post_meta = get_post_meta( $post_id, '', true );
192 if ( $post_meta ) {
193 foreach ( $meta as $key => $value ) {
194 if ( 0 === strpos( $key, 'visualizer' ) ) {
195 delete_post_meta( $post_id, $key );
196 }
197 }
198 }
199
200 if ( $meta ) {
201 foreach ( $meta as $key => $value ) {
202 if ( 0 === strpos( $key, 'visualizer' ) ) {
203 add_post_meta( $post_id, $key, maybe_unserialize( $value[0] ) );
204 }
205 }
206 }
207 }
208 }
209
210 /**
211 * Admin init.
212 *
213 * @access public
214 */
215 public function init() {
216 // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
217 if ( current_user_can( 'edit_posts' ) && current_user_can( 'edit_pages' ) && 'true' == get_user_option( 'rich_editing' ) ) {
218 $this->_addFilter( 'mce_external_languages', 'add_tinymce_lang', 10, 1 );
219 $this->_addFilter( 'mce_external_plugins', 'tinymce_plugin', 10, 1 );
220 $this->_addFilter( 'mce_buttons', 'register_mce_button', 10, 1 );
221 $this->_addFilter( 'tiny_mce_before_init', 'get_strings_for_block', 10, 1 );
222 }
223 }
224
225 /**
226 * Add the strings required for the TinyMCE buttons for the classic block (not the classic editor).
227 *
228 * @since ?
229 * @access friendly
230 */
231 function get_strings_for_block( $settings ) {
232 $class = new Visualizer_Module_Language();
233 $strings = $class->get_strings();
234 $array = array( 'visualizer_tinymce_plugin' => json_encode( $strings ) );
235 return array_merge( $settings, $array );
236 }
237
238 /**
239 * Load plugin translation for - TinyMCE API
240 *
241 * @access public
242 * @param array $arr The tinymce_lang array.
243 * @return array
244 */
245 public function add_tinymce_lang( $arr ) {
246 $ui_lang = VISUALIZER_ABSPATH . '/classes/Visualizer/Module/Language.php';
247 $ui_lang = apply_filters( 'visualizer_ui_lang_filter', $ui_lang );
248 $arr[] = $ui_lang;
249 return $arr;
250 }
251
252 /**
253 * Load custom js options - TinyMCE API
254 *
255 * @access public
256 * @param array $plugin_array The tinymce plugin array.
257 * @return array
258 */
259 public function tinymce_plugin( $plugin_array ) {
260 $plugin_array['visualizer_mce_button'] = VISUALIZER_ABSURL . 'js/mce.js';
261 return $plugin_array;
262 }
263
264 /**
265 * Register new button in the editor
266 *
267 * @access public
268 * @param array $buttons The tinymce buttons array.
269 * @return array
270 */
271 public function register_mce_button( $buttons ) {
272 array_push( $buttons, 'visualizer_mce_button' );
273 return $buttons;
274 }
275
276 /**
277 * Whether to show the feedback review or not.
278 *
279 * @access public
280 */
281 public function feedbackReviewTrigger( $dumb ) {
282 $query = new WP_Query(
283 array(
284 'posts_per_page' => 50,
285 'post_type' => Visualizer_Plugin::CPT_VISUALIZER,
286 'fields' => 'ids',
287 'update_post_meta_cache' => false,
288 'update_post_term_cache' => false,
289 )
290 );
291
292 if ( $query->have_posts() && $query->post_count > 0 ) {
293 return true;
294 }
295 return false;
296 }
297
298 /**
299 * Enqueues media scripts and styles.
300 *
301 * @since 1.0.0
302 * @uses wp_enqueue_style To enqueue style file.
303 * @uses wp_enqueue_script To enqueue script file.
304 *
305 * @access public
306 */
307 public function enqueueMediaScripts() {
308 global $typenow;
309 if ( post_type_supports( $typenow, 'editor' ) ) {
310 wp_enqueue_style( 'visualizer-media', VISUALIZER_ABSURL . 'css/media.css', array( 'media-views' ), Visualizer_Plugin::VERSION );
311
312 // Load all the assets for the different libraries we support.
313 $deps = array(
314 Visualizer_Render_Sidebar_Google::enqueue_assets( array( 'media-editor' ) ),
315 Visualizer_Render_Sidebar_Type_DataTable_DataTable::enqueue_assets( array( 'media-editor' ) ),
316 );
317
318 wp_enqueue_script( 'visualizer-media-model', VISUALIZER_ABSURL . 'js/media/model.js', $deps, Visualizer_Plugin::VERSION, true );
319 wp_enqueue_script( 'visualizer-media-collection', VISUALIZER_ABSURL . 'js/media/collection.js', array( 'visualizer-media-model' ), Visualizer_Plugin::VERSION, true );
320 wp_enqueue_script( 'visualizer-media-controller', VISUALIZER_ABSURL . 'js/media/controller.js', array( 'visualizer-media-collection' ), Visualizer_Plugin::VERSION, true );
321 wp_enqueue_script( 'visualizer-media-view', VISUALIZER_ABSURL . 'js/media/view.js', array( 'visualizer-media-controller' ), Visualizer_Plugin::VERSION, true );
322 wp_localize_script(
323 'visualizer-media-view',
324 'visualizer',
325 array(
326 'i10n' => array(
327 'insert' => __( 'Insert', 'visualizer' ),
328 ),
329 )
330 );
331 wp_enqueue_script( 'visualizer-media-toolbar', VISUALIZER_ABSURL . 'js/media/toolbar.js', array( 'visualizer-media-view' ), Visualizer_Plugin::VERSION, true );
332 wp_enqueue_script( 'visualizer-media', VISUALIZER_ABSURL . 'js/media.js', array( 'visualizer-media-toolbar' ), Visualizer_Plugin::VERSION, true );
333 }
334 }
335
336 /**
337 * Extends media view strings with visualizer strings.
338 *
339 * @since 1.0.0
340 *
341 * @access public
342 *
343 * @param array $strings The array of media view strings.
344 *
345 * @return array The extended array of media view strings.
346 */
347 public function setupMediaViewStrings( $strings ) {
348 $chart_types = self::_getChartTypesLocalized( true, true, true );
349 $strings['visualizer'] = array(
350 'actions' => array(
351 'get_charts' => Visualizer_Plugin::ACTION_GET_CHARTS,
352 'delete_chart' => Visualizer_Plugin::ACTION_DELETE_CHART,
353 ),
354 'controller' => array(
355 'title' => esc_html__( 'Visualizations', 'visualizer' ),
356 ),
357 'routers' => array(
358 'library' => esc_html__( 'From Library', 'visualizer' ),
359 'create' => esc_html__( 'Create New', 'visualizer' ),
360 ),
361 'library' => array(
362 'filters' => $chart_types,
363 'types' => array_keys( $chart_types ),
364 ),
365 'nonce' => wp_create_nonce(),
366 'buildurl' => add_query_arg( 'action', Visualizer_Plugin::ACTION_CREATE_CHART, admin_url( 'admin-ajax.php' ) ),
367 );
368
369 return $strings;
370 }
371
372 /**
373 * Returns associated array of chart types and localized names.
374 *
375 * @since 1.0.0
376 *
377 * @static
378 * @access private
379 * @return array The associated array of chart types with localized names.
380 */
381 public static function _getChartTypesLocalized( $enabledOnly = false, $get2Darray = false, $add_select = false, $where = null ) {
382 $additional = array();
383 if ( $add_select ) {
384 $additional['select'] = array(
385 'name' => esc_html__( 'All', 'visualizer' ),
386 'enabled' => true,
387 );
388 }
389
390 $types = array_merge(
391 $additional,
392 array(
393 'dataTable' => array(
394 'name' => esc_html__( 'Table', 'visualizer' ),
395 'enabled' => true,
396 'supports' => array( 'DataTable' ),
397 ),
398 'pie' => array(
399 'name' => esc_html__( 'Pie/Donut', 'visualizer' ),
400 'enabled' => true,
401 'supports' => array( 'Google Charts', 'ChartJS' ),
402 ),
403 'line' => array(
404 'name' => esc_html__( 'Line', 'visualizer' ),
405 'enabled' => true,
406 'supports' => array( 'Google Charts', 'ChartJS' ),
407 ),
408 'area' => array(
409 'name' => esc_html__( 'Area', 'visualizer' ),
410 'enabled' => true,
411 // in ChartJS, the fill option is used to make Line chart an area: https://www.chartjs.org/docs/latest/charts/area.html
412 'supports' => array( 'Google Charts' ),
413 ),
414 'geo' => array(
415 'name' => esc_html__( 'Geo', 'visualizer' ),
416 'enabled' => true,
417 'supports' => array( 'Google Charts' ),
418 ),
419 'bar' => array(
420 'name' => esc_html__( 'Bar', 'visualizer' ),
421 'enabled' => true,
422 'supports' => array( 'Google Charts', 'ChartJS' ),
423 ),
424 'column' => array(
425 'name' => esc_html__( 'Column', 'visualizer' ),
426 'enabled' => true,
427 'supports' => array( 'Google Charts', 'ChartJS' ),
428 ),
429 'bubble' => array(
430 'name' => esc_html__( 'Bubble', 'visualizer' ),
431 'enabled' => true,
432 // chartjs' bubble is ugly looking (and it won't work off the default bubble.csv) so it is being excluded for the time being.
433 'supports' => array( 'Google Charts' ),
434 ),
435 'scatter' => array(
436 'name' => esc_html__( 'Scatter', 'visualizer' ),
437 'enabled' => true,
438 'supports' => array( 'Google Charts' ),
439 ),
440 'gauge' => array(
441 'name' => esc_html__( 'Gauge', 'visualizer' ),
442 'enabled' => true,
443 'supports' => array( 'Google Charts' ),
444 ),
445 'candlestick' => array(
446 'name' => esc_html__( 'Candlestick', 'visualizer' ),
447 'enabled' => true,
448 'supports' => array( 'Google Charts' ),
449 ),
450 // pro types
451 'table' => array(
452 'name' => esc_html__( 'Table (Deprecated)', 'visualizer' ),
453 'enabled' => false,
454 'supports' => array( 'Google Charts' ),
455 ),
456 'timeline' => array(
457 'name' => esc_html__( 'Timeline', 'visualizer' ),
458 'enabled' => false,
459 'supports' => array( 'Google Charts', 'ChartJS' ),
460 ),
461 'combo' => array(
462 'name' => esc_html__( 'Combo', 'visualizer' ),
463 'enabled' => false,
464 'supports' => array( 'Google Charts' ),
465 ),
466 'polarArea' => array(
467 'name' => esc_html__( 'Polar Area', 'visualizer' ),
468 'enabled' => false,
469 'supports' => array( 'ChartJS' ),
470 ),
471 'radar' => array(
472 'name' => esc_html__( 'Radar/Spider', 'visualizer' ),
473 'enabled' => false,
474 'supports' => array( 'ChartJS' ),
475 ),
476 )
477 );
478 $types = apply_filters( 'visualizer_pro_chart_types', $types );
479 if ( $enabledOnly ) {
480 $filtered = array();
481 foreach ( $types as $type => $array ) {
482 if ( ! is_array( $array ) ) {
483 // support for old pro
484 $array = array( 'enabled' => true, 'name' => $array );
485 }
486 // backward compatibility for PRO before v1.9.0
487 if ( ! array_key_exists( 'supports', $array ) ) {
488 $array['supports'] = array( 'Google Charts' );
489 }
490 if ( ! $array['enabled'] ) {
491 continue;
492 }
493 $filtered[ $type ] = $array;
494 }
495 $types = $filtered;
496 }
497 if ( $get2Darray ) {
498 $doubleD = array();
499 foreach ( $types as $type => $array ) {
500 if ( ! is_array( $array ) ) {
501 // support for old pro
502 $array = array( 'enabled' => true, 'name' => $array );
503 }
504 // backward compatibility for PRO before v1.9.0
505 if ( ! array_key_exists( 'supports', $array ) ) {
506 $array['supports'] = array( 'Google Charts' );
507 }
508 $doubleD[ $type ] = $array['name'];
509 }
510 $types = $doubleD;
511 }
512
513 return self::handleDeprecatedCharts( $types, $enabledOnly, $get2Darray, $where );
514 }
515
516 /**
517 * Handle (soon-to-be) deprecated charts.
518 */
519 private static function handleDeprecatedCharts( $types, $enabledOnly, $get2Darray, $where ) {
520 $deprecated = array();
521
522 switch ( $where ) {
523 case 'types':
524 // fall-through
525 case 'library':
526 // if the user has a Google Table chart, show it as deprecated otherwise remove the option from the library.
527 if ( ! self::hasChartType( 'table' ) ) {
528 $deprecated[] = 'table';
529 if ( $get2Darray ) {
530 $types['dataTable'] = esc_html__( 'Table', 'visualizer' );
531 } else {
532 $types['dataTable']['name'] = esc_html__( 'Table', 'visualizer' );
533 }
534 }
535
536 // if a user has a Gauge/Candlestick chart, then let them keep using it.
537 if ( ! Visualizer_Module::is_pro() ) {
538 if ( ! self::hasChartType( 'gauge' ) ) {
539 if ( $get2Darray ) {
540 $deprecated[] = 'gauge';
541 } else {
542 $types['gauge']['enabled'] = false;
543 }
544 }
545 if ( ! self::hasChartType( 'candlestick' ) ) {
546 if ( $get2Darray ) {
547 $deprecated[] = 'candlestick';
548 } else {
549 $types['candlestick']['enabled'] = false;
550 }
551 }
552 }
553 break;
554 default:
555 // remove the option to create a Google Table chart.
556 $deprecated[] = 'table';
557
558 // rename the new table chart type.
559 if ( $get2Darray ) {
560 $types['dataTable'] = esc_html__( 'Table', 'visualizer' );
561 } else {
562 $types['dataTable']['name'] = esc_html__( 'Table', 'visualizer' );
563 }
564
565 // if a user has a Gauge/Candlestick chart, then let them keep using it.
566 if ( ! Visualizer_Module::is_pro() ) {
567 if ( ! self::hasChartType( 'gauge' ) ) {
568 if ( $get2Darray ) {
569 $deprecated[] = 'gauge';
570 } else {
571 $types['gauge']['enabled'] = false;
572 }
573 }
574 if ( ! self::hasChartType( 'candlestick' ) ) {
575 if ( $get2Darray ) {
576 $deprecated[] = 'candlestick';
577 } else {
578 $types['candlestick']['enabled'] = false;
579 }
580 }
581 }
582 }
583
584 if ( $deprecated ) {
585 foreach ( $deprecated as $type ) {
586 unset( $types[ $type ] );
587 }
588 }
589
590 return $types;
591 }
592
593 /**
594 * Renders templates to use in media popup.
595 *
596 * @since 1.0.0
597 * @global string $pagenow The name of the current page.
598 *
599 * @access public
600 */
601 public function renderTemplates() {
602 global $pagenow;
603 if ( 'post.php' !== $pagenow && 'post-new.php' !== $pagenow ) {
604 return;
605 }
606 $render = new Visualizer_Render_Templates();
607 $render->render();
608 }
609
610 /**
611 * Enqueues library scripts and styles.
612 *
613 * @since 1.0.0
614 * @uses wp_enqueue_style() To enqueue library stylesheet.
615 * @uses wp_enqueue_script() To enqueue javascript file.
616 * @uses wp_enqueue_media() To enqueue media stuff.
617 *
618 * @access public
619 *
620 * @param string $suffix The current page suffix.
621 */
622 public function enqueueLibraryScripts( $suffix ) {
623 if ( $suffix === $this->_libraryPage ) {
624 wp_enqueue_style( 'visualizer-library', VISUALIZER_ABSURL . 'css/library.css', array(), Visualizer_Plugin::VERSION );
625 $this->_addFilter( 'media_upload_tabs', 'setupVisualizerTab' );
626 wp_enqueue_media();
627 wp_enqueue_script(
628 'visualizer-library',
629 VISUALIZER_ABSURL . 'js/library.js',
630 array(
631 'jquery',
632 'media-views',
633 ),
634 Visualizer_Plugin::VERSION,
635 true
636 );
637
638 wp_enqueue_script( 'visualizer-customization', $this->get_user_customization_js(), array(), null, true );
639
640 $query = $this->getQuery();
641 while ( $query->have_posts() ) {
642 $chart = $query->next_post();
643 $library = $this->load_chart_type( $chart->ID );
644 if ( is_null( $library ) ) {
645 continue;
646 }
647 wp_enqueue_script(
648 "visualizer-render-$library",
649 VISUALIZER_ABSURL . 'js/render-facade.js',
650 apply_filters( 'visualizer_assets_render', array( 'visualizer-library', 'visualizer-customization' ), true ),
651 Visualizer_Plugin::VERSION,
652 true
653 );
654 }
655 }
656 }
657
658 /**
659 * Adds visualizer tab for media upload tabs array.
660 *
661 * @since 1.0.0
662 *
663 * @access public
664 *
665 * @param array $tabs The array of media upload tabs.
666 *
667 * @return array Extended array of media upload tabs.
668 */
669 public function setupVisualizerTab( $tabs ) {
670 $tabs['visualizer'] = 'Visualizer';
671
672 return $tabs;
673 }
674
675 /**
676 * Registers admin menu for visualizer library.
677 *
678 * @since 1.0.0
679 *
680 * @access public
681 */
682 public function registerAdminMenu() {
683 $svg_base64_icon = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iNzdweCIgaGVpZ2h0PSI3N3B4IiB2aWV3Qm94PSIwIDAgNzcgNzciIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICA8IS0tIEdlbmVyYXRvcjogU2tldGNoIDUyLjYgKDY3NDkxKSAtIGh0dHA6Ly93d3cuYm9oZW1pYW5jb2RpbmcuY29tL3NrZXRjaCAtLT4KICAgIDx0aXRsZT5Db21iaW5lZCBTaGFwZTwvdGl0bGU+CiAgICA8ZGVzYz5DcmVhdGVkIHdpdGggU2tldGNoLjwvZGVzYz4KICAgIDxnIGlkPSJQcm9kdWN0LVBhZ2UiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPgogICAgICAgIDxnIGlkPSJXb3JkUHJlc3MtcGx1Z2lucyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTE5MC4wMDAwMDAsIC00MzUuMDAwMDAwKSIgZmlsbD0iIzM5QzNEMiI+CiAgICAgICAgICAgIDxwYXRoIGQ9Ik0yMjguNSw1MTIgQzIwNy4yMzcwMzcsNTEyIDE5MCw0OTQuNzYyOTYzIDE5MCw0NzMuNSBDMTkwLDQ1Mi4yMzcwMzcgMjA3LjIzNzAzNyw0MzUgMjI4LjUsNDM1IEMyNDkuNzYyOTYzLDQzNSAyNjcsNDUyLjIzNzAzNyAyNjcsNDczLjUgQzI2Nyw0OTQuNzYyOTYzIDI0OS43NjI5NjMsNTEyIDIyOC41LDUxMiBaIE0yNDYuODQzNzUsNDgzLjU5MjA1OSBMMjE1LjYyNSw0ODMuNTkyMDU5IEwyMTUuNjI1LDQ2MC44MjY1NDQgQzIxNS42MjUsNDYwLjE2NDU0NyAyMTUuMTA3NTc4LDQ1OS42MjgzNTkgMjE0LjQ2ODc1LDQ1OS42MjgzNTkgTDIxMi4xNTYyNSw0NTkuNjI4MzU5IEMyMTEuNTE3NDIyLDQ1OS42MjgzNTkgMjExLDQ2MC4xNjQ1NDcgMjExLDQ2MC44MjY1NDQgTDIxMSw0ODUuOTg4NDI5IEMyMTEsNDg3LjMxMTY3NCAyMTIuMDM1NTY2LDQ4OC4zODQ3OTggMjEzLjMxMjUsNDg4LjM4NDc5OCBMMjQ2Ljg0Mzc1LDQ4OC4zODQ3OTggQzI0Ny40ODI1NzgsNDg4LjM4NDc5OCAyNDgsNDg3Ljg0ODYxMSAyNDgsNDg3LjE4NjYxMyBMMjQ4LDQ4NC43OTAyNDQgQzI0OCw0ODQuMTI4MjQ2IDI0Ny40ODI1NzgsNDgzLjU5MjA1OSAyNDYuODQzNzUsNDgzLjU5MjA1OSBaIE0yNDQuNTMxMjUsNDYyLjAyNDcyOSBMMjM1Ljk5OTU3LDQ2Mi4wMjQ3MjkgQzIzNC40NTQ1MzEsNDYyLjAyNDcyOSAyMzMuNjgwNTY2LDQ2My45NjA1NDcgMjM0Ljc3MzIyMyw0NjUuMDkyODMyIEwyMzcuMTE0NjI5LDQ2Ny41MTkxNTYgTDIzMS44MTI1LDQ3My4wMTQzMzIgTDIyNi41MTAzNzEsNDY3LjUxOTkwNSBDMjI1LjYwNzA1MSw0NjYuNTgzODIzIDIyNC4xNDI5NDksNDY2LjU4MzgyMyAyMjMuMjQwMzUyLDQ2Ny41MTk5MDUgTDIxOC4yNzY0MjYsNDcyLjY2Mzg2MyBDMjE3LjgyNDc2Niw0NzMuMTMxOTA0IDIxNy44MjQ3NjYsNDczLjg5MDUwNSAyMTguMjc2NDI2LDQ3NC4zNTg1NDYgTDIxOS45MTEwNzQsNDc2LjA1MjQ4IEMyMjAuMzYyNzM0LDQ3Ni41MjA1MjEgMjIxLjA5NDc4NSw0NzYuNTIwNTIxIDIyMS41NDY0NDUsNDc2LjA1MjQ4IEwyMjQuODc1LDQ3Mi42MDI0NTYgTDIzMC4xNzcxMjksNDc4LjA5Njg4MyBDMjMxLjA4MDQ0OSw0NzkuMDMyOTY1IDIzMi41NDQ1NTEsNDc5LjAzMjk2NSAyMzMuNDQ3MTQ4LDQ3OC4wOTY4ODMgTDI0MC4zODQ2NDgsNDcwLjkwNzc3MyBMMjQyLjcyNjA1NSw0NzMuMzM0MDk4IEMyNDMuODE4NzExLDQ3NC40NjYzODIgMjQ1LjY4Njc3Nyw0NzMuNjY0MzQ3IDI0NS42ODY3NzcsNDcyLjA2MzI3MyBMMjQ1LjY4Njc3Nyw0NjMuMjIyOTE0IEMyNDUuNjg3NSw0NjIuNTYwOTE3IDI0NS4xNzAwNzgsNDYyLjAyNDcyOSAyNDQuNTMxMjUsNDYyLjAyNDcyOSBaIiBpZD0iQ29tYmluZWQtU2hhcGUiPjwvcGF0aD4KICAgICAgICA8L2c+CiAgICA8L2c+Cjwvc3ZnPg==';
684
685 $this->_libraryPage = add_menu_page( __( 'Visualizer', 'visualizer' ), __( 'Visualizer', 'visualizer' ), 'edit_posts', Visualizer_Plugin::NAME, array( $this, 'renderLibraryPage' ), $svg_base64_icon, 99.7666 );
686
687 add_submenu_page(
688 Visualizer_Plugin::NAME,
689 __( 'Chart Library', 'visualizer' ),
690 __( 'Chart Library', 'visualizer' ),
691 'edit_posts',
692 admin_url( 'admin.php?page=' . Visualizer_Plugin::NAME )
693 );
694 add_submenu_page(
695 Visualizer_Plugin::NAME,
696 __( 'Add New Chart', 'visualizer' ),
697 __( 'Add New Chart', 'visualizer' ),
698 'edit_posts',
699 admin_url( 'admin.php?page=' . Visualizer_Plugin::NAME . '&vaction=addnew' )
700 );
701 add_submenu_page(
702 Visualizer_Plugin::NAME,
703 __( 'Support', 'visualizer' ),
704 __( '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>',
705 'edit_posts',
706 'viz-support',
707 array( $this, 'renderSupportPage' )
708 );
709 remove_submenu_page( Visualizer_Plugin::NAME, Visualizer_Plugin::NAME );
710 }
711
712 /**
713 * Get the instance of WP_Query that fetches the charts as per the given criteria.
714 */
715 private function getQuery() {
716 static $q;
717 if ( ! is_null( $q ) ) {
718 return $q;
719 }
720
721 // get current page
722 $page = filter_input(
723 INPUT_GET,
724 'vpage',
725 FILTER_VALIDATE_INT,
726 array(
727 'options' => array(
728 'min_range' => 1,
729 'default' => 1,
730 ),
731 )
732 );
733 // the initial query arguments to fetch charts
734 $query_args = array(
735 'post_type' => Visualizer_Plugin::CPT_VISUALIZER,
736 'posts_per_page' => 6,
737 'paged' => $page,
738 );
739 // add chart type filter to the query arguments
740 $filter = filter_input( INPUT_GET, 'type' );
741 if ( $filter && in_array( $filter, Visualizer_Plugin::getChartTypes(), true ) ) {
742 $query_args['meta_query'] = array(
743 array(
744 'key' => Visualizer_Plugin::CF_CHART_TYPE,
745 'value' => $filter,
746 'compare' => '=',
747 ),
748 );
749 } else {
750 $filter = 'all';
751 }
752 // Added by Ash/Upwork
753 $filterByMeta = filter_input( INPUT_GET, 's', FILTER_SANITIZE_STRING );
754 if ( $filterByMeta ) {
755 $query = array(
756 'key' => Visualizer_Plugin::CF_SETTINGS,
757 'value' => $filterByMeta,
758 'compare' => 'LIKE',
759 );
760 $meta = isset( $query_args['meta_query'] ) ? $query_args['meta_query'] : array();
761 $meta[] = $query;
762 $query_args['meta_query'] = $meta;
763 }
764 $q = new WP_Query( apply_filters( 'visualizer_query_args', $query_args ) );
765 return $q;
766 }
767
768 /**
769 * Renders support page.
770 *
771 * @since 3.3.0
772 *
773 * @access public
774 */
775 public function renderSupportPage() {
776 wp_enqueue_style( 'visualizer-upsell', VISUALIZER_ABSURL . 'css/upsell.css', array(), Visualizer_Plugin::VERSION );
777 include_once VISUALIZER_ABSPATH . '/templates/support.php';
778 }
779
780 /**
781 * Renders visualizer library page.
782 *
783 * @since 1.0.0
784 *
785 * @access public
786 */
787 public function renderLibraryPage() {
788 $charts = array();
789 $query = $this->getQuery();
790
791 // get current page
792 $page = filter_input(
793 INPUT_GET,
794 'vpage',
795 FILTER_VALIDATE_INT,
796 array(
797 'options' => array(
798 'min_range' => 1,
799 'default' => 1,
800 ),
801 )
802 );
803 // add chart type filter to the query arguments
804 $filter = filter_input( INPUT_GET, 'type' );
805 if ( ! ( $filter && in_array( $filter, Visualizer_Plugin::getChartTypes(), true ) ) ) {
806 $filter = 'all';
807 }
808
809 $css = '';
810 while ( $query->have_posts() ) {
811 $chart = $query->next_post();
812
813 // 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.
814 $chart = $this->handleExistingRevisions( $chart->ID, $chart );
815 // refresh a "live" db query chart.
816 $chart = apply_filters( 'visualizer_schedule_refresh_chart', $chart, $chart->ID, false );
817
818 $type = get_post_meta( $chart->ID, Visualizer_Plugin::CF_CHART_TYPE, true );
819
820 // fetch and update settings
821 $settings = get_post_meta( $chart->ID, Visualizer_Plugin::CF_SETTINGS, true );
822
823 $settings = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_SETTINGS, $settings, $chart->ID, $type );
824 if ( ! empty( $atts['settings'] ) ) {
825 $settings = apply_filters( $atts['settings'], $settings, $chart->ID, $type );
826 }
827
828 if ( $settings ) {
829 unset( $settings['height'], $settings['width'], $settings['chartArea'] );
830 }
831
832 $series = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_SERIES, get_post_meta( $chart->ID, Visualizer_Plugin::CF_SERIES, true ), $chart->ID, $type );
833 $data = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_DATA, unserialize( html_entity_decode( $chart->post_content ) ), $chart->ID, $type );
834
835 $library = $this->load_chart_type( $chart->ID );
836
837 $id = 'visualizer-' . $chart->ID;
838 $arguments = $this->get_inline_custom_css( $id, $settings );
839 if ( ! empty( $arguments ) ) {
840 $css .= $arguments[0];
841 $settings = $arguments[1];
842 }
843
844 // add chart to the array
845 $charts[ $id ] = array(
846 'id' => $chart->ID,
847 'type' => $type,
848 'series' => $series,
849 'settings' => $settings,
850 'data' => $data,
851 'library' => $library,
852 );
853 }
854 // enqueue charts array
855 $ajaxurl = admin_url( 'admin-ajax.php' );
856 wp_localize_script(
857 'visualizer-library',
858 'visualizer',
859 array(
860 'language' => $this->get_language(),
861 'map_api_key' => get_option( 'visualizer-map-api-key' ),
862 'charts' => $charts,
863 'urls' => array(
864 'base' => add_query_arg( array( 'vpage' => false, 'vaction' => false ) ),
865 'create' => add_query_arg(
866 array(
867 'action' => Visualizer_Plugin::ACTION_CREATE_CHART,
868 'library' => 'yes',
869 'type' => isset( $_GET['type'] ) ? $_GET['type'] : '',
870 'chart-library' => isset( $_GET['chart-library'] ) ? $_GET['chart-library'] : '',
871 'vaction' => false,
872 ),
873 $ajaxurl
874 ),
875 'edit' => add_query_arg(
876 array(
877 'action' => Visualizer_Plugin::ACTION_EDIT_CHART,
878 'library' => 'yes',
879 'vaction' => false,
880 ),
881 $ajaxurl
882 ),
883 ),
884 'page_type' => 'library',
885 'is_front' => false,
886 )
887 );
888 // render library page
889 $render = new Visualizer_Render_Library();
890 $render->charts = $charts;
891 $render->type = $filter;
892 $render->types = self::_getChartTypesLocalized( false, false, false, true );
893 $render->custom_css = $css;
894 $render->pagination = paginate_links(
895 array(
896 'base' => add_query_arg( array( 'vpage' => '%#%', 'vaction' => false ) ),
897 'format' => '',
898 'current' => $page,
899 'total' => $query->max_num_pages,
900 'type' => 'array',
901 )
902 );
903 $render->render();
904 }
905
906 /**
907 * Updates the plugin's action links, which will be rendered at the plugins table.
908 *
909 * @since 1.0.0
910 *
911 * @access public
912 *
913 * @param array $links The array of original action links.
914 * @param string $file The plugin basename.
915 *
916 * @return array Updated array of action links.
917 */
918 public function getPluginActionLinks( $links, $file ) {
919 if ( $file === plugin_basename( VISUALIZER_BASEFILE ) ) {
920 array_unshift(
921 $links,
922 sprintf(
923 '<a href="%s">%s</a>',
924 admin_url( 'admin.php?page=' . Visualizer_Plugin::NAME ),
925 esc_html__( 'Library', 'visualizer' )
926 )
927 );
928 }
929
930 return $links;
931 }
932
933 /**
934 * Updates the plugin's meta links, which will be rendered at the plugins table.
935 *
936 * @since 1.0.0
937 *
938 * @access public
939 *
940 * @param array $plugin_meta The array of a plugin meta links.
941 * @param string $plugin_file The plugin's basename.
942 *
943 * @return array Updated array of plugin meta links.
944 */
945 public function getPluginMetaLinks( $plugin_meta, $plugin_file ) {
946 if ( $plugin_file === plugin_basename( VISUALIZER_BASEFILE ) ) {
947 // knowledge base link
948 $plugin_meta[] = sprintf(
949 '<a href="' . VISUALIZER_MAIN_DOC . '" target="_blank">%s</a>',
950 esc_html__( 'Docs', 'visualizer' )
951 );
952 // flattr link
953 $plugin_meta[] = sprintf(
954 '<a style="color:red" href="' . Visualizer_Plugin::PRO_TEASER_URL . '" target="_blank">%s</a>',
955 esc_html__( 'Pro Addon', 'visualizer' )
956 );
957 }
958
959 return $plugin_meta;
960 }
961
962 }
963