PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.4.0
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.4.0
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.0, at classes/Visualizer/Module/Admin.php

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