PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.11.7
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.11.7
4.0.7 4.0.6 4.0.5 4.0.4 4.0.3 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.1 3.1.2 3.1.3 3.10.0 3.10.1 3.10.10 3.10.11 3.10.12 3.10.13 3.10.14 3.10.15 3.10.2 3.10.3 3.10.4 All 148 releases
← All changes | classes/Visualizer/Module/Admin.php +943 -126 3.0.53.11.7 View file →
@@ -52,19 +52,254 @@
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' );
57 - $this->_addAction( 'admin_enqueue_scripts', 'enqueueLibraryScripts', null, 8 );
56 + $this->_addAction( 'enqueue_block_editor_assets', 'enqueueMediaScripts' );
57 + $this->_addAction( 'admin_footer', 'renderTemplates' );
58 + $this->_addAction( 'admin_enqueue_scripts', 'enqueueLibraryScripts', null, 0 );
58 59 $this->_addAction( 'admin_menu', 'registerAdminMenu' );
59 60 $this->_addFilter( 'media_view_strings', 'setupMediaViewStrings' );
60 61 $this->_addFilter( 'plugin_action_links', 'getPluginActionLinks', 10, 2 );
62 + $this->_addFilter( 'plugin_row_meta', 'getPluginMetaLinks', 10, 2 );
61 63 $this->_addFilter( 'visualizer_logger_data', 'getLoggerData' );
62 - $this->_addFilter( 'visualizer_get_chart_counts', 'getChartCountsByTypeAndMeta' );
63 64 $this->_addFilter( 'visualizer_feedback_review_trigger', 'feedbackReviewTrigger' );
65 +
66 + // screen pagination
67 + $this->_addFilter( 'set-screen-option', 'setScreenOptions', 10, 3 );
68 +
69 + // revision support.
70 + $this->_addFilter( 'wp_revisions_to_keep', 'limitRevisions', null, 10, 2 );
71 + $this->_addAction( '_wp_put_post_revision', 'addRevision', null, 10, 1 );
72 + $this->_addAction( 'wp_restore_post_revision', 'restoreRevision', null, 10, 2 );
73 +
74 + $this->_addAction( 'visualizer_chart_schedules_spl', 'addSplChartSchedules', null, 10, 3 );
75 +
76 + $this->_addAction( 'admin_init', 'init' );
77 +
78 + $this->_addAction( 'visualizer_chart_languages', 'addMultilingualSupport' );
79 +
80 + $this->_addFilter( 'admin_footer_text', 'render_review_notice' );
81 +
82 + if ( defined( 'TI_CYPRESS_TESTING' ) ) {
83 + $this->load_cypress_hooks();
84 + }
85 +
64 86 }
87 + /**
88 + * Display review notice.
89 + */
90 + public function render_review_notice( $footer_text ) {
91 + $current_screen = get_current_screen();
65 92
93 + $visualizer_page_ids = ['toplevel_page_visualizer', 'visualizer_page_viz-support', 'visualizer_page_ti-about-visualizer' ];
94 +
95 + if ( ! empty( $current_screen ) && isset( $current_screen->id ) ) {
96 + foreach ( $visualizer_page_ids as $page_to_check ) {
97 + if ( strpos( $current_screen->id, $page_to_check ) !== false ) {
98 + $footer_text = sprintf(
99 + __( 'Enjoying %1$s? %2$s %3$s rating. Thank you for being so supportive!', 'visualizer' ),
100 + '<b>Visualizer</b>',
101 + esc_html__( 'You can help us by leaving a', 'visualizer' ),
102 + '<a href="https://wordpress.org/support/plugin/visualizer/reviews/" target="_blank">&#9733;&#9733;&#9733;&#9733;&#9733;</a>'
103 + );
104 + break;
105 + }
106 + }
107 + }
108 +
109 + return $footer_text;
110 + }
111 +
112 +
66 113 /**
114 + * Define the hooks that are needed for cypress.
115 + *
116 + * @since 3.4.0
117 + * @access private
118 + */
119 + private function load_cypress_hooks() {
120 + // all charts should load on the same page without pagination.
121 + add_filter(
122 + 'visualizer_query_args', function( $args ) {
123 + $args['posts_per_page'] = 20;
124 + return $args;
125 + }, 10, 1
126 + );
127 + }
128 +
129 + /**
130 + * Add disabled `optgroup` schedules to the drop downs.
131 + *
132 + * @since ?
133 + *
134 + * @access public
135 + *
136 + * @param string $feature The feature for which to add schedules.
137 + * @param int $chart_id The chart ID.
138 + * @param int $plan The plan number.
139 + */
140 + public function addSplChartSchedules( $feature, $chart_id, $plan ) {
141 + if ( apply_filters( 'visualizer_is_business', false ) ) {
142 + return;
143 + }
144 +
145 + $is_new_personal = apply_filters( 'visualizer_is_new_personal', false );
146 +
147 + $hours = array(
148 + '0.16' => __( '10 minutes', 'visualizer' ),
149 + '1' => __( 'Each hour', 'visualizer' ),
150 + '12' => __( 'Each 12 hours', 'visualizer' ),
151 + '24' => __( 'Each day', 'visualizer' ),
152 + '72' => __( 'Each 3 days', 'visualizer' ),
153 + );
154 +
155 + switch ( $feature ) {
156 + case 'json':
157 + case 'csv':
158 + // no more schedules if pro is already active.
159 + if ( Visualizer_Module::is_pro() && ! $is_new_personal ) {
160 + return;
161 + }
162 + break;
163 + case 'wp':
164 + // fall-through.
165 + case 'db':
166 + break;
167 + default:
168 + return;
169 + }
170 +
171 + echo '<optgroup disabled label="' . __( 'Upgrade required', 'visualizer' ) . '">';
172 + foreach ( $hours as $hour => $desc ) {
173 + echo '<option disabled>' . $desc . '</option>';
174 + }
175 + echo '</optgroup>';
176 + }
177 +
178 + /**
179 + * No limits on revisions.
180 + */
181 + public function limitRevisions( $num, $post ) {
182 + if ( Visualizer_Plugin::CPT_VISUALIZER === $post->post_type ) {
183 + return -1;
184 + }
185 + return $num;
186 + }
187 +
188 + /**
189 + * Add a revision.
190 + */
191 + public function addRevision( $revision_id ) {
192 + $parent_id = wp_is_post_revision( $revision_id );
193 + if ( Visualizer_Plugin::CPT_VISUALIZER === get_post_type( $parent_id ) ) {
194 + // add the meta data to this revision.
195 + $meta = get_post_meta( $parent_id, '', true );
196 +
197 + if ( $meta ) {
198 + foreach ( $meta as $key => $value ) {
199 + if ( 0 === strpos( $key, 'visualizer' ) ) {
200 + add_metadata( 'post', $revision_id, $key, maybe_unserialize( $value[0] ) );
201 + }
202 + }
203 + }
204 + }
205 + }
206 +
207 + /**
208 + * Restore a revision.
209 + */
210 + public function restoreRevision( $post_id, $revision_id ) {
211 + if ( Visualizer_Plugin::CPT_VISUALIZER === get_post_type( $post_id ) ) {
212 + // get the meta information from the revision.
213 + $meta = get_metadata( 'post', $revision_id, '', true );
214 +
215 + // delete all meta information from the post before adding.
216 + $post_meta = get_post_meta( $post_id, '', true );
217 + if ( $post_meta ) {
218 + foreach ( $meta as $key => $value ) {
219 + if ( 0 === strpos( $key, 'visualizer' ) ) {
220 + delete_post_meta( $post_id, $key );
221 + }
222 + }
223 + }
224 +
225 + if ( $meta ) {
226 + foreach ( $meta as $key => $value ) {
227 + if ( 0 === strpos( $key, 'visualizer' ) ) {
228 + add_post_meta( $post_id, $key, maybe_unserialize( $value[0] ) );
229 + }
230 + }
231 + }
232 + }
233 + }
234 +
235 + /**
236 + * Admin init.
237 + *
238 + * @access public
239 + */
240 + public function init() {
241 + // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
242 + if ( current_user_can( 'edit_posts' ) && current_user_can( 'edit_pages' ) && 'true' == get_user_option( 'rich_editing' ) ) {
243 + $this->_addFilter( 'mce_external_languages', 'add_tinymce_lang', 10, 1 );
244 + $this->_addFilter( 'mce_external_plugins', 'tinymce_plugin', 10, 1 );
245 + $this->_addFilter( 'mce_buttons', 'register_mce_button', 10, 1 );
246 + $this->_addFilter( 'tiny_mce_before_init', 'get_strings_for_block', 10, 1 );
247 + }
248 + }
249 +
250 + /**
251 + * Add the strings required for the TinyMCE buttons for the classic block (not the classic editor).
252 + *
253 + * @since ?
254 + * @access friendly
255 + */
256 + function get_strings_for_block( $settings ) {
257 + $class = new Visualizer_Module_Language();
258 + $strings = $class->get_strings();
259 + $array = array( 'visualizer_tinymce_plugin' => json_encode( $strings ) );
260 + return array_merge( $settings, $array );
261 + }
262 +
263 + /**
264 + * Load plugin translation for - TinyMCE API
265 + *
266 + * @access public
267 + * @param array $arr The tinymce_lang array.
268 + * @return array
269 + */
270 + public function add_tinymce_lang( $arr ) {
271 + $ui_lang = VISUALIZER_ABSPATH . '/classes/Visualizer/Module/Language.php';
272 + $ui_lang = apply_filters( 'visualizer_ui_lang_filter', $ui_lang );
273 + $arr[] = $ui_lang;
274 + return $arr;
275 + }
276 +
277 + /**
278 + * Load custom js options - TinyMCE API
279 + *
280 + * @access public
281 + * @param array $plugin_array The tinymce plugin array.
282 + * @return array
283 + */
284 + public function tinymce_plugin( $plugin_array ) {
285 + $plugin_array['visualizer_mce_button'] = VISUALIZER_ABSURL . 'js/mce.js';
286 + return $plugin_array;
287 + }
288 +
289 + /**
290 + * Register new button in the editor
291 + *
292 + * @access public
293 + * @param array $buttons The tinymce buttons array.
294 + * @return array
295 + */
296 + public function register_mce_button( $buttons ) {
297 + array_push( $buttons, 'visualizer_mce_button' );
298 + return $buttons;
299 + }
300 +
301 + /**
67 302 * Whether to show the feedback review or not.
68 303 *
69 304 * @access public
70 305 */
@@ -95,16 +330,32 @@
95 330 * @access public
96 331 */
97 332 public function enqueueMediaScripts() {
98 333 global $typenow;
99 - if ( post_type_supports( $typenow, 'editor' ) ) {
334 + global $current_screen;
335 +
336 + if ( post_type_supports( $typenow, 'editor' ) || $current_screen->id === 'widgets' || $current_screen->id === 'customize' ) {
100 337 wp_enqueue_style( 'visualizer-media', VISUALIZER_ABSURL . 'css/media.css', array( 'media-views' ), Visualizer_Plugin::VERSION );
101 - wp_enqueue_script( 'visualizer-google-jsapi-new', '//www.gstatic.com/charts/loader.js', array( 'media-editor' ), null, true );
102 - wp_enqueue_script( 'visualizer-google-jsapi-old', '//www.google.com/jsapi', array( 'visualizer-google-jsapi-new' ), null, true );
103 - wp_enqueue_script( 'visualizer-media-model', VISUALIZER_ABSURL . 'js/media/model.js', array( 'visualizer-google-jsapi-old' ), Visualizer_Plugin::VERSION, true );
338 +
339 + // Load all the assets for the different libraries we support.
340 + $deps = array(
341 + Visualizer_Render_Sidebar_Google::enqueue_assets( array( 'media-editor' ) ),
342 + Visualizer_Render_Sidebar_Type_DataTable_Tabular::enqueue_assets( array( 'media-editor' ) ),
343 + );
344 +
345 + wp_enqueue_script( 'visualizer-media-model', VISUALIZER_ABSURL . 'js/media/model.js', $deps, Visualizer_Plugin::VERSION, true );
104 346 wp_enqueue_script( 'visualizer-media-collection', VISUALIZER_ABSURL . 'js/media/collection.js', array( 'visualizer-media-model' ), Visualizer_Plugin::VERSION, true );
105 347 wp_enqueue_script( 'visualizer-media-controller', VISUALIZER_ABSURL . 'js/media/controller.js', array( 'visualizer-media-collection' ), Visualizer_Plugin::VERSION, true );
106 348 wp_enqueue_script( 'visualizer-media-view', VISUALIZER_ABSURL . 'js/media/view.js', array( 'visualizer-media-controller' ), Visualizer_Plugin::VERSION, true );
349 + wp_localize_script(
350 + 'visualizer-media-view',
351 + 'visualizer',
352 + array(
353 + 'i10n' => array(
354 + 'insert' => __( 'Insert', 'visualizer' ),
355 + ),
356 + )
357 + );
107 358 wp_enqueue_script( 'visualizer-media-toolbar', VISUALIZER_ABSURL . 'js/media/toolbar.js', array( 'visualizer-media-view' ), Visualizer_Plugin::VERSION, true );
108 359 wp_enqueue_script( 'visualizer-media', VISUALIZER_ABSURL . 'js/media.js', array( 'visualizer-media-toolbar' ), Visualizer_Plugin::VERSION, true );
109 360 }
110 361 }
@@ -120,8 +371,9 @@
120 371 *
121 372 * @return array The extended array of media view strings.
122 373 */
123 374 public function setupMediaViewStrings( $strings ) {
375 + $chart_types = self::_getChartTypesLocalized( true, true, true );
124 376 $strings['visualizer'] = array(
125 377 'actions' => array(
126 378 'get_charts' => Visualizer_Plugin::ACTION_GET_CHARTS,
127 379 'delete_chart' => Visualizer_Plugin::ACTION_DELETE_CHART,
@@ -133,13 +385,13 @@
133 385 'library' => esc_html__( 'From Library', 'visualizer' ),
134 386 'create' => esc_html__( 'Create New', 'visualizer' ),
135 387 ),
136 388 'library' => array(
137 - 'filters' => self::_getChartTypesLocalized( true, true ),
138 - 'types' => array_keys( self::_getChartTypesLocalized( true, true ) ),
389 + 'filters' => $chart_types,
390 + 'types' => array_keys( $chart_types ),
139 391 ),
140 392 'nonce' => wp_create_nonce(),
141 - 'buildurl' => add_query_arg( 'action', Visualizer_Plugin::ACTION_CREATE_CHART, admin_url( 'admin-ajax.php' ) ),
393 + 'buildurl' => esc_url( add_query_arg( 'action', Visualizer_Plugin::ACTION_CREATE_CHART, admin_url( 'admin-ajax.php' ) ) ),
142 394 );
143 395
144 396 return $strings;
145 397 }
@@ -152,59 +404,112 @@
152 404 * @static
153 405 * @access private
154 406 * @return array The associated array of chart types with localized names.
155 407 */
156 - public static function _getChartTypesLocalized( $enabledOnly = false, $get2Darray = false ) {
157 - $types = array(
158 - 'pie' => array(
159 - 'name' => esc_html__( 'Pie', 'visualizer' ),
408 + public static function _getChartTypesLocalized( $enabledOnly = false, $get2Darray = false, $add_select = false, $where = null ) {
409 + $additional = array();
410 + if ( $add_select ) {
411 + $additional['select'] = array(
412 + 'name' => esc_html__( 'All', 'visualizer' ),
160 413 'enabled' => true,
161 - ),
162 - 'line' => array(
163 - 'name' => esc_html__( 'Line', 'visualizer' ),
164 - 'enabled' => true,
165 - ),
166 - 'area' => array(
167 - 'name' => esc_html__( 'Area', 'visualizer' ),
168 - 'enabled' => true,
169 - ),
170 - 'geo' => array(
171 - 'name' => esc_html__( 'Geo', 'visualizer' ),
172 - 'enabled' => true,
173 - ),
174 - 'bar' => array(
175 - 'name' => esc_html__( 'Bar', 'visualizer' ),
176 - 'enabled' => true,
177 - ),
178 - 'column' => array(
179 - 'name' => esc_html__( 'Column', 'visualizer' ),
180 - 'enabled' => true,
181 - ),
182 - 'gauge' => array(
183 - 'name' => esc_html__( 'Gauge', 'visualizer' ),
184 - 'enabled' => true,
185 - ),
186 - 'scatter' => array(
187 - 'name' => esc_html__( 'Scatter', 'visualizer' ),
188 - 'enabled' => true,
189 - ),
190 - 'candlestick' => array(
191 - 'name' => esc_html__( 'Candlestick', 'visualizer' ),
192 - 'enabled' => true,
193 - ),
194 - // pro types
195 - 'table' => array(
196 - 'name' => esc_html__( 'Table', 'visualizer' ),
197 - 'enabled' => false,
198 - ),
199 - 'timeline' => array(
200 - 'name' => esc_html__( 'Timeline', 'visualizer' ),
201 - 'enabled' => false,
202 - ),
203 - 'combo' => array(
204 - 'name' => esc_html__( 'Combo', 'visualizer' ),
205 - 'enabled' => false,
206 - ),
414 + );
415 + }
416 +
417 + $enabled = self::proFeaturesLocked();
418 +
419 + $types = array_merge(
420 + $additional,
421 + array(
422 + 'tabular' => array(
423 + 'name' => esc_html__( 'Table', 'visualizer' ),
424 + 'enabled' => true,
425 + 'supports' => $enabled ? array( 'Google Charts', 'DataTable' ) : array( 'DataTable' ),
426 + ),
427 + 'pie' => array(
428 + 'name' => esc_html__( 'Pie/Donut', 'visualizer' ),
429 + 'enabled' => true,
430 + 'supports' => array( 'Google Charts', 'ChartJS' ),
431 + ),
432 + 'line' => array(
433 + 'name' => esc_html__( 'Line', 'visualizer' ),
434 + 'enabled' => true,
435 + 'supports' => array( 'Google Charts', 'ChartJS' ),
436 + ),
437 + 'bar' => array(
438 + 'name' => esc_html__( 'Bar', 'visualizer' ),
439 + 'enabled' => true,
440 + 'supports' => $enabled ? array( 'Google Charts', 'ChartJS' ) : array( 'Google Charts' ),
441 + ),
442 + 'area' => array(
443 + 'name' => esc_html__( 'Area', 'visualizer' ),
444 + 'enabled' => $enabled,
445 + // in ChartJS, the fill option is used to make Line chart an area: https://www.chartjs.org/docs/latest/charts/area.html
446 + 'supports' => array( 'Google Charts' ),
447 + 'demo_url' => 'https://demo.themeisle.com/visualizer/area-chart/',
448 + ),
449 + 'geo' => array(
450 + 'name' => esc_html__( 'Geo', 'visualizer' ),
451 + 'enabled' => $enabled,
452 + 'supports' => array( 'Google Charts' ),
453 + 'demo_url' => 'https://demo.themeisle.com/visualizer/geo-chart/',
454 + ),
455 + 'column' => array(
456 + 'name' => esc_html__( 'Column', 'visualizer' ),
457 + 'enabled' => $enabled,
458 + 'supports' => array( 'Google Charts', 'ChartJS' ),
459 + 'demo_url' => 'https://demo.themeisle.com/visualizer/column-chart/',
460 + ),
461 + 'bubble' => array(
462 + 'name' => esc_html__( 'Bubble', 'visualizer' ),
463 + 'enabled' => $enabled,
464 + // chartjs' bubble is ugly looking (and it won't work off the default bubble.csv) so it is being excluded for the time being.
465 + 'supports' => array( 'Google Charts' ),
466 + 'demo_url' => 'https://demo.themeisle.com/visualizer/bubble-chart/',
467 + ),
468 + 'scatter' => array(
469 + 'name' => esc_html__( 'Scatter', 'visualizer' ),
470 + 'enabled' => $enabled,
471 + 'supports' => array( 'Google Charts' ),
472 + 'demo_url' => 'https://demo.themeisle.com/visualizer/scatter-chart/',
473 + ),
474 + 'gauge' => array(
475 + 'name' => esc_html__( 'Gauge', 'visualizer' ),
476 + 'enabled' => $enabled,
477 + 'supports' => array( 'Google Charts' ),
478 + 'demo_url' => 'https://demo.themeisle.com/visualizer/gauge-chart/',
479 + ),
480 + 'candlestick' => array(
481 + 'name' => esc_html__( 'Candlestick', 'visualizer' ),
482 + 'enabled' => $enabled,
483 + 'supports' => array( 'Google Charts' ),
484 + 'demo_url' => 'https://demo.themeisle.com/visualizer/candlestick-chart/',
485 + ),
486 + // pro types
487 + 'timeline' => array(
488 + 'name' => esc_html__( 'Timeline', 'visualizer' ),
489 + 'enabled' => false,
490 + 'supports' => array( 'Google Charts', 'ChartJS' ),
491 + 'demo_url' => 'https://demo.themeisle.com/visualizer/timeline-chart/',
492 + ),
493 + 'combo' => array(
494 + 'name' => esc_html__( 'Combo', 'visualizer' ),
495 + 'enabled' => false,
496 + 'supports' => array( 'Google Charts' ),
497 + 'demo_url' => 'https://demo.themeisle.com/visualizer/combo-chart/',
498 + ),
499 + 'polarArea' => array(
500 + 'name' => esc_html__( 'Polar Area', 'visualizer' ),
501 + 'enabled' => false,
502 + 'supports' => array( 'ChartJS' ),
503 + 'demo_url' => 'https://demo.themeisle.com/visualizer/polar-area-chart/',
504 + ),
505 + 'radar' => array(
506 + 'name' => esc_html__( 'Radar/Spider', 'visualizer' ),
507 + 'enabled' => false,
508 + 'supports' => array( 'ChartJS' ),
509 + 'demo_url' => 'https://demo.themeisle.com/visualizer/radar-spider-chart/',
510 + ),
511 + )
207 512 );
208 513 $types = apply_filters( 'visualizer_pro_chart_types', $types );
209 514 if ( $enabledOnly ) {
210 515 $filtered = array();
@@ -212,8 +517,12 @@
212 517 if ( ! is_array( $array ) ) {
213 518 // support for old pro
214 519 $array = array( 'enabled' => true, 'name' => $array );
215 520 }
521 + // backward compatibility for PRO before v1.9.0
522 + if ( ! array_key_exists( 'supports', $array ) ) {
523 + $array['supports'] = array( 'Google Charts' );
524 + }
216 525 if ( ! $array['enabled'] ) {
217 526 continue;
218 527 }
219 528 $filtered[ $type ] = $array;
@@ -226,13 +535,74 @@
226 535 if ( ! is_array( $array ) ) {
227 536 // support for old pro
228 537 $array = array( 'enabled' => true, 'name' => $array );
229 538 }
539 + // backward compatibility for PRO before v1.9.0
540 + if ( ! array_key_exists( 'supports', $array ) ) {
541 + $array['supports'] = array( 'Google Charts' );
542 + }
230 543 $doubleD[ $type ] = $array['name'];
231 544 }
232 545 $types = $doubleD;
233 546 }
234 547
548 + return self::handleDeprecatedCharts( $types, $enabledOnly, $get2Darray, $where );
549 + }
550 +
551 + /**
552 + * Handle (soon-to-be) deprecated charts.
553 + */
554 + private static function handleDeprecatedCharts( $types, $enabledOnly, $get2Darray, $where ) {
555 + $deprecated = array();
556 +
557 + switch ( $where ) {
558 + case 'types':
559 + // fall-through
560 + case 'library':
561 + // if a user has a Gauge/Candlestick chart, then let them keep using it.
562 + if ( ! Visualizer_Module::is_pro() ) {
563 + if ( ! self::hasChartType( 'gauge' ) ) {
564 + if ( $get2Darray ) {
565 + $deprecated[] = 'gauge';
566 + } else {
567 + $types['gauge']['enabled'] = false;
568 + }
569 + }
570 + if ( ! self::hasChartType( 'candlestick' ) ) {
571 + if ( $get2Darray ) {
572 + $deprecated[] = 'candlestick';
573 + } else {
574 + $types['candlestick']['enabled'] = false;
575 + }
576 + }
577 + }
578 + break;
579 + default:
580 + // if a user has a Gauge/Candlestick chart, then let them keep using it.
581 + if ( ! Visualizer_Module::is_pro() ) {
582 + if ( ! self::hasChartType( 'gauge' ) ) {
583 + if ( $get2Darray ) {
584 + $deprecated[] = 'gauge';
585 + } else {
586 + $types['gauge']['enabled'] = false;
587 + }
588 + }
589 + if ( ! self::hasChartType( 'candlestick' ) ) {
590 + if ( $get2Darray ) {
591 + $deprecated[] = 'candlestick';
592 + } else {
593 + $types['candlestick']['enabled'] = false;
594 + }
595 + }
596 + }
597 + }
598 +
599 + if ( $deprecated ) {
600 + foreach ( $deprecated as $type ) {
601 + unset( $types[ $type ] );
602 + }
603 + }
604 +
235 605 return $types;
236 606 }
237 607
238 608 /**
@@ -242,11 +612,11 @@
242 612 * @global string $pagenow The name of the current page.
243 613 *
244 614 * @access public
245 615 */
246 - public function renderTempaltes() {
616 + public function renderTemplates() {
247 617 global $pagenow;
248 - if ( 'post.php' != $pagenow && 'post-new.php' != $pagenow ) {
618 + if ( 'post.php' !== $pagenow && 'post-new.php' !== $pagenow ) {
249 619 return;
250 620 }
251 621 $render = new Visualizer_Render_Templates();
252 622 $render->render();
@@ -264,26 +634,41 @@
264 634 *
265 635 * @param string $suffix The current page suffix.
266 636 */
267 637 public function enqueueLibraryScripts( $suffix ) {
268 - if ( $suffix == $this->_libraryPage ) {
638 + if ( $suffix === $this->_libraryPage ) {
269 639 wp_enqueue_style( 'visualizer-library', VISUALIZER_ABSURL . 'css/library.css', array(), Visualizer_Plugin::VERSION );
270 640 $this->_addFilter( 'media_upload_tabs', 'setupVisualizerTab' );
271 641 wp_enqueue_media();
272 642 wp_enqueue_script(
273 - 'visualizer-library', VISUALIZER_ABSURL . 'js/library.js', array(
643 + 'visualizer-library',
644 + VISUALIZER_ABSURL . 'js/library.js',
645 + array(
274 646 'jquery',
275 647 'media-views',
276 - ), Visualizer_Plugin::VERSION, true
648 + 'clipboard',
649 + ),
650 + Visualizer_Plugin::VERSION,
651 + true
277 652 );
278 - wp_enqueue_script( 'google-jsapi-new', '//www.gstatic.com/charts/loader.js', array(), null, true );
279 - wp_enqueue_script( 'google-jsapi-old', '//www.google.com/jsapi', array( 'google-jsapi-new' ), null, true );
280 - wp_enqueue_script(
281 - 'visualizer-render', VISUALIZER_ABSURL . 'js/render.js', array(
282 - 'google-jsapi-old',
283 - 'visualizer-library',
284 - ), Visualizer_Plugin::VERSION, true
285 - );
653 +
654 + wp_enqueue_script( 'visualizer-customization', $this->get_user_customization_js(), array(), null, true );
655 +
656 + $query = $this->getQuery();
657 + while ( $query->have_posts() ) {
658 + $chart = $query->next_post();
659 + $library = $this->load_chart_type( $chart->ID );
660 + if ( is_null( $library ) ) {
661 + continue;
662 + }
663 + wp_enqueue_script(
664 + "visualizer-render-$library",
665 + VISUALIZER_ABSURL . 'js/render-facade.js',
666 + apply_filters( 'visualizer_assets_render', array( 'visualizer-library', 'visualizer-customization' ), true ),
667 + Visualizer_Plugin::VERSION,
668 + true
669 + );
670 + }
286 671 }
287 672 }
288 673
289 674 /**
@@ -310,24 +695,191 @@
310 695 *
311 696 * @access public
312 697 */
313 698 public function registerAdminMenu() {
314 - $title = esc_html__( 'Visualizer Library', 'visualizer' );
315 - $callback = array( $this, 'renderLibraryPage' );
316 - $this->_libraryPage = add_submenu_page( 'upload.php', $title, $title, 'edit_posts', Visualizer_Plugin::NAME, $callback );
699 + $svg_base64_icon = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iNzdweCIgaGVpZ2h0PSI3N3B4IiB2aWV3Qm94PSIwIDAgNzcgNzciIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICA8IS0tIEdlbmVyYXRvcjogU2tldGNoIDUyLjYgKDY3NDkxKSAtIGh0dHA6Ly93d3cuYm9oZW1pYW5jb2RpbmcuY29tL3NrZXRjaCAtLT4KICAgIDx0aXRsZT5Db21iaW5lZCBTaGFwZTwvdGl0bGU+CiAgICA8ZGVzYz5DcmVhdGVkIHdpdGggU2tldGNoLjwvZGVzYz4KICAgIDxnIGlkPSJQcm9kdWN0LVBhZ2UiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPgogICAgICAgIDxnIGlkPSJXb3JkUHJlc3MtcGx1Z2lucyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTE5MC4wMDAwMDAsIC00MzUuMDAwMDAwKSIgZmlsbD0iIzM5QzNEMiI+CiAgICAgICAgICAgIDxwYXRoIGQ9Ik0yMjguNSw1MTIgQzIwNy4yMzcwMzcsNTEyIDE5MCw0OTQuNzYyOTYzIDE5MCw0NzMuNSBDMTkwLDQ1Mi4yMzcwMzcgMjA3LjIzNzAzNyw0MzUgMjI4LjUsNDM1IEMyNDkuNzYyOTYzLDQzNSAyNjcsNDUyLjIzNzAzNyAyNjcsNDczLjUgQzI2Nyw0OTQuNzYyOTYzIDI0OS43NjI5NjMsNTEyIDIyOC41LDUxMiBaIE0yNDYuODQzNzUsNDgzLjU5MjA1OSBMMjE1LjYyNSw0ODMuNTkyMDU5IEwyMTUuNjI1LDQ2MC44MjY1NDQgQzIxNS42MjUsNDYwLjE2NDU0NyAyMTUuMTA3NTc4LDQ1OS42MjgzNTkgMjE0LjQ2ODc1LDQ1OS42MjgzNTkgTDIxMi4xNTYyNSw0NTkuNjI4MzU5IEMyMTEuNTE3NDIyLDQ1OS42MjgzNTkgMjExLDQ2MC4xNjQ1NDcgMjExLDQ2MC44MjY1NDQgTDIxMSw0ODUuOTg4NDI5IEMyMTEsNDg3LjMxMTY3NCAyMTIuMDM1NTY2LDQ4OC4zODQ3OTggMjEzLjMxMjUsNDg4LjM4NDc5OCBMMjQ2Ljg0Mzc1LDQ4OC4zODQ3OTggQzI0Ny40ODI1NzgsNDg4LjM4NDc5OCAyNDgsNDg3Ljg0ODYxMSAyNDgsNDg3LjE4NjYxMyBMMjQ4LDQ4NC43OTAyNDQgQzI0OCw0ODQuMTI4MjQ2IDI0Ny40ODI1NzgsNDgzLjU5MjA1OSAyNDYuODQzNzUsNDgzLjU5MjA1OSBaIE0yNDQuNTMxMjUsNDYyLjAyNDcyOSBMMjM1Ljk5OTU3LDQ2Mi4wMjQ3MjkgQzIzNC40NTQ1MzEsNDYyLjAyNDcyOSAyMzMuNjgwNTY2LDQ2My45NjA1NDcgMjM0Ljc3MzIyMyw0NjUuMDkyODMyIEwyMzcuMTE0NjI5LDQ2Ny41MTkxNTYgTDIzMS44MTI1LDQ3My4wMTQzMzIgTDIyNi41MTAzNzEsNDY3LjUxOTkwNSBDMjI1LjYwNzA1MSw0NjYuNTgzODIzIDIyNC4xNDI5NDksNDY2LjU4MzgyMyAyMjMuMjQwMzUyLDQ2Ny41MTk5MDUgTDIxOC4yNzY0MjYsNDcyLjY2Mzg2MyBDMjE3LjgyNDc2Niw0NzMuMTMxOTA0IDIxNy44MjQ3NjYsNDczLjg5MDUwNSAyMTguMjc2NDI2LDQ3NC4zNTg1NDYgTDIxOS45MTEwNzQsNDc2LjA1MjQ4IEMyMjAuMzYyNzM0LDQ3Ni41MjA1MjEgMjIxLjA5NDc4NSw0NzYuNTIwNTIxIDIyMS41NDY0NDUsNDc2LjA1MjQ4IEwyMjQuODc1LDQ3Mi42MDI0NTYgTDIzMC4xNzcxMjksNDc4LjA5Njg4MyBDMjMxLjA4MDQ0OSw0NzkuMDMyOTY1IDIzMi41NDQ1NTEsNDc5LjAzMjk2NSAyMzMuNDQ3MTQ4LDQ3OC4wOTY4ODMgTDI0MC4zODQ2NDgsNDcwLjkwNzc3MyBMMjQyLjcyNjA1NSw0NzMuMzM0MDk4IEMyNDMuODE4NzExLDQ3NC40NjYzODIgMjQ1LjY4Njc3Nyw0NzMuNjY0MzQ3IDI0NS42ODY3NzcsNDcyLjA2MzI3MyBMMjQ1LjY4Njc3Nyw0NjMuMjIyOTE0IEMyNDUuNjg3NSw0NjIuNTYwOTE3IDI0NS4xNzAwNzgsNDYyLjAyNDcyOSAyNDQuNTMxMjUsNDYyLjAyNDcyOSBaIiBpZD0iQ29tYmluZWQtU2hhcGUiPjwvcGF0aD4KICAgICAgICA8L2c+CiAgICA8L2c+Cjwvc3ZnPg==';
700 +
701 + $this->_libraryPage = add_menu_page( __( 'Visualizer', 'visualizer' ), __( 'Visualizer', 'visualizer' ), 'edit_posts', Visualizer_Plugin::NAME, array( $this, 'renderLibraryPage' ), $svg_base64_icon, 99.7666 );
702 +
703 + add_submenu_page(
704 + Visualizer_Plugin::NAME,
705 + __( 'Chart Library', 'visualizer' ),
706 + __( 'Chart Library', 'visualizer' ),
707 + 'edit_posts',
708 + 'admin.php?page=' . Visualizer_Plugin::NAME
709 + );
710 + add_submenu_page(
711 + Visualizer_Plugin::NAME,
712 + __( 'Add New Chart', 'visualizer' ),
713 + __( 'Add New Chart', 'visualizer' ),
714 + 'edit_posts',
715 + 'admin.php?page=' . Visualizer_Plugin::NAME . '&vaction=addnew'
716 + );
717 + add_submenu_page(
718 + Visualizer_Plugin::NAME,
719 + __( 'Support', 'visualizer' ),
720 + __( '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>',
721 + 'edit_posts',
722 + 'viz-support',
723 + array( $this, 'renderSupportPage' )
724 + );
725 +
726 + remove_submenu_page( Visualizer_Plugin::NAME, Visualizer_Plugin::NAME );
727 +
728 + add_action( "load-{$this->_libraryPage}", array( $this, 'addScreenOptions' ) );
729 + add_action( 'admin_footer', array( $this, 'handleGetProSubMenu' ) );
317 730 }
318 731
319 732 /**
320 - * Renders visualizer library page.
321 - *
322 - * @since 1.0.0
323 - *
324 - * @access public
733 + * Handle get pro plugin submenu.
325 734 */
326 - public function renderLibraryPage() {
735 + public function handleGetProSubMenu() {
736 + if ( ! Visualizer_Module::is_pro() ) {
737 + ?>
738 + <style type="text/css">
739 + #toplevel_page_visualizer ul.wp-submenu li:last-child {
740 + background: #FF7E65;
741 + font-size: 14px;
742 + font-weight: 600;
743 + color: #fff;
744 + }
745 + #toplevel_page_visualizer ul.wp-submenu li:last-child > a > span {
746 + color: #fff !important;
747 + }
748 + #toplevel_page_visualizer ul.wp-submenu li:last-child > a:hover {
749 + box-shadow: inherit;
750 + }
751 + </style>
752 + <?php
753 + if ( get_option( 'visualizer_fresh_install', false ) ) {
754 + ?>
755 + <style type="text/css">
756 + #toplevel_page_visualizer ul.wp-submenu li.wp-first-item + li + li + li {
757 + display: none;
758 + }
759 + </style>
760 + <?php
761 + }
762 + }
763 + }
764 +
765 + /**
766 + * Adds the screen options for pagination.
767 + */
768 + function addScreenOptions() {
769 + $screen = get_current_screen();
770 +
771 + // bail if it's some other page.
772 + if ( ! is_object( $screen ) || $screen->id !== $this->_libraryPage ) {
773 + return;
774 + }
775 +
776 + $args = array(
777 + 'label' => __( 'Number of charts per page:', 'visualizer' ),
778 + 'default' => 6,
779 + 'option' => 'visualizer_library_per_page',
780 + );
781 + add_screen_option( 'per_page', $args );
782 + }
783 +
784 + /**
785 + * Returns the screen option for pagination.
786 + */
787 + function setScreenOptions( $status, $option, $value ) {
788 + if ( 'visualizer_library_per_page' === $option ) {
789 + return $value;
790 + }
791 + }
792 +
793 + /**
794 + * Adds the display filters to be used in the meta_query while displaying the charts.
795 + */
796 + private function getDisplayFilters( &$query_args ) {
797 + $query = array();
798 + global $sitepress;
799 + if ( Visualizer_Module::is_pro() && ( function_exists( 'icl_get_languages' ) && $sitepress instanceof \SitePress ) ) {
800 + $current_lang = icl_get_current_language();
801 + if ( in_array( $current_lang, array( 'all', icl_get_default_language() ), true ) ) {
802 + $query[] = array(
803 + 'key' => 'chart_lang',
804 + 'compare' => 'NOT EXISTS',
805 + );
806 + } else {
807 + $query[] = array(
808 + 'key' => 'chart_lang',
809 + 'value' => $current_lang,
810 + 'compare' => '=',
811 + );
812 + }
813 + }
814 +
815 + // add chart type filter to the query arguments
816 + $type = filter_input( INPUT_GET, 'type' );
817 + if ( $type && in_array( $type, Visualizer_Plugin::getChartTypes(), true ) ) {
818 + $query[] = array(
819 + 'key' => Visualizer_Plugin::CF_CHART_TYPE,
820 + 'value' => $type,
821 + 'compare' => '=',
822 + );
823 + }
824 +
825 + // add chart library filter to the query arguments
826 + $library = filter_input( INPUT_GET, 'library' );
827 + if ( $library ) {
828 + $query[] = array(
829 + 'key' => Visualizer_Plugin::CF_CHART_LIBRARY,
830 + 'value' => $library,
831 + 'compare' => '=',
832 + );
833 + }
834 +
835 + // add date filter to the query arguments
836 + $date = filter_input( INPUT_GET, 'date' );
837 + $possible = array_keys( Visualizer_Plugin::getSupportedDateFilter() );
838 + if ( $date && in_array( $date, $possible, true ) ) {
839 + $query_args['date_query'] = array(
840 + 'after' => "$date -1 day",
841 + 'inclusive' => true,
842 + );
843 + }
844 +
845 + // add source filter to the query arguments
846 + $source = filter_input( INPUT_GET, 'source' );
847 + if ( $source ) {
848 + $source = ucwords( $source );
849 + $source = "Visualizer_Source_{$source}";
850 + $query[] = array(
851 + 'key' => Visualizer_Plugin::CF_SOURCE,
852 + 'value' => $source,
853 + 'compare' => '=',
854 + );
855 + }
856 +
857 + $query_args['meta_query'] = $query;
858 +
859 + $orderby = filter_input( INPUT_GET, 'orderby' );
860 + $order = filter_input( INPUT_GET, 'order' );
861 + if ( $orderby ) {
862 + $query_args['order_by'] = $orderby;
863 + }
864 + $query_args['order'] = empty( $order ) ? 'desc' : $order;
865 + }
866 +
867 + /**
868 + * Get the instance of WP_Query that fetches the charts as per the given criteria.
869 + */
870 + private function getQuery() {
871 + static $q;
872 + if ( ! is_null( $q ) ) {
873 + return $q;
874 + }
875 +
327 876 // get current page
328 877 $page = filter_input(
329 - INPUT_GET, 'vpage', FILTER_VALIDATE_INT, array(
878 + INPUT_GET,
879 + 'vpage',
880 + FILTER_VALIDATE_INT,
881 + array(
330 882 'options' => array(
331 883 'min_range' => 1,
332 884 'default' => 1,
333 885 ),
@@ -332,29 +884,34 @@
332 884 'default' => 1,
333 885 ),
334 886 )
335 887 );
888 +
889 + $per_page = 6;
890 + $screen = get_current_screen();
891 + if ( $screen ) {
892 + // retrieve the per_page option
893 + $screen_option = $screen->get_option( 'per_page', 'option' );
894 + // retrieve the value stored for the current user
895 + $user = get_current_user_id();
896 + $per_page = get_user_meta( $user, $screen_option, true );
897 + if ( empty( $per_page ) || $per_page < 1 ) {
898 + // nothing set, get the default value
899 + $per_page = $screen->get_option( 'per_page', 'default' );
900 + }
901 + }
902 +
336 903 // the initial query arguments to fetch charts
337 904 $query_args = array(
338 905 'post_type' => Visualizer_Plugin::CPT_VISUALIZER,
339 - 'posts_per_page' => 6,
906 + 'posts_per_page' => $per_page,
340 907 'paged' => $page,
341 908 );
342 - // add chart type filter to the query arguments
343 - $filter = filter_input( INPUT_GET, 'type' );
344 - if ( $filter && in_array( $filter, Visualizer_Plugin::getChartTypes() ) ) {
345 - $query_args['meta_query'] = array(
346 - array(
347 - 'key' => Visualizer_Plugin::CF_CHART_TYPE,
348 - 'value' => $filter,
349 - 'compare' => '=',
350 - ),
351 - );
352 - } else {
353 - $filter = 'all';
354 - }
909 +
910 + $this->getDisplayFilters( $query_args );
911 +
355 912 // Added by Ash/Upwork
356 - $filterByMeta = filter_input( INPUT_GET, 's', FILTER_SANITIZE_STRING );
913 + $filterByMeta = ! empty( $_GET['s'] ) ? sanitize_text_field( wp_unslash( $_GET['s'] ) ) : null; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
357 914 if ( $filterByMeta ) {
358 915 $query = array(
359 916 'key' => Visualizer_Plugin::CF_SETTINGS,
360 917 'value' => $filterByMeta,
@@ -363,49 +920,160 @@
363 920 $meta = isset( $query_args['meta_query'] ) ? $query_args['meta_query'] : array();
364 921 $meta[] = $query;
365 922 $query_args['meta_query'] = $meta;
366 923 }
367 - // Added by Ash/Upwork
368 - // fetch charts
924 + $q = new WP_Query( apply_filters( 'visualizer_query_args', $query_args ) );
925 + return $q;
926 + }
927 +
928 + /**
929 + * Renders support page.
930 + *
931 + * @since 3.3.0
932 + *
933 + * @access public
934 + */
935 + public function renderSupportPage() {
936 + wp_enqueue_style( 'visualizer-upsell', VISUALIZER_ABSURL . 'css/upsell.css', array(), Visualizer_Plugin::VERSION );
937 + $this->load_survey();
938 + include_once VISUALIZER_ABSPATH . '/templates/support.php';
939 + }
940 +
941 + /**
942 + * Renders visualizer library page.
943 + *
944 + * @since 1.0.0
945 + *
946 + * @access public
947 + */
948 + public function renderLibraryPage() {
369 949 $charts = array();
370 - $query = new WP_Query( $query_args );
950 + $query = $this->getQuery();
951 +
952 + // get current page
953 + $page = filter_input(
954 + INPUT_GET,
955 + 'vpage',
956 + FILTER_VALIDATE_INT,
957 + array(
958 + 'options' => array(
959 + 'min_range' => 1,
960 + 'default' => 1,
961 + ),
962 + )
963 + );
964 + // add chart type filter to the query arguments
965 + $filter = filter_input( INPUT_GET, 'type' );
966 + if ( ! ( $filter && in_array( $filter, Visualizer_Plugin::getChartTypes(), true ) ) ) {
967 + $filter = 'all';
968 + }
969 +
970 + $css = '';
371 971 while ( $query->have_posts() ) {
372 972 $chart = $query->next_post();
973 +
974 + // 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.
975 + $chart = $this->handleExistingRevisions( $chart->ID, $chart );
976 + // refresh a "live" db query chart.
977 + $chart = apply_filters( 'visualizer_schedule_refresh_chart', $chart, $chart->ID, false );
978 +
979 + $type = get_post_meta( $chart->ID, Visualizer_Plugin::CF_CHART_TYPE, true );
980 +
373 981 // fetch and update settings
374 982 $settings = get_post_meta( $chart->ID, Visualizer_Plugin::CF_SETTINGS, true );
375 - unset( $settings['height'], $settings['width'] );
376 - $type = get_post_meta( $chart->ID, Visualizer_Plugin::CF_CHART_TYPE, true );
983 +
984 + $settings = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_SETTINGS, $settings, $chart->ID, $type );
985 + if ( ! empty( $atts['settings'] ) ) {
986 + $settings = apply_filters( $atts['settings'], $settings, $chart->ID, $type );
987 + }
988 +
989 + if ( $settings ) {
990 + unset( $settings['height'], $settings['width'], $settings['chartArea'] );
991 + }
992 +
377 993 $series = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_SERIES, get_post_meta( $chart->ID, Visualizer_Plugin::CF_SERIES, true ), $chart->ID, $type );
378 - $data = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_DATA, unserialize( html_entity_decode( $chart->post_content ) ), $chart->ID, $type );
994 + $data = self::get_chart_data( $chart, $type );
995 +
996 + // Set default setting series when add manual chart data - Only during first creation.
997 + if ( isset( $settings['series'] ) && ! empty( $series ) ) {
998 + $count_series = count( $series ) - count( $settings['series'] );
999 + if ( $count_series > 1 ) {
1000 + $clone_last_series = end( $settings['series'] );
1001 + $clone_last_series = array_fill_keys( array_keys( $clone_last_series ), '' );
1002 + foreach ( range( 1, $count_series ) as $item ) {
1003 + $settings['series'][] = $clone_last_series;
1004 + }
1005 + }
1006 + }
1007 +
1008 + $library = $this->load_chart_type( $chart->ID );
1009 +
1010 + $id = 'visualizer-' . $chart->ID;
1011 + $arguments = $this->get_inline_custom_css( $id, $settings );
1012 + if ( ! empty( $arguments ) ) {
1013 + $css .= $arguments[0];
1014 + $settings = $arguments[1];
1015 + }
1016 +
1017 + if ( isset( $settings['controls']['ui']['labelStacking'] ) ) {
1018 + unset( $settings['controls']['ui']['labelStacking'] );
1019 + }
1020 + if ( isset( $settings['controls']['ui']['orientation'] ) ) {
1021 + unset( $settings['controls']['ui']['orientation'] );
1022 + }
1023 +
379 1024 // add chart to the array
380 - $charts[ 'visualizer-' . $chart->ID ] = array(
1025 + $charts[ $id ] = array(
381 1026 'id' => $chart->ID,
382 1027 'type' => $type,
383 1028 'series' => $series,
384 1029 'settings' => $settings,
385 1030 'data' => $data,
1031 + 'library' => $library,
386 1032 );
387 1033 }
388 1034 // enqueue charts array
389 1035 $ajaxurl = admin_url( 'admin-ajax.php' );
1036 +
390 1037 wp_localize_script(
391 - 'visualizer-library', 'visualizer', array(
1038 + 'visualizer-library',
1039 + 'visualizer',
1040 + array(
1041 + 'language' => $this->get_language(),
1042 + 'map_api_key' => get_option( 'visualizer-map-api-key' ),
392 1043 'charts' => $charts,
393 1044 'urls' => array(
394 - 'base' => add_query_arg( 'vpage', false ),
395 - 'create' => add_query_arg(
396 - array(
397 - 'action' => Visualizer_Plugin::ACTION_CREATE_CHART,
398 - 'library' => 'yes',
399 - ), $ajaxurl
1045 + 'base' => esc_url( add_query_arg( array( 'vpage' => false, 'vaction' => false ) ) ),
1046 + 'create' => esc_url(
1047 + add_query_arg(
1048 + array(
1049 + 'action' => Visualizer_Plugin::ACTION_CREATE_CHART,
1050 + 'library' => 'yes',
1051 + 'type' => isset( $_GET['type'] ) ? $_GET['type'] : '',
1052 + 'chart-library' => isset( $_GET['chart-library'] ) ? $_GET['chart-library'] : '',
1053 + 'vaction' => false,
1054 + ),
1055 + $ajaxurl
1056 + )
400 1057 ),
401 - 'edit' => add_query_arg(
402 - array(
403 - 'action' => Visualizer_Plugin::ACTION_EDIT_CHART,
404 - 'library' => 'yes',
405 - ), $ajaxurl
1058 + 'edit' => esc_url(
1059 + add_query_arg(
1060 + array(
1061 + 'action' => Visualizer_Plugin::ACTION_EDIT_CHART,
1062 + 'library' => 'yes',
1063 + 'vaction' => false,
1064 + ),
1065 + $ajaxurl
1066 + )
406 1067 ),
407 1068 ),
1069 + 'page_type' => 'library',
1070 + 'is_front' => false,
1071 + 'i10n' => array(
1072 + 'copied' => __( 'The shortcode has been copied to your clipboard. Hit Ctrl-V/Cmd-V to paste it.', 'visualizer' ),
1073 + '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' ),
1074 + ),
1075 + 'is_pro_user' => Visualizer_Module::is_pro(),
408 1076 )
409 1077 );
410 1078 // render library page
411 1079 $render = new Visualizer_Render_Library();
@@ -410,12 +1078,13 @@
410 1078 // render library page
411 1079 $render = new Visualizer_Render_Library();
412 1080 $render->charts = $charts;
413 1081 $render->type = $filter;
414 - $render->types = self::_getChartTypesLocalized();
1082 + $render->types = self::_getChartTypesLocalized( false, false, false, true );
1083 + $render->custom_css = $css;
415 1084 $render->pagination = paginate_links(
416 1085 array(
417 - 'base' => add_query_arg( 'vpage', '%#%' ),
1086 + 'base' => add_query_arg( array( 'vpage' => '%#%', 'vaction' => false ) ),
418 1087 'format' => '',
419 1088 'current' => $page,
420 1089 'total' => $query->max_num_pages,
421 1090 'type' => 'array',
@@ -420,8 +1089,15 @@
420 1089 'total' => $query->max_num_pages,
421 1090 'type' => 'array',
422 1091 )
423 1092 );
1093 +
1094 + $this->load_survey();
1095 +
1096 + if ( ! apply_filters( 'visualizer_is_business', false ) ) {
1097 + do_action( 'themeisle_sdk_load_banner', 'visualizer' );
1098 + }
1099 +
424 1100 $render->render();
425 1101 }
426 1102
427 1103 /**
@@ -436,14 +1112,14 @@
436 1112 *
437 1113 * @return array Updated array of action links.
438 1114 */
439 1115 public function getPluginActionLinks( $links, $file ) {
440 - if ( $file == plugin_basename( VISUALIZER_BASEFILE ) ) {
1116 + if ( $file === plugin_basename( VISUALIZER_BASEFILE ) ) {
441 1117 array_unshift(
442 1118 $links,
443 1119 sprintf(
444 1120 '<a href="%s">%s</a>',
445 - admin_url( 'upload.php?page=' . Visualizer_Plugin::NAME ),
1121 + admin_url( 'admin.php?page=' . Visualizer_Plugin::NAME ),
446 1122 esc_html__( 'Library', 'visualizer' )
447 1123 )
448 1124 );
449 1125 }
@@ -463,18 +1139,18 @@
463 1139 *
464 1140 * @return array Updated array of plugin meta links.
465 1141 */
466 1142 public function getPluginMetaLinks( $plugin_meta, $plugin_file ) {
467 - if ( $plugin_file == plugin_basename( VISUALIZER_BASEFILE ) ) {
1143 + if ( $plugin_file === plugin_basename( VISUALIZER_BASEFILE ) ) {
468 1144 // knowledge base link
469 1145 $plugin_meta[] = sprintf(
470 - '<a href="https://github.com/codeinwp/visualizer/wiki" target="_blank">%s</a>',
471 - esc_html__( 'Knowledge Base', 'visualizer' )
1146 + '<a href="' . VISUALIZER_MAIN_DOC . '" target="_blank">%s</a>',
1147 + esc_html__( 'Docs', 'visualizer' )
472 1148 );
473 1149 // flattr link
474 1150 $plugin_meta[] = sprintf(
475 - '<a style="color:red" href="https://themeisle.com/plugins/visualizer-charts-and-graphs-pro-addon/" target="_blank">%s</a>',
476 - esc_html__( 'Pro Addon', 'visualizer' )
1151 + '<a style="color:red" href="' . tsdk_utmify( Visualizer_Plugin::PRO_TEASER_URL, 'pluginrow' ) . '" target="_blank">%s</a>',
1152 + esc_html__( 'Get Visualizer Pro', 'visualizer' )
477 1153 );
478 1154 }
479 1155
480 1156 return $plugin_meta;
@@ -479,5 +1155,146 @@
479 1155
480 1156 return $plugin_meta;
481 1157 }
482 1158
1159 + /**
1160 + * If check is existing user.
1161 + *
1162 + * @return bool Default false
1163 + */
1164 + public static function proFeaturesLocked() {
1165 + if ( Visualizer_Module::is_pro() ) {
1166 + return true;
1167 + }
1168 + return 'yes' === get_option( 'visualizer-new-user', 'yes' ) ? false : true;
1169 + }
1170 +
1171 + /**
1172 + * Multilingual Support.
1173 + *
1174 + * @param int $chart_id Chart ID.
1175 + * @return bool Default false
1176 + */
1177 + public function addMultilingualSupport( $chart_id ) {
1178 + global $sitepress;
1179 + if ( Visualizer_Module::is_pro() ) {
1180 + return;
1181 + }
1182 + if ( function_exists( 'icl_get_languages' ) && $sitepress instanceof \SitePress ) {
1183 + $language = icl_get_languages();
1184 + $current_lang = icl_get_current_language();
1185 + $default_lang = icl_get_default_language();
1186 + $post_info = wpml_get_language_information( null, $chart_id );
1187 + $translations = array();
1188 + if ( ! empty( $post_info ) && ( $default_lang === $post_info['language_code'] ) ) {
1189 + $trid = $sitepress->get_element_trid( $chart_id, 'post_' . Visualizer_Plugin::CPT_VISUALIZER );
1190 + $translations = $sitepress->get_element_translations( $trid );
1191 + }
1192 + if ( empty( $translations ) ) {
1193 + return;
1194 + }
1195 + ?>
1196 + <hr><div class="visualizer-languages-list only-pro">
1197 + <?php
1198 + foreach ( $language as $lang ) {
1199 + $lang_code = $lang['code'];
1200 + if ( $current_lang !== $lang_code ) {
1201 + ?>
1202 + <a href="javascript:;">
1203 + <img src="<?php echo esc_url( $lang['country_flag_url'] ); ?>" alt="<?php echo esc_attr( $lang['translated_name'] ); ?>">
1204 + </a>
1205 + <?php
1206 + }
1207 + }
1208 + ?>
1209 + <a href="<?php echo tsdk_utmify( Visualizer_Plugin::PRO_TEASER_URL, 'wpml-support', 'visualizer_render_char' ); ?>"target="_blank"><?php esc_html_e( 'Upgrade to PRO to active this translation for charts', 'visualizer' ); ?></a>
1210 + </div>
1211 + <?php
1212 + }
1213 + }
1214 +
1215 + /**
1216 + * Check chart is enabled or not.
1217 + *
1218 + * @param string $type Chart ID.
1219 + *
1220 + * @return bool Default false
1221 + */
1222 + public static function checkChartStatus( $type ) {
1223 + $types = self::_getChartTypesLocalized( false, false, false, true );
1224 + if ( isset( $types[ $type ] ) ) {
1225 + return ! empty( $types[ $type ]['enabled'] );
1226 + }
1227 + return false;
1228 + }
1229 +
1230 + /**
1231 + * Get the survey metadata.
1232 + *
1233 + * @return array The survey metadata.
1234 + */
1235 + private function get_survey_metadata() {
1236 + $install_date = get_option( 'visualizer_install', false );
1237 + $install_category = 0;
1238 +
1239 + if ( false !== $install_date ) {
1240 + $days_since_install = round( ( time() - $install_date ) / DAY_IN_SECONDS );
1241 +
1242 + if ( 0 === $days_since_install || 1 === $days_since_install ) {
1243 + $install_category = 0;
1244 + } elseif ( 1 < $days_since_install && 8 > $days_since_install ) {
1245 + $install_category = 7;
1246 + } elseif ( 8 <= $days_since_install && 31 > $days_since_install ) {
1247 + $install_category = 30;
1248 + } elseif ( 30 < $days_since_install && 90 > $days_since_install ) {
1249 + $install_category = 90;
1250 + } elseif ( 90 <= $days_since_install ) {
1251 + $install_category = 91;
1252 + }
1253 + }
1254 +
1255 + $plugin_data = get_plugin_data( VISUALIZER_BASEFILE, false, false );
1256 + $plugin_version = '';
1257 + if ( ! empty( $plugin_data['Version'] ) ) {
1258 + $plugin_version = $plugin_data['Version'];
1259 + }
1260 +
1261 + $user_id = 'visualizer_' . preg_replace( '/[^\w\d]*/', '', get_site_url() ); // Use a normalized version of the site URL as a user ID.
1262 +
1263 + $license_data = get_option( 'visualizer_pro_license_data', false );
1264 + if ( false !== $license_data && isset( $license_data->key ) ) {
1265 + $user_id = 'visualizer_' . $license_data->key;
1266 + }
1267 +
1268 + return array(
1269 + 'userId' => $user_id,
1270 + 'attributes' => array(
1271 + 'days_since_install' => strval( $install_category ),
1272 + 'free_version' => $plugin_version,
1273 + 'pro_version' => defined( 'VISUALIZER_PRO_VERSION' ) ? VISUALIZER_PRO_VERSION : '',
1274 + 'license_status' => apply_filters( 'product_visualizer_license_status', 'invalid' ),
1275 + ),
1276 + );
1277 + }
1278 +
1279 + /**
1280 + * Load the survey.
1281 + */
1282 + private function load_survey() {
1283 +
1284 + if ( defined( 'TI_CYPRESS_TESTING' ) ) {
1285 + return;
1286 + }
1287 +
1288 + $survey_handler = apply_filters( 'themeisle_sdk_dependency_script_handler', 'survey' );
1289 +
1290 + if ( empty( $survey_handler ) ) {
1291 + return;
1292 + }
1293 +
1294 + $metadata = $this->get_survey_metadata();
1295 +
1296 + do_action( 'themeisle_sdk_dependency_enqueue_script', 'survey' );
1297 + wp_enqueue_script( 'visualizer_chart_survey', VISUALIZER_ABSURL . 'js/survey.js', array( $survey_handler ), $metadata['attributes']['free_version'], true );
1298 + wp_localize_script( 'visualizer_chart_survey', 'visualizerSurveyData', $metadata );
1299 + }
483 1300 }