PluginProbe ʕ •ᴥ•ʔ
YITH WooCommerce Wishlist / 4.0.1
YITH WooCommerce Wishlist v4.0.1
trunk 2.1.0 2.1.1 2.1.2 2.2.0 2.2.1 2.2.10 2.2.11 2.2.12 2.2.13 2.2.14 2.2.15 2.2.16 2.2.17 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 2.2.7 2.2.8 2.2.9 3.0.0 3.0.1 3.0.10 3.0.11 3.0.12 3.0.13 3.0.14 3.0.15 3.0.16 3.0.17 3.0.18 3.0.19 3.0.2 3.0.20 3.0.21 3.0.22 3.0.23 3.0.25 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.1 3.10.0 3.11.0 3.12.0 3.13.0 3.14.0 3.15.0 3.16.0 3.17.0 3.18.0 3.19.0 3.2.0 3.20.0 3.21.0 3.22.0 3.23.0 3.24.0 3.25.0 3.26.0 3.27.0 3.28.0 3.29.0 3.3.0 3.30.0 3.31.0 3.32.0 3.33.0 3.34.0 3.35.0 3.36.0 3.37.0 3.38.0 3.4.0 3.5.0 3.6.0 3.7.0 3.8.0 3.9.0 4.0.0 4.0.1 4.1.0 4.10.0 4.10.1 4.10.2 4.11.0 4.12.0 4.13.0 4.14.0 4.15.0 4.2.0 4.3.0 4.4.0 4.5.0 4.6.0 4.7.0 4.8.0 4.9.0
yith-woocommerce-wishlist / plugin-fw / includes / class-yit-plugin-panel.php
yith-woocommerce-wishlist / plugin-fw / includes Last commit date
builders 2 years ago privacy 2 years ago class-yit-ajax.php 2 years ago class-yit-assets.php 2 years ago class-yit-cpt-unlimited.php 5 years ago class-yit-gradients.php 2 years ago class-yit-help-desk.php 2 years ago class-yit-icons.php 2 years ago class-yit-metabox.php 2 years ago class-yit-plugin-common.php 5 years ago class-yit-plugin-licence.php 2 years ago class-yit-plugin-panel-woocommerce.php 1 year ago class-yit-plugin-panel.php 1 year ago class-yit-plugin-subpanel.php 2 years ago class-yit-pointers.php 2 years ago class-yit-theme-licence.php 2 years ago class-yit-upgrade.php 5 years ago class-yit-video.php 5 years ago class-yith-bh-onboarding.php 3 years ago class-yith-dashboard.php 4 years ago class-yith-debug.php 2 years ago class-yith-external-services.php 1 year ago class-yith-post-type-admin.php 2 years ago class-yith-system-status.php 1 year ago
class-yit-plugin-panel.php
2576 lines
1 <?php
2 /**
3 * YITH Plugin Panel Class.
4 *
5 * @class YIT_Plugin_Panel
6 * @author YITH <plugins@yithemes.com>
7 * @package YITH\PluginFramework\Classes
8 */
9
10 defined( 'ABSPATH' ) || exit; // Exit if accessed directly.
11
12 if ( ! class_exists( 'YIT_Plugin_Panel' ) ) {
13 /**
14 * Class YIT_Plugin_Panel
15 */
16 class YIT_Plugin_Panel {
17 /**
18 * Version of the class.
19 *
20 * @var string
21 */
22 public $version = '1.0.0';
23
24 /**
25 * List of settings parameters.
26 *
27 * @var array
28 */
29 public $settings = array();
30
31 /**
32 * Tab Path Files.
33 *
34 * @var array
35 */
36 protected $tabs_path_files;
37
38 /**
39 * Main array of options.
40 *
41 * @var array
42 */
43 protected $main_array_options;
44
45 /**
46 * Tabs hierarchy.
47 *
48 * @var array
49 */
50 protected $tabs_hierarchy;
51
52 /**
53 * Tabs in WP Pages.
54 *
55 * @var array
56 */
57 protected static $panel_tabs_in_wp_pages = array();
58
59 /**
60 * Array of links.
61 *
62 * @var array
63 */
64 public $links;
65
66 /**
67 * Are the actions initialized?
68 *
69 * @var bool
70 */
71 protected static $actions_initialized = false;
72
73 /**
74 * Notices to be shown in the panel.
75 *
76 * @var array
77 */
78 protected $notices = array();
79
80 /**
81 * YIT_Plugin_Panel constructor.
82 *
83 * @param array $args The panel arguments.
84 */
85 public function __construct( $args = array() ) {
86 if ( ! empty( $args ) ) {
87 $default_args = array(
88 'parent_slug' => 'edit.php?',
89 'page_title' => __( 'Plugin Settings', 'yith-plugin-fw' ),
90 'menu_title' => __( 'Settings', 'yith-plugin-fw' ),
91 'capability' => 'manage_options',
92 'icon_url' => '',
93 'position' => null,
94 );
95
96 $args = apply_filters( 'yit_plugin_fw_panel_option_args', wp_parse_args( $args, $default_args ) );
97 if ( isset( $args['parent_page'] ) && 'yit_plugin_panel' === $args['parent_page'] ) {
98 $args['parent_page'] = 'yith_plugin_panel';
99 }
100
101 $this->settings = $args;
102 $this->tabs_path_files = $this->get_tabs_path_files();
103
104 $this->settings['ui_version'] = $this->settings['ui_version'] ?? 1;
105
106 $this->init_admin_tabs();
107
108 if ( isset( $this->settings['create_menu_page'] ) && $this->settings['create_menu_page'] ) {
109 $this->add_menu_page();
110 }
111
112 if ( ! empty( $this->settings['links'] ) ) {
113 $this->links = $this->settings['links'];
114 }
115
116 $this->maybe_init_your_store_tools_tab();
117 $this->maybe_init_help_tab();
118 $this->maybe_init_premium_tab();
119 $this->maybe_init_welcome_modals();
120
121 add_filter( 'admin_body_class', array( $this, 'add_body_class' ) );
122 add_action( 'admin_init', array( $this, 'register_settings' ) );
123 add_action( 'admin_menu', array( $this, 'add_setting_page' ), 20 );
124 add_action( 'admin_menu', array( $this, 'add_premium_version_upgrade_to_menu' ), 100 );
125 add_action( 'admin_bar_menu', array( $this, 'add_admin_bar_menu' ), 100 );
126 add_action( 'admin_init', array( $this, 'add_fields' ) );
127
128 add_action( 'admin_enqueue_scripts', array( $this, 'init_wp_with_tabs' ), 11 );
129 add_action( 'admin_init', array( $this, 'maybe_redirect_to_proper_wp_page' ) );
130
131 /* Add UTM tracking code on premium tab */
132 add_filter( 'yith_plugin_fw_premium_landing_uri', array( $this, 'add_utm_data_on_premium_tab' ), 10, 2 );
133 // Init actions once to prevent multiple initialization.
134 static::init_actions();
135 }
136
137 add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
138 add_action( 'wp_ajax_yith_plugin_fw_save_toggle_element', array( $this, 'save_toggle_element_options' ) );
139 }
140
141 /**
142 * Init the admin tabs.
143 *
144 * @since 4.0.0
145 */
146 protected function init_admin_tabs() {
147 foreach ( $this->settings['admin-tabs'] as $key => $tab ) {
148 if ( ! is_array( $tab ) ) {
149 $this->settings['admin-tabs'][ $key ] = array(
150 'title' => $tab,
151 'description' => '',
152 'icon' => '',
153 );
154 }
155 }
156 }
157
158 /**
159 * Retrieve the UI version of the panel.
160 *
161 * @return int
162 * @since 4.0.0
163 */
164 protected function get_ui_version() {
165 return absint( $this->settings['ui_version'] );
166 }
167
168 /**
169 * Is this a custom post type page?
170 *
171 * @return bool
172 * @see YIT_Plugin_Panel::init_wp_with_tabs
173 * @since 3.4.17
174 */
175 protected function is_custom_post_type_page() {
176 global $pagenow, $post_type;
177 $excluded_post_types = array( 'product', 'page', 'post' );
178
179 return in_array( $pagenow, array( 'post.php', 'post-new.php', 'edit.php' ), true ) && ! in_array( $post_type, $excluded_post_types, true );
180 }
181
182 /**
183 * Is this a custom taxonomy page?
184 *
185 * @return bool
186 * @see YIT_Plugin_Panel::init_wp_with_tabs
187 * @since 3.4.17
188 */
189 protected function is_custom_taxonomy_page() {
190 global $pagenow, $taxonomy;
191 $excluded_taxonomies = array( 'category', 'post_tag', 'product_cat', 'product_tag' );
192
193 return in_array( $pagenow, array( 'edit-tags.php', 'term.php' ), true ) && ! in_array( $taxonomy, $excluded_taxonomies, true );
194 }
195
196 /**
197 * Init actions to show YITH Panel tabs in WP Pages
198 *
199 * @since 3.4.0
200 */
201 public function init_wp_with_tabs() {
202 if ( ! current_user_can( $this->settings['capability'] ) ) {
203 return;
204 }
205
206 global $post_type, $taxonomy;
207 $tabs = false;
208
209 if ( $this->is_custom_post_type_page() ) {
210 $tabs = $this->get_post_type_tabs( $post_type );
211 } elseif ( $this->is_custom_taxonomy_page() ) {
212 $tabs = $this->get_taxonomy_tabs( $taxonomy );
213 }
214
215 $screen = function_exists( 'get_current_screen' ) ? get_current_screen() : false;
216 $is_block_editor = ! ! $screen && is_callable( array( $screen, 'is_block_editor' ) ) && $screen->is_block_editor();
217
218 if ( $tabs ) {
219 $current_tab_args = array(
220 'page' => $this->settings['page'],
221 'current_tab' => isset( $tabs['tab'] ) ? $tabs['tab'] : '',
222 'current_sub_tab' => isset( $tabs['sub_tab'] ) ? $tabs['sub_tab'] : '',
223 'options' => isset( $tabs['options'] ) ? $tabs['options'] : array(),
224 );
225
226 if ( ! $is_block_editor ) {
227 if ( 1 === $this->get_ui_version() ) {
228 wp_enqueue_style( 'yit-plugin-style' );
229 } else {
230 // Set the old plugin framework style to be empty, to prevent issues if any plugin is enqueueing it directly.
231 wp_deregister_style( 'yit-plugin-style' );
232 wp_register_style( 'yit-plugin-style', false, array(), yith_plugin_fw_get_version() );
233 }
234 wp_enqueue_style( 'yith-plugin-panel' );
235 wp_enqueue_style( 'yith-plugin-fw-fields' );
236 wp_enqueue_script( 'yith-plugin-fw-wp-pages' );
237 }
238
239 if ( ! self::$panel_tabs_in_wp_pages ) {
240 self::$panel_tabs_in_wp_pages = $current_tab_args;
241 if ( ! $is_block_editor ) {
242 add_action( 'all_admin_notices', array( $this, 'print_panel_tabs_in_wp_pages' ) );
243 add_action( 'admin_footer', array( $this, 'print_panel_tabs_in_wp_pages_end' ) );
244 }
245 add_filter( 'parent_file', array( $this, 'set_parent_file_to_handle_menu_for_wp_pages' ) );
246 add_filter( 'submenu_file', array( $this, 'set_submenu_file_to_handle_menu_for_wp_pages' ), 10, 2 );
247 }
248 }
249 }
250
251 /**
252 * Init actions.
253 *
254 * @since 3.0.0
255 */
256 protected static function init_actions() {
257 if ( ! static::$actions_initialized ) {
258 // Sort plugins by name in YITH Plugins menu.
259 add_action( 'admin_menu', array( __CLASS__, 'sort_plugins' ), 90 );
260 add_filter( 'add_menu_classes', array( __CLASS__, 'add_menu_class_in_yith_plugin' ) );
261 add_filter( 'removable_query_args', array( __CLASS__, 'removable_query_args' ), 10, 2 );
262
263 static::$actions_initialized = true;
264 }
265 }
266
267 /**
268 * Handle removable query args.
269 *
270 * @param array $args Query args to be removed.
271 *
272 * @return array
273 * @since 4.4.2
274 */
275 public static function removable_query_args( $args ) {
276 $args[] = 'yith-plugin-fw-panel-skip-redirect';
277
278 return $args;
279 }
280
281 /**
282 * Maybe init vars
283 */
284 protected function maybe_init_vars() {
285 if ( ! isset( $this->main_array_options ) && ! isset( $this->tabs_hierarchy ) ) {
286 $options_path = $this->settings['options-path'];
287 $this->main_array_options = array();
288 $this->tabs_hierarchy = array();
289
290 foreach ( $this->settings['admin-tabs'] as $item => $tab ) {
291 $path = trailingslashit( $options_path ) . $item . '-options.php';
292 $path = apply_filters( 'yith_plugin_panel_item_options_path', $path, $options_path, $item, $this );
293 if ( file_exists( $path ) ) {
294 $_tab = $this->get_options_from_path( $path );
295 $this->main_array_options = array_merge( $this->main_array_options, $_tab );
296 $sub_tabs = $this->get_sub_tabs( $_tab );
297 $current_tab_key = array_keys( $_tab )[0];
298
299 $this->tabs_hierarchy[ $current_tab_key ] = array_merge(
300 array(
301 'parent' => '',
302 'has_sub_tabs' => ! ! $sub_tabs,
303 ),
304 $this->get_tab_info_by_options( $_tab[ $current_tab_key ] ),
305 array(
306 'title' => $tab['title'],
307 'description' => $tab['description'] ?? '',
308 )
309 );
310
311 foreach ( $sub_tabs as $sub_item => $sub_options ) {
312 if ( strpos( $sub_item, $item . '-' ) === 0 ) {
313 $sub_item = substr( $sub_item, strlen( $item ) + 1 );
314 }
315 $sub_tab_path = $sub_options['options_path'] ?? ( $options_path . '/' . $item . '/' . $sub_item . '-options.php' );
316 $sub_tab_path = apply_filters( 'yith_plugin_panel_sub_tab_item_options_path', $sub_tab_path, $sub_tabs, $sub_item, $this );
317
318 if ( file_exists( $sub_tab_path ) ) {
319 $_sub_tab = $this->get_options_from_path( $sub_tab_path );
320 $this->main_array_options = array_merge( $this->main_array_options, $_sub_tab );
321
322 $current_sub_tab_key = array_keys( $_sub_tab )[0];
323 $this->tabs_hierarchy[ $current_sub_tab_key ] = array_merge(
324 array( 'parent' => $current_tab_key ),
325 $this->get_tab_info_by_options( $_sub_tab[ $current_sub_tab_key ] ),
326 array(
327 'title' => $sub_options['title'],
328 'description' => $sub_options['description'] ?? '',
329 )
330 );
331 }
332 }
333 }
334 }
335 }
336 }
337
338 /**
339 * Add a notice to be shown in the panel.
340 *
341 * @param string $message The message.
342 * @param string $type The type of the notice. Use the same types of the "notice" component.
343 *
344 * @return void
345 * @since 4.0.0
346 */
347 public function add_notice( string $message, string $type = 'info' ) {
348 $this->notices[] = array(
349 'message' => $message,
350 'type' => $type,
351 );
352 }
353
354 /**
355 * Retrieve the notices to be shown.
356 *
357 * @return array
358 * @since 4.0.0
359 */
360 public function get_notices(): array {
361 return $this->notices;
362 }
363
364 /**
365 * Add body classes in Panel pages
366 *
367 * @param string $classes Body classes.
368 *
369 * @return string
370 * @since 3.0.0
371 */
372 public function add_body_class( $classes ) {
373 global $pagenow;
374
375 if ( ( 'admin.php' === $pagenow && strpos( get_current_screen()->id, $this->settings['page'] ) !== false ) || $this->get_current_tab() ) {
376 $to_add = array( 'yith-plugin-fw-panel', 'yith-plugin-fw-panel--version-' . $this->get_ui_version() );
377 foreach ( $to_add as $class_to_add ) {
378 $classes = ! substr_count( $classes, " $class_to_add " ) ? $classes . " $class_to_add " : $classes;
379 }
380 }
381
382 return $classes;
383 }
384
385 /**
386 * Add Menu page link
387 */
388 public function add_menu_page() {
389 global $admin_page_hooks;
390
391 if ( ! isset( $admin_page_hooks['yith_plugin_panel'] ) ) {
392 $position = apply_filters( 'yit_plugins_menu_item_position', '62.32' );
393 $capability = apply_filters( 'yit_plugin_panel_menu_page_capability', 'manage_options' );
394 $show = apply_filters( 'yit_plugin_panel_menu_page_show', true );
395
396 // YITH text must NOT be translated.
397 if ( ! ! $show ) {
398 add_menu_page( 'yith_plugin_panel', 'YITH', $capability, 'yith_plugin_panel', null, yith_plugin_fw_get_default_logo(), $position );
399 // Prevent issues for backward compatibility.
400 $admin_page_hooks['yith_plugin_panel'] = 'yith-plugins'; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
401 }
402 }
403 }
404
405 /**
406 * Remove duplicate submenu
407 * Submenu page hack: Remove the duplicate YIT Plugin link on subpages
408 */
409 public function remove_duplicate_submenu_page() {
410 remove_submenu_page( 'yith_plugin_panel', 'yith_plugin_panel' );
411 }
412
413 /**
414 * Enqueue script and styles in admin side
415 * Add style and scripts to administrator
416 */
417 public function admin_enqueue_scripts() {
418 global $pagenow;
419
420 $is_current_panel = $this->is_current_panel( false );
421
422 if ( $is_current_panel || apply_filters( 'yit_plugin_panel_asset_loading', false ) ) {
423 wp_enqueue_media();
424
425 if ( $is_current_panel ) {
426 if ( 1 === $this->get_ui_version() ) {
427 wp_enqueue_style( 'yit-plugin-style' );
428 } else {
429 // Set the old plugin framework style to be empty, to prevent issues if any plugin is enqueueing it directly.
430 wp_deregister_style( 'yit-plugin-style' );
431 wp_register_style( 'yit-plugin-style', false, array(), yith_plugin_fw_get_version() );
432 }
433 }
434
435 wp_enqueue_style( 'yith-plugin-fw-fields' );
436 wp_enqueue_style( 'jquery-ui-style' );
437 wp_enqueue_style( 'yith-plugin-panel' );
438
439 wp_enqueue_script( 'jquery-ui' );
440 wp_enqueue_script( 'jquery-ui-core' );
441 wp_enqueue_script( 'jquery-ui-dialog' );
442 wp_enqueue_script( 'yith_how_to' );
443 wp_enqueue_script( 'yith-plugin-fw-fields' );
444
445 wp_enqueue_media();
446 wp_enqueue_script( 'yit-plugin-panel' );
447 }
448
449 if ( 'admin.php' === $pagenow && strpos( get_current_screen()->id, 'yith_upgrade_premium_version' ) !== false ) {
450 wp_enqueue_style( 'yit-upgrade-to-pro' );
451 wp_enqueue_script( 'colorbox' );
452 }
453
454 if ( $this->is_current_panel( true ) ) {
455 do_action( 'yith_plugin_fw_panel_enqueue_scripts', $this );
456 }
457 }
458
459 /**
460 * Register Settings
461 * Generate wp-admin settings pages by registering your settings and using a few callbacks to control the output
462 */
463 public function register_settings() {
464 register_setting( 'yit_' . $this->settings['parent'] . '_options', 'yit_' . $this->settings['parent'] . '_options', array( $this, 'options_validate' ) );
465 }
466
467 /**
468 * Add Setting SubPage
469 * add Setting SubPage to WordPress administrator
470 */
471 public function add_setting_page() {
472 $this->settings['icon_url'] = isset( $this->settings['icon_url'] ) ? $this->settings['icon_url'] : '';
473 $this->settings['position'] = isset( $this->settings['position'] ) ? $this->settings['position'] : null;
474 $parent = $this->settings['parent_slug'] . $this->settings['parent_page'];
475
476 if ( ! empty( $parent ) ) {
477 add_submenu_page( $parent, $this->settings['page_title'], $this->settings['menu_title'], $this->settings['capability'], $this->settings['page'], array( $this, 'yit_panel' ) );
478 } else {
479 add_menu_page( $this->settings['page_title'], $this->settings['menu_title'], $this->settings['capability'], $this->settings['page'], array( $this, 'yit_panel' ), $this->settings['icon_url'], $this->settings['position'] );
480 }
481 // Duplicate Items Hack.
482 $this->remove_duplicate_submenu_page();
483 do_action( 'yit_after_add_settings_page' );
484
485 }
486
487 /**
488 * Options Validate
489 * a callback function called by Register Settings function
490 *
491 * @param array $field The field to validate.
492 *
493 * @return array validated fields
494 */
495 public function options_validate( $field ) {
496 $option_key = ! empty( $field['option_key'] ) ? $field['option_key'] : 'general';
497 $yit_options = $this->get_main_array_options();
498 $validated_fields = $this->get_options();
499
500 if ( isset( $yit_options[ $option_key ] ) ) {
501 foreach ( $yit_options[ $option_key ] as $section => $data ) {
502 foreach ( $data as $key => $option ) {
503 if ( ! empty( $option['is_option_disabled'] ) ) {
504 unset( $yit_options[ $option_key ][ $section ][ $key ] );
505 continue;
506 }
507
508 if ( isset( $option['sanitize_call'] ) && isset( $option['id'] ) ) {
509 if ( is_array( $option['sanitize_call'] ) ) {
510 foreach ( $option['sanitize_call'] as $callback ) {
511 if ( is_array( $field[ $option['id'] ] ) ) {
512 $validated_fields[ $option['id'] ] = array_map( $callback, $field[ $option['id'] ] );
513 } else {
514 $validated_fields[ $option['id'] ] = call_user_func( $callback, $field[ $option['id'] ] );
515 }
516 }
517 } else {
518 if ( is_array( $field[ $option['id'] ] ) ) {
519 $validated_fields[ $option['id'] ] = array_map( $option['sanitize_call'], $field[ $option['id'] ] );
520 } else {
521 $validated_fields[ $option['id'] ] = call_user_func( $option['sanitize_call'], $field[ $option['id'] ] );
522 }
523 }
524 } else {
525 if ( isset( $option['id'] ) ) {
526 $value = $field[ $option['id'] ] ?? false;
527 if ( isset( $option['type'] ) && in_array( $option['type'], array( 'checkbox', 'onoff' ), true ) ) {
528 $value = yith_plugin_fw_is_true( $value ) ? 'yes' : 'no';
529 }
530
531 if ( ! empty( $option['yith-sanitize-callback'] ) && is_callable( $option['yith-sanitize-callback'] ) ) {
532 $value = call_user_func( $option['yith-sanitize-callback'], $value );
533 }
534
535 $validated_fields[ $option['id'] ] = $value;
536 }
537 }
538 }
539 }
540 }
541
542 return $validated_fields;
543 }
544
545 /**
546 * Add Premium Version upgrade menu item
547 *
548 * @since 2.9.13
549 */
550 public function add_premium_version_upgrade_to_menu() {
551 // Add the How To menu item only if the customer haven't a premium version enabled.
552 if ( function_exists( 'YIT_Plugin_Licence' ) && ! ! YIT_Plugin_Licence()->get_products() ) {
553 return;
554 }
555
556 global $submenu;
557 if ( apply_filters( 'yit_show_upgrade_to_premium_version', isset( $submenu['yith_plugin_panel'] ) ) ) {
558 $how_to_menu = array(
559 sprintf( '%s%s%s', '<span id="yith-how-to-premium">', __( 'How to install premium version', 'yith-plugin-fw' ), '</span>' ),
560 'install_plugins',
561 '//support.yithemes.com/hc/en-us/articles/217840988',
562 __( 'How to install premium version', 'yith-plugin-fw' ),
563 );
564 $submenu['yith_plugin_panel']['how_to'] = $how_to_menu; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
565 }
566 }
567
568 /**
569 * Print the tabs navigation
570 *
571 * @param array $nav_args Nav Arguments.
572 *
573 * @since 3.4.0
574 */
575 public function print_tabs_nav( $nav_args = array() ) {
576 $defaults = array(
577 'current_tab' => $this->get_current_tab(),
578 'current_sub_tab' => $this->get_current_sub_tab(),
579 'premium_class' => isset( $this->settings['class'] ) ? 'yith-premium' : 'premium',
580 'page' => $this->settings['page'],
581 'parent_page' => $this->settings['parent_page'],
582 'wrapper_class' => $this->get_ui_version() > 1 ? '' : 'nav-tab-wrapper',
583 );
584 $nav_args = wp_parse_args( $nav_args, $defaults );
585
586 $this->get_template(
587 'panel-nav.php',
588 array(
589 'panel' => $this,
590 'nav_args' => $nav_args,
591 )
592 );
593 }
594
595 /**
596 * Retrieve the Nav URL.
597 *
598 * @param string $page The page.
599 * @param string $tab The tab.
600 * @param string $sub_tab The sub-tab.
601 * @param string $parent_page The parent page.
602 *
603 * @return string
604 */
605 public function get_nav_url( $page, $tab, $sub_tab = '', $parent_page = '' ) {
606 $tab_hierarchy = $this->get_tabs_hierarchy();
607 $key = ! ! $sub_tab ? $sub_tab : $tab;
608
609 if ( isset( $tab_hierarchy[ $key ], $tab_hierarchy[ $key ]['type'], $tab_hierarchy[ $key ]['post_type'] ) && 'post_type' === $tab_hierarchy[ $key ]['type'] ) {
610 $url = admin_url( "edit.php?post_type={$tab_hierarchy[$key]['post_type']}" );
611 } elseif ( isset( $tab_hierarchy[ $key ], $tab_hierarchy[ $key ]['type'], $tab_hierarchy[ $key ]['taxonomy'] ) && 'taxonomy' === $tab_hierarchy[ $key ]['type'] ) {
612 $url = admin_url( "edit-tags.php?taxonomy={$tab_hierarchy[$key]['taxonomy']}" );
613 } else {
614 $url = ! ! $parent_page ? "?{$parent_page}&" : '?';
615
616 $url .= "page={$page}&tab={$tab}";
617 $url .= ! ! $sub_tab ? "&sub_tab={$sub_tab}" : '';
618
619 $url = admin_url( "admin.php{$url}" );
620 }
621
622 return apply_filters( 'yith_plugin_fw_panel_url', $url, $page, $tab, $sub_tab, $parent_page );
623 }
624
625 /**
626 * Print the Sub-tabs navigation if the current tab has sub-tabs
627 *
628 * @param array $args Sub-tab arguments.
629 *
630 * @since 3.4.0
631 */
632 public function print_sub_tabs_nav( $args = array() ) {
633 $defaults = array(
634 'current_tab' => $this->get_current_tab(),
635 'page' => $this->settings['page'],
636 'current_sub_tab' => $this->get_current_sub_tab(),
637 );
638 $args = wp_parse_args( $args, $defaults );
639
640 /**
641 * The arguments.
642 *
643 * @var string $current_tab The current tab.
644 * @var string $page The page.
645 * @var string $current_sub_tab The current sub-tab.
646 */
647 extract( $args ); // phpcs:ignore WordPress.PHP.DontExtract.extract_extract
648
649 $sub_tabs = $this->get_sub_tabs( $current_tab );
650
651 if ( $sub_tabs && $current_sub_tab ) {
652 include YIT_CORE_PLUGIN_TEMPLATE_PATH . '/panel/sub-tabs-nav.php';
653 }
654 }
655
656 /**
657 * Get CSS classes of the panel content.
658 *
659 * @return string
660 * @since 4.4.0
661 */
662 public function get_panel_content_classes(): string {
663 return implode(
664 ' ',
665 array_filter(
666 array(
667 'yith-plugin-fw__panel__content',
668 $this->has_panel_header_nav() ? 'yith-plugin-fw__panel__content--has-header-nav' : '',
669 )
670 )
671 );
672 }
673
674 /**
675 * Print the panel content page.
676 *
677 * @since 4.0.0
678 */
679 public function render_panel_content_page() {
680 $yit_options = $this->get_main_array_options();
681 $option_key = $this->get_current_option_key();
682 $custom_tab_options = $this->get_custom_tab_options( $yit_options, $option_key );
683
684 if ( $this->is_premium_tab() && $this->has_premium_tab() ) {
685 $this->print_premium_tab();
686 } elseif ( $custom_tab_options ) {
687 $this->print_custom_tab( $custom_tab_options );
688 } elseif ( $this->is_help_tab() ) {
689 $this->print_help_tab();
690 } elseif ( $this->has_your_store_tools_tab() && $this->is_your_store_tools_tab() ) {
691 $this->print_your_store_tools_tab();
692 } else {
693 $this->get_template(
694 'panel-content-page.php',
695 array(
696 'panel' => $this,
697 'form_method' => apply_filters( 'yit_admin_panel_form_method', 'POST', $option_key ),
698 'panel_content_class' => apply_filters( 'yit_admin_panel_content_class', 'yit-admin-panel-content-wrap', $option_key ),
699 'option_key' => $option_key,
700 )
701 );
702 }
703 }
704
705 /**
706 * Maybe print the header nav.
707 *
708 * @return bool
709 * @since 4.4.0
710 */
711 public function has_panel_header_nav(): bool {
712 return $this->get_sub_tabs() && 'horizontal' === $this->get_sub_tabs_nav_layout();
713 }
714
715 /**
716 * Maybe print the header nav.
717 *
718 * @since 4.4.0
719 */
720 public function render_panel_header_nav() {
721 if ( ! $this->has_panel_header_nav() ) {
722 return;
723 }
724 $this->get_template(
725 'panel-header-nav.php',
726 array(
727 'panel' => $this,
728 'nav_args' => array(
729 'current_tab' => $this->get_current_tab(),
730 'current_sub_tab' => $this->get_current_sub_tab(),
731 'page' => $this->settings['page'],
732 'parent_page' => $this->settings['parent_page'],
733 ),
734 )
735 );
736 }
737
738 /**
739 * Print the mobile header.
740 *
741 * @since 4.0.0
742 */
743 protected function render_mobile_header() {
744 if ( $this->get_ui_version() > 1 ) {
745 $this->get_template(
746 'panel-mobile-header.php',
747 array(
748 'header_title' => $this->get_header_title(),
749 )
750 );
751 }
752 }
753
754 /**
755 * Show a tabbed panel to setting page
756 * a callback function called by add_setting_page => add_submenu_page
757 */
758 public function yit_panel() {
759 $wrap_class = $this->settings['class'] ?? '';
760 $option_key = $this->get_current_option_key();
761 $content_id = $this->settings['page'] . '_' . $option_key;
762
763 $this->render_panel_header();
764 ?>
765 <div class="yith-plugin-fw__wrap wrap <?php echo esc_attr( $wrap_class ); ?>">
766 <div id="icon-themes" class="icon32"><br/></div>
767 <?php
768 do_action( 'yith_plugin_fw_before_yith_panel', $this->settings['page'] );
769
770 $this->get_template(
771 'panel-content.php',
772 array(
773 'panel' => $this,
774 'content_id' => $content_id,
775 )
776 );
777 ?>
778 </div>
779 <?php
780 }
781
782 /**
783 * Check if is a custom tab.
784 *
785 * @param array $options The tab options.
786 * @param string $option_key The option key.
787 *
788 * @return string|false The action to be fired of false if it's not a custom tab.
789 */
790 public function is_custom_tab( $options, $option_key ) {
791 $option = $this->get_custom_tab_options( $options, $option_key );
792
793 return ! ! $option && isset( $option['action'] ) ? $option['action'] : false;
794 }
795
796 /**
797 * Retrieve the custom tab options.
798 *
799 * @param array $options The tab options.
800 * @param string $option_key The option key.
801 *
802 * @return array|false The options of the custom tab; false if it's not a custom tab.
803 */
804 public function get_custom_tab_options( $options, $option_key ) {
805 $option = ! empty( $options[ $option_key ] ) ? current( $options[ $option_key ] ) : false;
806
807 if ( $option && isset( $option['type'], $option['action'] ) && 'custom_tab' === $option['type'] && ! empty( $option['action'] ) ) {
808 // Inherit values for title and description, if it's a sub-tab/sub-page with show_container set to true.
809 if ( $this->get_ui_version() > 1 ) {
810 $hierarchy = $this->get_tabs_hierarchy();
811 $hierarchy_page_info = $hierarchy[ $option_key ] ?? array();
812 $parent = $hierarchy_page_info['parent'] ?? '';
813 $hierarchy_parent_info = $hierarchy[ $parent ] ?? array();
814 $inherited_values = array( 'title', 'description' );
815
816 if ( $hierarchy_page_info ) {
817 foreach ( $inherited_values as $inherited_value ) {
818 if ( ! isset( $option[ $inherited_value ] ) && isset( $hierarchy_page_info[ $inherited_value ] ) ) {
819 $option[ $inherited_value ] = $hierarchy_page_info[ $inherited_value ];
820 }
821 }
822 }
823 }
824
825 return $option;
826 } else {
827 return false;
828 }
829 }
830
831 /**
832 * Retrieve the tab type by its options.
833 *
834 * @param array $tab_options The tab options.
835 *
836 * @return string
837 */
838 public function get_tab_type_by_options( $tab_options ) {
839 $first = ! ! $tab_options && is_array( $tab_options ) ? current( $tab_options ) : array();
840 $type = isset( $first['type'] ) ? $first['type'] : 'options';
841 $special_types = array( 'post_type', 'taxonomy', 'custom_tab', 'multi_tab' );
842
843 return in_array( $type, $special_types, true ) ? $type : 'options';
844 }
845
846 /**
847 * Retrieve the tab info by its options.
848 *
849 * @param array $tab_options The tab options.
850 *
851 * @return string[]
852 */
853 public function get_tab_info_by_options( $tab_options ) {
854 $type = $this->get_tab_type_by_options( $tab_options );
855 $first = ! ! $tab_options && is_array( $tab_options ) ? current( $tab_options ) : array();
856 $info = $first;
857
858 $info['type'] = $type;
859 if ( 'post_type' === $type ) {
860 $info['post_type'] = $first['post_type'] ?? '';
861 } elseif ( 'taxonomy' === $type ) {
862 $info['taxonomy'] = $first['taxonomy'] ?? '';
863 }
864
865 return $info;
866 }
867
868 /**
869 * Fire the action to print the custom tab.
870 *
871 * @param array $options The options of the custom tab.
872 */
873 public function print_custom_tab( $options ) {
874 if ( is_string( $options ) ) {
875 // Backward compatibility.
876 $options = array( 'action' => $options );
877 }
878 $current_tab = $this->get_current_tab();
879 $current_sub_tab = $this->get_current_sub_tab();
880
881 $this->get_template( 'custom-tab.php', compact( 'options', 'current_tab', 'current_sub_tab' ) );
882 }
883
884 /**
885 * Check if panel has help tab
886 *
887 * @return bool Whether panel has help tab or no.
888 */
889 public function has_help_tab() {
890 return apply_filters( 'yith_plugin_fw_panel_has_help_tab', isset( $this->settings['help_tab'] ) && is_array( $this->settings['help_tab'] ) && ( ! $this->is_free() || ! empty( $this->settings['help_tab']['show_on_free'] ) ), $this );
891 }
892
893
894 /**
895 * Checks whether current tab is special Help Tab
896 *
897 * @return bool Whether current tab is Help Tab
898 */
899 public function is_help_tab() {
900 return 'help' === $this->get_current_tab();
901 }
902
903 /**
904 * Prints special Help Tab
905 *
906 * @return void
907 */
908 public function print_help_tab() {
909 $options = isset( $this->settings['help_tab'] ) ? $this->settings['help_tab'] : array();
910 $plugin_title = isset( $this->settings['plugin_title'] ) ? $this->settings['plugin_title'] : $this->settings['page_title'];
911 $is_extended = $this->is_extended();
912 $is_premium = $this->is_premium() || ! $is_extended;
913 $plugin_slug = $this->get_plugin_slug();
914
915 if ( 0 !== strpos( $plugin_title, 'YITH' ) ) {
916 $plugin_title = "YITH {$plugin_title}";
917 }
918
919 // translators: 1. Plugin name.
920 $default_title = $is_premium ? _x( 'Thank you for purchasing %s!', 'Help tab default title', 'yith-plugin-fw' ) : _x( 'Thank you for using %s!', 'Help tab default title', 'yith-plugin-fw' );
921 $default_doc_url = $this->get_doc_url();
922 $default_support_url = $is_extended ? trailingslashit( $default_doc_url ) . 'overview/need-support/' : 'https://yithemes.com/my-account/support/submit-a-ticket/';
923
924 // parse options.
925 $options = wp_parse_args(
926 $options,
927 array(
928 'title' => sprintf( $default_title, $plugin_title ),
929 'description' => _x( 'We want to help you enjoy a wonderful experience with all of our products.', 'Help tab default description', 'yith-plugin-fw' ),
930 'main_video' => false,
931 'playlists' => array(),
932 'hc_url' => 'https://support.yithemes.com/hc/',
933 'doc_url' => $default_doc_url,
934 'submit_ticket_url' => $default_support_url,
935 'show_hc_articles' => true,
936 'show_submit_ticket' => true,
937 )
938 );
939
940 // add campaign parameters to url.
941 if ( ! ! $plugin_slug && ! $is_extended ) {
942 $utm_medium = $plugin_slug;
943 $utm_campaign = 'help-tab';
944
945 $campaign_urls = array(
946 'submit_ticket_url',
947 'doc_url',
948 );
949
950 foreach ( $campaign_urls as $campaign_url ) {
951 if ( empty( $options[ $campaign_url ] ) ) {
952 continue;
953 }
954
955 $options[ $campaign_url ] = $this->add_utm_data( $options[ $campaign_url ], $utm_campaign );
956 }
957 }
958
959 // set template variables.
960 $current_tab = $this->get_current_tab();
961 $current_sub_tab = $this->get_current_sub_tab();
962 $latest_articles = ! ! $plugin_slug ? YIT_Help_Desk::get_latest_articles( $plugin_slug ) : array();
963
964 $options = apply_filters( 'yith_plugin_fw_panel_help_tab_options', $options, $this->settings );
965
966 include YIT_CORE_PLUGIN_TEMPLATE_PATH . '/panel/help-tab.php';
967 }
968
969 /**
970 * Add premium tab in admin-tabs if is set.
971 *
972 * @since 3.9.0
973 */
974 protected function maybe_init_premium_tab() {
975 if ( isset( $this->settings['premium_tab'] ) ) {
976 $this->settings['admin-tabs']['premium'] = array(
977 'title' => _x( 'Get premium', 'Premium tab name', 'yith-plugin-fw' ),
978 'icon' => 'premium',
979 'description' => '',
980 );
981 }
982 }
983
984 /**
985 * Initialize the "Your Store Tools" tab
986 *
987 * @since 4.1.0
988 */
989 protected function maybe_init_your_store_tools_tab() {
990 if ( isset( $this->settings['your_store_tools'] ) ) {
991 $this->settings['admin-tabs']['your-store-tools'] = array(
992 'title' => _x( 'Your Store Tools', 'Panel tab name', 'yith-plugin-fw' ),
993 'icon' => 'boost',
994 'description' => '',
995 );
996 }
997 }
998
999 /**
1000 * Add help tab in admin-tabs if is set.
1001 *
1002 * @since 3.9.0
1003 */
1004 protected function maybe_init_help_tab() {
1005 if ( $this->has_help_tab() ) {
1006 $this->settings['admin-tabs']['help'] = array(
1007 'title' => _x( 'Help', 'Help tab name', 'yith-plugin-fw' ),
1008 'icon' => 'help',
1009 'description' => '',
1010 );
1011 }
1012 }
1013
1014 /**
1015 * Get the plugin doc URL.
1016 *
1017 * @return string
1018 * @since 3.9.14
1019 */
1020 protected function get_doc_url() {
1021 $plugin_slug = sanitize_title( $this->get_plugin_slug() );
1022 if ( $plugin_slug ) {
1023 $doc_slug = $plugin_slug;
1024 if ( $this->is_extended() ) {
1025 $doc_slug .= '-extended';
1026 }
1027
1028 return "https://docs.yithemes.com/{$doc_slug}/";
1029 }
1030
1031 return '';
1032 }
1033
1034 /**
1035 * Is in panel?
1036 *
1037 * @return bool
1038 * @since 3.9.14
1039 */
1040 protected function is_panel(): bool {
1041 $is_panel = yith_plugin_fw_is_panel() && isset( $_GET['page'] ) && $_GET['page'] === $this->settings['page']; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
1042 $is_wp_page_in_panel = isset( self::$panel_tabs_in_wp_pages, self::$panel_tabs_in_wp_pages['page'] ) && self::$panel_tabs_in_wp_pages['page'] === $this->settings['page'];
1043
1044 return $is_panel || $is_wp_page_in_panel;
1045 }
1046
1047 /**
1048 * Is this the first panel page?
1049 *
1050 * @return bool
1051 * @since 3.9.14
1052 */
1053 protected function is_first_page(): bool {
1054 $is_first_page = false;
1055 if ( $this->is_panel() ) {
1056 $first_tab = current( array_keys( $this->settings['admin-tabs'] ?? array() ) );
1057 $sub_tabs = $this->get_sub_tabs( $first_tab );
1058 $first_sub_tab = current( array_keys( $sub_tabs ) );
1059
1060 $tab = $this->get_current_tab();
1061 $sub_tab = $this->get_current_sub_tab();
1062
1063 $is_first_page = $first_tab === $tab;
1064
1065 if ( $is_first_page && ! ! $first_sub_tab ) {
1066 $is_first_page = $first_sub_tab === $sub_tab;
1067 }
1068 }
1069
1070 return $is_first_page;
1071 }
1072
1073 /**
1074 * Add welcome modals.
1075 *
1076 * @since 3.9.14
1077 */
1078 protected function maybe_init_welcome_modals() {
1079 if ( isset( $this->settings['welcome_modals'] ) ) {
1080 // Priority needs to be greater than 11, to correctly check if it's first page also for WP pages.
1081 add_action( 'admin_enqueue_scripts', array( $this, 'maybe_print_welcome_modal' ), 20 );
1082 add_action( 'admin_init', array( $this, 'handle_welcome_modal_action' ) );
1083 }
1084 }
1085
1086 /**
1087 * Handle welcome modal actions.
1088 *
1089 * @since 3.9.14
1090 */
1091 public function handle_welcome_modal_action() {
1092 if ( isset( $_GET['yith-plugin-fw-welcome-modal-close'], $_GET['yith-panel-page'] ) && $_GET['yith-panel-page'] === $this->settings['page'] ) {
1093 check_admin_referer( 'welcome-modal-close' );
1094 $modal = sanitize_key( wp_unslash( $_GET['yith-plugin-fw-welcome-modal-close'] ) );
1095 $on_close = $this->settings['welcome_modals']['modals'][ $modal ]['on_close'] ?? $this->settings['welcome_modals']['on_close'] ?? false;
1096
1097 if ( $on_close && is_callable( $on_close ) ) {
1098 call_user_func( $on_close );
1099 }
1100
1101 wp_safe_redirect( add_query_arg( array( 'page' => $this->settings['page'] ), admin_url( 'admin.php' ) ) );
1102 exit();
1103 }
1104 }
1105
1106 /**
1107 * Print the welcome modal.
1108 *
1109 * @since 3.9.14
1110 */
1111 public function maybe_print_welcome_modal() {
1112 $settings = $this->settings['welcome_modals'] ?? array();
1113 $modals = $settings['modals'] ?? array();
1114 $show_in = $settings['show_in'] ?? 'panel';
1115
1116 if ( ! $this->is_panel() ) {
1117 return;
1118 }
1119
1120 $is_page_to_show = true;
1121
1122 switch ( $show_in ) {
1123 case 'panel':
1124 break;
1125 case 'first_page':
1126 $is_page_to_show = $this->is_first_page();
1127 break;
1128 default:
1129 if ( is_callable( $show_in ) ) {
1130 $context = array(
1131 'is_first_page' => $this->is_first_page(),
1132 'tab' => $this->get_current_tab(),
1133 'sub_tab' => $this->get_current_sub_tab(),
1134 );
1135 $is_page_to_show = call_user_func( $show_in, $context );
1136 }
1137 break;
1138 }
1139
1140 if ( $is_page_to_show ) {
1141 foreach ( $modals as $key => $modal ) {
1142 $show = $modal['show'] ?? null;
1143 $should_be_shown = ! ! ( is_callable( $show ) ? call_user_func( $show ) : $show );
1144 $modal['items'] = $modal['items'] ?? array();
1145
1146 if ( $should_be_shown ) {
1147 $type = $modal['type'] ?? $key;
1148 $template = YIT_CORE_PLUGIN_TEMPLATE_PATH . '/panel/welcome-modals/' . $type . '.php';
1149 $close_url = wp_nonce_url(
1150 add_query_arg(
1151 array(
1152 'yith-plugin-fw-welcome-modal-close' => $key,
1153 'yith-panel-page' => $this->settings['page'],
1154 ),
1155 admin_url()
1156 ),
1157 'welcome-modal-close'
1158 );
1159 $plugin = array(
1160 'name' => $this->get_plugin_name(),
1161 'version' => $this->settings['plugin_version'] ?? '',
1162 'slug' => $this->get_plugin_slug(),
1163 'icon' => $this->settings['plugin_icon'] ?? '',
1164 );
1165
1166 $plugin['version'] = preg_replace( '/\.0$/', '', $plugin['version'] ); // Make the version nicer.
1167
1168 if ( 'welcome' === $type ) {
1169 if ( isset( $modal['items']['documentation'] ) ) {
1170 $modal['items']['documentation'] = wp_parse_args(
1171 $modal['items']['documentation'],
1172 array(
1173 'title' => __( 'Read the <mark>plugin documentation</mark>', 'yith-plugin-fw' ),
1174 'description' => __( 'Learn what you can really do with this powerful tool', 'yith-plugin-fw' ),
1175 'url' => $this->get_doc_url(),
1176 )
1177 );
1178 }
1179
1180 if ( isset( $modal['items']['how-to-video'], $modal['items']['how-to-video']['url'] ) ) {
1181 $modal['items']['how-to-video'] = wp_parse_args(
1182 $modal['items']['how-to-video'],
1183 array(
1184 'title' => __( 'Watch our <mark>"First Steps" video</mark>', 'yith-plugin-fw' ),
1185 'description' => __( 'See how it works before you start using it', 'yith-plugin-fw' ),
1186 )
1187 );
1188 }
1189 }
1190
1191 if ( 'update' === $type ) {
1192 if ( ! isset( $modal['changelog_url'] ) && $this->is_premium() && ! $this->is_extended() ) {
1193 $doc_url = $this->get_doc_url();
1194 if ( $doc_url ) {
1195 $modal['changelog_url'] = trailingslashit( $doc_url ) . 'changelog/changelog-premium-version/';
1196 }
1197 }
1198 }
1199
1200 if ( file_exists( $template ) ) {
1201 wp_enqueue_script( 'yith-plugin-fw-welcome-modal' );
1202 wp_enqueue_style( 'yith-plugin-fw-welcome-modal' );
1203
1204 // Plugin, modal and close_url variables are required in the modal templates.
1205 $print_template_cb = function () use ( $template, $plugin, $modal, $close_url ) {
1206 ?>
1207 <script type="text/html" id="tmpl-yith-plugin-fw-welcome-modal">
1208 <?php include $template; ?>
1209 </script>
1210 <?php
1211 };
1212
1213 add_action( 'admin_footer', $print_template_cb );
1214 }
1215
1216 break;
1217 }
1218 }
1219 }
1220 }
1221
1222 /**
1223 * Checks whether current tab is Premium Tab
1224 *
1225 * @return bool
1226 * @since 3.9.0
1227 */
1228 protected function is_premium_tab() {
1229 return 'premium' === $this->get_current_tab();
1230 }
1231
1232 /**
1233 * Check if panel has premium tab
1234 * (Check for premium Tab through the premium_tab param fully handled by plugin-fw)
1235 *
1236 * @return bool
1237 * @since 3.9.0
1238 */
1239 protected function has_premium_tab() {
1240 return ! empty( $this->settings['premium_tab'] ) && ( $this->is_free() || $this->is_extended() );
1241 }
1242
1243 /**
1244 * Get the plugin pricing from API.
1245 *
1246 * @return array
1247 */
1248 protected function get_plugin_pricing() {
1249 $pricing = array();
1250 $slug = $this->get_plugin_slug();
1251 if ( $slug ) {
1252 $api_url = 'https://yithemes.com/wp-json/wc/v3/product-data/' . $slug;
1253 $params = array_filter(
1254 array(
1255 'currency' => function_exists( 'get_woocommerce_currency' ) ? get_woocommerce_currency() : null,
1256 'lang' => get_locale(),
1257 )
1258 );
1259
1260 $transient_name = 'yith_fw_plugin_pricing_' . md5( $slug . '_' . implode( '_', array_values( $params ) ) );
1261 $pricing = get_transient( $transient_name );
1262 if ( false === $pricing || ! is_array( $pricing ) ) {
1263 $url = add_query_arg( $params, $api_url );
1264 $response = wp_remote_get(
1265 $url,
1266 array(
1267 'timeout' => 5,
1268 'headers' => array( 'Content-Type' => 'application/json' ),
1269 )
1270 );
1271
1272 if ( wp_remote_retrieve_response_code( $response ) === 200 ) {
1273 $body = wp_remote_retrieve_body( $response );
1274 if ( $body ) {
1275 $pricing = json_decode( $body, true );
1276 }
1277 }
1278
1279 $pricing = is_array( $pricing ) ? $pricing : array();
1280 set_transient( $transient_name, $pricing, DAY_IN_SECONDS );
1281 }
1282 }
1283
1284 return $pricing;
1285 }
1286
1287 /**
1288 * Prints Premium Tab
1289 *
1290 * @return void
1291 * @since 3.9.0
1292 */
1293 protected function print_premium_tab() {
1294 $options = $this->settings['premium_tab'] ?? array();
1295 $plugin_slug = $this->get_plugin_slug();
1296
1297 $defaults = array(
1298 'features' => array(),
1299 'landing_page_url' => '',
1300 'show_free_vs_premium_link' => $this->is_free(),
1301 'testimonials' => array(
1302 array(
1303 'name' => 'Max Ackerman',
1304 'avatar' => YIT_CORE_PLUGIN_URL . '/assets/images/premium-tab/testimonial.jpg',
1305 'message' => __( "At first, I was hesitant to buy the premium version so I started with the free option.\nAfter a while, seeing the quality of the plugin and the results I was getting, I decided to give it a shot and switch to premium. No regrets!\nThey have an amazing support team that is always there no matter how big or small your problem is. Do yourself a favor and stop using free plugins that kind of work and just buy whatever plugin you need from YITH.", 'yith-plugin-fw' ),
1306 ),
1307 ),
1308 );
1309 $options = wp_parse_args( $options, $defaults );
1310
1311 if ( ! $options['landing_page_url'] && $plugin_slug ) {
1312 $options['landing_page_url'] = 'https://yithemes.com/themes/plugins/' . $plugin_slug;
1313 }
1314
1315 // Map old options to new ones.
1316 if ( ! $options['features'] && ! empty( $options['premium_features'] ) ) {
1317 foreach ( $options['premium_features'] as $feature ) {
1318 $options['features'][] = array(
1319 'title' => '',
1320 'description' => $feature,
1321 );
1322 }
1323 }
1324
1325 $plugin_pricing = $this->get_plugin_pricing();
1326
1327 $this->get_template(
1328 'premium-tab.php',
1329 array(
1330 'panel' => $this,
1331 'features' => $options['features'],
1332 'testimonials' => $options['testimonials'],
1333 'landing_page_url' => ! ! $options['landing_page_url'] ? $this->add_utm_data( $options['landing_page_url'], 'premium-tab-button-upgrade' ) : '',
1334 'free_vs_premium_url' => ! ! $options['landing_page_url'] ? $this->add_utm_data( $options['landing_page_url'], 'premium-tab-button-upgrade' ) . '#tab-free_vs_premium_tab' : '',
1335 'show_free_vs_premium' => ! ! $options['show_free_vs_premium_link'],
1336 'pricing' => isset( $plugin_pricing['price_html'], $plugin_pricing['discount_percentage'] ) ? $plugin_pricing : array(),
1337 )
1338 );
1339 }
1340
1341 /**
1342 * Checks whether current tab is Premium Tab
1343 *
1344 * @return bool
1345 * @since 4.1.0
1346 */
1347 protected function is_your_store_tools_tab() {
1348 return 'your-store-tools' === $this->get_current_tab();
1349 }
1350
1351 /**
1352 * Check if panel has premium tab
1353 * (Check for premium Tab through the premium_tab param fully handled by plugin-fw)
1354 *
1355 * @return bool
1356 * @since 4.1.0
1357 */
1358 protected function has_your_store_tools_tab() {
1359 return ! empty( $this->settings['your_store_tools'] );
1360 }
1361
1362 /**
1363 * Prints Premium Tab
1364 *
1365 * @return void
1366 * @since 4.1.0
1367 */
1368 protected function print_your_store_tools_tab() {
1369 $options = $this->settings['your_store_tools'] ?? array();
1370
1371 $defaults = array(
1372 'items' => array(),
1373 );
1374 $options = wp_parse_args( $options, $defaults );
1375
1376 $item_defaults = array(
1377 'name' => '',
1378 'description' => '',
1379 'url' => '',
1380 'icon_url' => '',
1381 'is_active' => false,
1382 'is_recommended' => false,
1383 );
1384
1385 foreach ( $options['items'] as $key => $item ) {
1386 $item = wp_parse_args( $item, $item_defaults );
1387
1388 if ( $item['url'] ) {
1389 $plugin_ref = basename( wp_parse_url( $item['url'] )['path'] ?? '' );
1390 $item['url'] = $this->add_utm_data( $item['url'], 'your-store-tools', 'button-cta', $plugin_ref );
1391 }
1392
1393 $options['items'][ $key ] = $item;
1394 }
1395
1396 $this->get_template( 'your-store-tools-tab.php', $options );
1397 }
1398
1399 /**
1400 * Add sections and fields to setting panel.
1401 * Read all options and show sections and fields.
1402 */
1403 public function add_fields() {
1404 $yit_options = $this->get_main_array_options();
1405 $option_key = $this->get_current_option_key();
1406
1407 if ( ! $option_key || ! isset( $yit_options[ $option_key ] ) ) {
1408 return;
1409 }
1410
1411 foreach ( $yit_options[ $option_key ] as $section => $data ) {
1412 add_settings_section( "yit_settings_{$option_key}_{$section}", $this->get_section_title( $section ), '__return_empty_string', 'yit', array( 'description' => $this->get_section_description( $section ) ) );
1413 foreach ( $data as $option ) {
1414 if ( isset( $option['id'] ) && isset( $option['type'] ) && isset( $option['name'] ) ) {
1415 add_settings_field(
1416 'yit_setting_' . $option['id'],
1417 $option['name'],
1418 array( $this, 'render_field' ),
1419 'yit',
1420 "yit_settings_{$option_key}_{$section}",
1421 array(
1422 'option' => $option,
1423 'label_for' => $this->get_id_field( $option['id'] ),
1424 )
1425 );
1426 }
1427 }
1428 }
1429 }
1430
1431 /**
1432 * Add the tabs to admin bar menu.
1433 * Set all tabs of settings page on wp admin bar.
1434 */
1435 public function add_admin_bar_menu() {
1436 global $wp_admin_bar;
1437
1438 if ( ! current_user_can( 'manage_options' ) ) {
1439 return;
1440 }
1441
1442 if ( ! empty( $this->settings['admin_tabs'] ) ) {
1443 foreach ( $this->settings['admin-tabs'] as $key => $tab ) {
1444 $wp_admin_bar->add_menu(
1445 array(
1446 'parent' => $this->settings['parent'],
1447 'title' => $tab['title'],
1448 'id' => $this->settings['parent'] . '-' . $key,
1449 'href' => admin_url( 'themes.php' ) . '?page=' . $this->settings['parent_page'] . '&tab=' . $key,
1450 )
1451 );
1452 }
1453 }
1454 }
1455
1456 /**
1457 * Get current tab.
1458 * Retrieve the id of tab shown, return general is the current tab is not defined.
1459 *
1460 * @return string|false
1461 * @since 3.9.14 Check for WP pages.
1462 */
1463 public function get_current_tab() {
1464 // phpcs:disable WordPress.Security.NonceVerification.Recommended
1465 $admin_tabs = array_keys( $this->settings['admin-tabs'] );
1466 global $post_type, $taxonomy;
1467 $wp_tabs = array();
1468 if ( $this->is_custom_post_type_page() ) {
1469 $wp_tabs = $this->get_post_type_tabs( $post_type );
1470 } elseif ( $this->is_custom_taxonomy_page() ) {
1471 $wp_tabs = $this->get_taxonomy_tabs( $taxonomy );
1472 }
1473
1474 if ( $wp_tabs && isset( $wp_tabs['tab'] ) ) {
1475 return $wp_tabs['tab'];
1476 }
1477
1478 if ( ! isset( $_GET['page'] ) || $_GET['page'] !== $this->settings['page'] ) {
1479 return false;
1480 }
1481 if ( isset( $_REQUEST['yit_tab_options'] ) ) {
1482 return sanitize_key( wp_unslash( $_REQUEST['yit_tab_options'] ) );
1483 } elseif ( isset( $_GET['tab'] ) ) {
1484 return sanitize_key( wp_unslash( $_GET['tab'] ) );
1485 } elseif ( isset( $admin_tabs[0] ) ) {
1486 return $admin_tabs[0];
1487 } else {
1488 return 'general';
1489 }
1490 // phpcs:enable
1491 }
1492
1493 /**
1494 * Get the current sub-tab.
1495 *
1496 * @return string The key of the sub-tab if exists, empty string otherwise.
1497 * @since 3.4.0
1498 * @since 3.9.14 Check for WP pages.
1499 */
1500 public function get_current_sub_tab() {
1501 // phpcs:disable WordPress.Security.NonceVerification.Recommended
1502
1503 global $post_type, $taxonomy;
1504 $wp_tabs = array();
1505 if ( $this->is_custom_post_type_page() ) {
1506 $wp_tabs = $this->get_post_type_tabs( $post_type );
1507 } elseif ( $this->is_custom_taxonomy_page() ) {
1508 $wp_tabs = $this->get_taxonomy_tabs( $taxonomy );
1509 }
1510
1511 if ( $wp_tabs && isset( $wp_tabs['sub_tab'] ) ) {
1512 return $wp_tabs['sub_tab'];
1513 }
1514
1515 $sub_tabs = $this->get_sub_tabs();
1516 $sub_tab = isset( $_REQUEST['sub_tab'] ) ? sanitize_key( wp_unslash( $_REQUEST['sub_tab'] ) ) : '';
1517
1518 if ( $sub_tabs ) {
1519 if ( $sub_tab && ! isset( $sub_tabs[ $sub_tab ] ) || ! $sub_tab ) {
1520 $sub_tab = current( array_keys( $sub_tabs ) );
1521 }
1522 } else {
1523 $sub_tab = '';
1524 }
1525
1526 return $sub_tab;
1527 // phpcs:enable
1528 }
1529
1530 /**
1531 * Return the option key related to the current page.
1532 * for sub-tabbed tabs, it will return the current sub-tab.
1533 * fot normal tabs, it will return the current tab.
1534 *
1535 * @return string the current sub-tab, if exists; the current tab otherwise.
1536 * @since 3.4.0
1537 */
1538 public function get_current_option_key() {
1539 $current_tab = $this->get_current_tab();
1540 $current_sub_tab = $this->get_current_sub_tab();
1541
1542 if ( ! $current_tab || $this->is_custom_post_type_page() || $this->is_custom_taxonomy_page() ) {
1543 return false;
1544 }
1545
1546 return ! ! $current_sub_tab ? $current_sub_tab : $current_tab;
1547 }
1548
1549 /**
1550 * Message
1551 * define an array of message and show the content od message if
1552 * is find in the query string
1553 */
1554 public function message() {
1555 // phpcs:disable WordPress.Security.NonceVerification.Recommended
1556 $message = array(
1557 'element_exists' => $this->get_message( __( 'The element you have entered already exists. Please, enter another name.', 'yith-plugin-fw' ), 'error', false ),
1558 'saved' => $this->get_message( __( 'Settings saved', 'yith-plugin-fw' ) . '.', 'success', false ),
1559 'reset' => $this->get_message( __( 'Settings reset', 'yith-plugin-fw' ) . '.', 'success', false ),
1560 'delete' => $this->get_message( __( 'Element deleted correctly.', 'yith-plugin-fw' ), 'success', false ),
1561 'updated' => $this->get_message( __( 'Element updated correctly.', 'yith-plugin-fw' ), 'success', false ),
1562 'settings-updated' => $this->get_message( __( 'Options saved!', 'yith-plugin-fw' ), 'success', false ),
1563 'imported' => $this->get_message( __( 'Database imported correctly.', 'yith-plugin-fw' ), 'success', false ),
1564 'no-imported' => $this->get_message( __( 'An error has occurred during import. Please try again.', 'yith-plugin-fw' ), 'error', false ),
1565 'file-not-valid' => $this->get_message( __( 'The added file is not valid.', 'yith-plugin-fw' ), 'error', false ),
1566 'cant-import' => $this->get_message( __( 'Sorry, import is disabled.', 'yith-plugin-fw' ), 'error', false ),
1567 'ord' => $this->get_message( __( 'Sorting successful.', 'yith-plugin-fw' ), 'success', false ),
1568 );
1569
1570 foreach ( $message as $key => $value ) {
1571 if ( isset( $_GET[ $key ] ) ) {
1572 echo wp_kses_post( $message[ $key ] );
1573 }
1574 }
1575 // phpcs:enable
1576 }
1577
1578 /**
1579 * Get Message
1580 * return html code of message
1581 *
1582 * @param string $message The message.
1583 * @param string $type The type of message (can be 'error' or 'updated').
1584 * @param bool $echo Set to true if you want to print the message.
1585 *
1586 * @return string
1587 */
1588 public function get_message( $message, $type = 'error', $echo = true ) {
1589 return yith_plugin_fw_get_component(
1590 array(
1591 'type' => 'notice',
1592 'notice_type' => $type,
1593 'message' => $message,
1594 'inline' => $this->get_ui_version() > 1,
1595 ),
1596 $echo
1597 );
1598 }
1599
1600 /**
1601 * Get Tab Path Files
1602 * return an array with file names of tabs
1603 *
1604 * @return array
1605 */
1606 public function get_tabs_path_files() {
1607 $option_files_path = $this->settings['options-path'] . '/';
1608 $tabs = array();
1609
1610 foreach ( (array) glob( $option_files_path . '*.php' ) as $filename ) {
1611 preg_match( '/(.*)-options\.(.*)/', basename( $filename ), $filename_parts );
1612
1613 if ( ! isset( $filename_parts[1] ) ) {
1614 continue;
1615 }
1616
1617 $tab = $filename_parts[1];
1618 $tabs[ $tab ] = $filename;
1619 }
1620
1621 return $tabs;
1622 }
1623
1624 /**
1625 * Get main array options
1626 * return an array with all options defined on options-files
1627 *
1628 * @return array
1629 */
1630 public function get_main_array_options() {
1631 $this->maybe_init_vars();
1632
1633 return $this->main_array_options;
1634 }
1635
1636 /**
1637 * Get tab hierarchy.
1638 *
1639 * @return array
1640 */
1641 public function get_tabs_hierarchy() {
1642 $this->maybe_init_vars();
1643
1644 return $this->tabs_hierarchy;
1645 }
1646
1647 /**
1648 * Return the sub-tabs options
1649 *
1650 * @param array|bool $tab the tab; if not set it'll be the current tab.
1651 *
1652 * @since 4.4.0
1653 * @return array
1654 */
1655 protected function get_sub_tabs_options( $tab = false ): array {
1656 if ( false === $tab ) {
1657 $tab = $this->get_current_tab();
1658 }
1659
1660 if ( is_string( $tab ) ) {
1661 $main_array_options = $this->get_main_array_options();
1662 $current_tab_options = $main_array_options[ $tab ] ?? array();
1663 if ( $current_tab_options ) {
1664 $tab = array( $tab => $current_tab_options );
1665 }
1666 }
1667
1668 $tab_options = ! ! $tab && is_array( $tab ) ? current( $tab ) : false;
1669 $first = ! ! $tab_options && is_array( $tab_options ) ? current( $tab_options ) : false;
1670 if ( $first && is_array( $first ) && isset( $first['type'] ) && 'multi_tab' === $first['type'] ) {
1671 return $first;
1672 }
1673
1674 return array();
1675 }
1676
1677 /**
1678 * Return the sub-tabs layout
1679 *
1680 * @param array|bool $tab the tab; if not set it'll be the current tab.
1681 *
1682 * @since 4.4.0
1683 * @return string
1684 */
1685 public function get_sub_tabs_nav_layout( $tab = false ): string {
1686 $options = $this->get_sub_tabs_options( $tab );
1687 $allowed = array( 'vertical', 'horizontal' );
1688 $layout = $options['nav-layout'] ?? '';
1689
1690 return in_array( $layout, $allowed, true ) ? $layout : 'vertical';
1691 }
1692
1693 /**
1694 * Return the sub-tabs array of a specific tab
1695 *
1696 * @param array|bool $tab the tab; if not set it'll be the current tab.
1697 *
1698 * @since 3.4.0
1699 * @return array Sub-tabs array.
1700 */
1701 public function get_sub_tabs( $tab = false ): array {
1702 $options = $this->get_sub_tabs_options( $tab );
1703
1704 return $options['sub-tabs'] ?? array();
1705 }
1706
1707 /**
1708 * Retrieve the first sub-tab key.
1709 *
1710 * @param string|false $_tab The tab; if not set it'll be the current tab.
1711 *
1712 * @return false|mixed
1713 */
1714 public function get_first_sub_tab_key( $_tab = false ) {
1715 $key = false;
1716 if ( is_string( $_tab ) ) {
1717 $main_array_options = $this->get_main_array_options();
1718 $current_tab_options = isset( $main_array_options[ $_tab ] ) ? $main_array_options[ $_tab ] : array();
1719 if ( $current_tab_options ) {
1720 $_tab = array( $_tab => $current_tab_options );
1721 }
1722 }
1723 $sub_tabs = $this->get_sub_tabs( $_tab );
1724 if ( $sub_tabs ) {
1725 $key = current( array_keys( $sub_tabs ) );
1726 }
1727
1728 return $key;
1729 }
1730
1731 /**
1732 * Set an array with all default options
1733 * put default options in an array
1734 *
1735 * @return array
1736 */
1737 public function get_default_options() {
1738 $yit_options = $this->get_main_array_options();
1739 $default_options = array();
1740
1741 foreach ( $yit_options as $tab => $sections ) {
1742 foreach ( $sections as $section ) {
1743 foreach ( $section as $id => $value ) {
1744 if ( isset( $value['std'] ) && isset( $value['id'] ) ) {
1745 $default_options[ $value['id'] ] = $value['std'];
1746 }
1747 }
1748 }
1749 }
1750
1751 unset( $yit_options );
1752
1753 return $default_options;
1754 }
1755
1756 /**
1757 * Get the title of the tab
1758 * return the title of tab
1759 *
1760 * @return string
1761 */
1762 public function get_tab_title() {
1763 $yit_options = $this->get_main_array_options();
1764 $option_key = $this->get_current_option_key();
1765
1766 foreach ( $yit_options[ $option_key ] as $sections => $data ) {
1767 foreach ( $data as $option ) {
1768 if ( isset( $option['type'] ) && 'title' === $option['type'] ) {
1769 return $option['name'];
1770 }
1771 }
1772 }
1773
1774 return '';
1775 }
1776
1777 /**
1778 * Get the title of the section
1779 * return the title of section
1780 *
1781 * @param string $section The section.
1782 *
1783 * @return string
1784 */
1785 public function get_section_title( $section ) {
1786 $yit_options = $this->get_main_array_options();
1787 $option_key = $this->get_current_option_key();
1788 $title_types = $this->get_ui_version() > 1 ? array( 'title', 'section' ) : array( 'section' );
1789
1790 foreach ( $yit_options[ $option_key ][ $section ] as $option ) {
1791 if ( isset( $option['type'] ) && in_array( $option['type'], $title_types, true ) ) {
1792 return $option['name'];
1793 }
1794 }
1795
1796 return '';
1797 }
1798
1799 /**
1800 * Get the description of the section
1801 * return the description of section if is set
1802 *
1803 * @param string $section The section.
1804 *
1805 * @return string
1806 */
1807 public function get_section_description( $section ) {
1808 $yit_options = $this->get_main_array_options();
1809 $option_key = $this->get_current_option_key();
1810 $title_types = $this->get_ui_version() > 1 ? array( 'title', 'section' ) : array( 'section' );
1811
1812 foreach ( $yit_options[ $option_key ][ $section ] as $option ) {
1813 if ( isset( $option['type'] ) && in_array( $option['type'], $title_types, true ) && isset( $option['desc'] ) ) {
1814 return $option['desc'];
1815 }
1816 }
1817
1818 return '';
1819 }
1820
1821
1822 /**
1823 * Show form when necessary
1824 * return true if 'showform' is not defined
1825 *
1826 * @return bool
1827 */
1828 public function is_show_form() {
1829 $yit_options = $this->get_main_array_options();
1830 $option_key = $this->get_current_option_key();
1831
1832 foreach ( $yit_options[ $option_key ] as $sections => $data ) {
1833 foreach ( $data as $option ) {
1834 if ( ! isset( $option['type'] ) || 'title' !== $option['type'] ) {
1835 continue;
1836 }
1837 if ( isset( $option['showform'] ) ) {
1838 return $option['showform'];
1839 } else {
1840 return true;
1841 }
1842 }
1843 }
1844 }
1845
1846 /**
1847 * Get name field
1848 * return a string with the name of the input field
1849 *
1850 * @param string $name The name.
1851 *
1852 * @return string
1853 */
1854 public function get_name_field( $name = '' ) {
1855 return 'yit_' . $this->settings['parent'] . '_options[' . $name . ']';
1856 }
1857
1858 /**
1859 * Get id field
1860 * return a string with the id of the input field
1861 *
1862 * @param string $id The ID.
1863 *
1864 * @return string
1865 */
1866 public function get_id_field( $id ) {
1867 return 'yit_' . $this->settings['parent'] . '_options_' . $id;
1868 }
1869
1870
1871 /**
1872 * Render the field showed in the setting page
1873 * include the file of the option type, if file do not exists
1874 * return a text area
1875 *
1876 * @param array $param The parameters.
1877 *
1878 * @return void
1879 */
1880 public function render_field( $param ) {
1881 if ( ! empty( $param ) && isset( $param ['option'] ) ) {
1882
1883 if ( $this->get_ui_version() > 1 ) {
1884 $field = $param['option'];
1885 $field_id = $field['id'];
1886 $db_options = $this->get_options();
1887
1888 if ( 'on-off' === $field['type'] ) {
1889 $field['type'] = 'onoff';
1890 }
1891 $std = $field['std'] ?? '';
1892 $db_value = $db_options[ $field_id ] ?? $std;
1893 $field_template_path = yith_plugin_fw_get_field_template_path( $field );
1894 if ( $field_template_path ) {
1895 $field['id'] = $this->get_id_field( $field_id );
1896 $field['name'] = $this->get_name_field( $field_id );
1897 $field['value'] = $db_value;
1898
1899 yith_plugin_fw_get_field( $field, true, true );
1900 } else {
1901 do_action( "yit_panel_{$field['type']}", $field, $db_value );
1902 }
1903
1904 return;
1905 }
1906
1907 $option = $param['option'];
1908 $db_options = $this->get_options();
1909
1910 $custom_attributes = array();
1911
1912 if ( ! empty( $option['custom_attributes'] ) && is_array( $option['custom_attributes'] ) ) {
1913 foreach ( $option['custom_attributes'] as $attribute => $attribute_value ) {
1914 $custom_attributes[] = esc_attr( $attribute ) . '="' . esc_attr( $attribute_value ) . '"';
1915 }
1916 }
1917
1918 $custom_attributes = implode( ' ', $custom_attributes );
1919 $std = isset( $option['std'] ) ? $option['std'] : '';
1920 $db_value = ( isset( $db_options[ $option['id'] ] ) ) ? $db_options[ $option['id'] ] : $std;
1921
1922 if ( isset( $option['deps'] ) ) {
1923 $deps = $option['deps'];
1924 }
1925
1926 if ( 'on-off' === $option['type'] ) {
1927 $option['type'] = 'onoff';
1928 }
1929
1930 $field_template_path = yith_plugin_fw_get_field_template_path( $option );
1931 if ( $field_template_path ) {
1932 $field_container_path = apply_filters( 'yith_plugin_fw_panel_field_container_template_path', YIT_CORE_PLUGIN_TEMPLATE_PATH . '/panel/panel-field-container.php', $option );
1933 file_exists( $field_container_path ) && include $field_container_path;
1934 } else {
1935 do_action( "yit_panel_{$option['type']}", $option, $db_value, $custom_attributes );
1936 }
1937 }
1938 }
1939
1940 /**
1941 * Get options from db
1942 * return the options from db, if the options aren't defined in the db,
1943 * get the default options ad add the options in the db
1944 *
1945 * @return array
1946 */
1947 public function get_options() {
1948 $options = get_option( 'yit_' . $this->settings['parent'] . '_options' );
1949 if ( false === $options || ( isset( $_REQUEST['yit-action'] ) && 'reset' === sanitize_key( wp_unslash( $_REQUEST['yit-action'] ) ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
1950 $options = $this->get_default_options();
1951 }
1952
1953 return $options;
1954 }
1955
1956 /**
1957 * Show a box panel with specific content in two columns as a new woocommerce type
1958 *
1959 * @param array $args The arguments.
1960 */
1961 public static function add_infobox( $args = array() ) {
1962 if ( ! empty( $args ) ) {
1963 extract( $args ); // phpcs:ignore WordPress.PHP.DontExtract.extract_extract
1964 require YIT_CORE_PLUGIN_TEMPLATE_PATH . '/panel/boxinfo.php';
1965 }
1966 }
1967
1968 /**
1969 * Show a box panel with specific content in two columns as a new woocommerce type
1970 *
1971 * @param array $args Arguments.
1972 *
1973 * @return void
1974 * @deprecated 3.0.12 Do nothing! Method left to prevent Fatal Error if called directly
1975 */
1976 public static function add_videobox( $args = array() ) {
1977
1978 }
1979
1980 /**
1981 * Fire the action to print the custom tab
1982 *
1983 * @return void
1984 * @deprecated 3.0.12 Do nothing! Method left to prevent Fatal Error if called directly
1985 */
1986 public function print_video_box() {
1987
1988 }
1989
1990 /**
1991 * Sort plugins by name in YITH Plugins menu.
1992 *
1993 * @since 3.0.0
1994 */
1995 public static function sort_plugins() {
1996 global $submenu;
1997 if ( ! empty( $submenu['yith_plugin_panel'] ) ) {
1998 $sorted_plugins = $submenu['yith_plugin_panel'];
1999
2000 usort(
2001 $sorted_plugins,
2002 function ( $a, $b ) {
2003 return strcmp( current( $a ), current( $b ) );
2004 }
2005 );
2006
2007 $submenu['yith_plugin_panel'] = $sorted_plugins; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
2008 }
2009 }
2010
2011 /**
2012 * Add menu class in YITH Plugins menu.
2013 *
2014 * @param array $menu The menu.
2015 *
2016 * @return array
2017 * @since 3.0.0
2018 */
2019 public static function add_menu_class_in_yith_plugin( $menu ) {
2020 global $submenu;
2021
2022 if ( ! empty( $submenu['yith_plugin_panel'] ) ) {
2023 $item_count = count( $submenu['yith_plugin_panel'] );
2024 $columns = absint( $item_count / 20 ) + 1;
2025 $columns = max( 1, min( $columns, 3 ) );
2026 $columns = apply_filters( 'yith_plugin_fw_yith_plugins_menu_columns', $columns, $item_count );
2027
2028 if ( $columns > 1 ) {
2029 $class = "yith-plugin-fw-menu-$columns-columns";
2030 foreach ( $menu as $order => $top ) {
2031 if ( 'yith_plugin_panel' === $top[2] ) {
2032 $c = $menu[ $order ][4];
2033 $menu[ $order ][4] = add_cssclass( $class, $c );
2034 break;
2035 }
2036 }
2037 }
2038 }
2039
2040 return $menu;
2041 }
2042
2043 /**
2044 * Check if inside the admin tab there's the premium tab to
2045 * check if the plugin is a free or not
2046 * TODO: remove this from panel, and move to a more generic plugin-registration process; use general plugin data wherever is needed
2047 */
2048 public function is_free() {
2049 $has_fw_premium_tab = ! empty( $this->settings['premium_tab'] );
2050 $has_old_premium_tab = ! ! ( $this->settings['admin-tabs']['premium'] ?? false );
2051
2052 return ( $has_fw_premium_tab || $has_old_premium_tab ) && ! $this->is_extended() && ! $this->is_premium();
2053 }
2054
2055 /**
2056 * Checks whether current panel is for extended version of the plugin
2057 * TODO: remove this from panel, and move to a more generic plugin-registration process; use general plugin data wherever is needed
2058 *
2059 * @return bool
2060 */
2061 public function is_extended() {
2062 return ! empty( $this->settings['is_extended'] );
2063 }
2064
2065 /**
2066 * Checks whether current panel is for premium version of the plugin
2067 * TODO: remove this from panel, and move to a more generic plugin-registration process; use general plugin data wherever is needed
2068 *
2069 * @return bool
2070 */
2071 public function is_premium() {
2072 return ! empty( $this->settings['is_premium'] );
2073 }
2074
2075 /**
2076 * Render the panel header.
2077 *
2078 * @return void
2079 * @since 4.0.0
2080 */
2081 public function render_panel_header() {
2082 $plugin_slug = $this->get_plugin_slug();
2083 $this->render_mobile_header();
2084
2085 do_action( 'yith_plugin_fw_panel_before_panel_header', $this );
2086
2087 $this->get_template(
2088 'panel-header.php',
2089 array(
2090 'title' => $this->settings['page_title'],
2091 'is_free' => $this->is_free(),
2092 'rate_url' => ! ! $plugin_slug ? apply_filters( 'yith_plugin_fw_rate_url', 'https://wordpress.org/support/plugin/' . $plugin_slug . '/reviews/#new-post' ) : '',
2093 )
2094 );
2095 }
2096
2097 /**
2098 * Add plugin banner.
2099 *
2100 * @param string $page The page.
2101 *
2102 * @deprecated 4.0.0
2103 */
2104 public function add_plugin_banner( $page ) {
2105 if ( $this->get_ui_version() < 1 ) {
2106 return;
2107 }
2108
2109 if ( $page !== $this->settings['page'] || ! isset( $this->settings['class'] ) ) {
2110 return;
2111 }
2112
2113 $this->render_panel_header();
2114 }
2115
2116 /**
2117 * Add additional element after print the field.
2118 *
2119 * @param array $field The field.
2120 *
2121 * @since 3.2
2122 */
2123 public function add_yith_ui( $field ) {
2124 global $pagenow;
2125
2126 $screen = function_exists( 'get_current_screen' ) ? get_current_screen() : false;
2127
2128 if ( empty( $this->settings['class'] ) || ! isset( $field['type'] ) ) {
2129 return;
2130 }
2131 if ( 'admin.php' === $pagenow && $screen && strpos( $screen->id, $this->settings['page'] ) !== false ) {
2132 switch ( $field['type'] ) {
2133 case 'datepicker':
2134 echo '<span class="yith-icon yith-icon-calendar yith-icon--right-overlay"></span>';
2135 break;
2136 default:
2137 break;
2138 }
2139 }
2140 }
2141
2142 /**
2143 * Get post type tabs.
2144 *
2145 * @param string $post_type The post type.
2146 *
2147 * @return array
2148 */
2149 public function get_post_type_tabs( $post_type ) {
2150 $tabs = array();
2151
2152 foreach ( $this->get_tabs_hierarchy() as $key => $info ) {
2153 if ( isset( $info['type'], $info['post_type'] ) && 'post_type' === $info['type'] && $post_type === $info['post_type'] ) {
2154 if ( ! empty( $info['parent'] ) ) {
2155 $tabs = array(
2156 'tab' => $info['parent'],
2157 'sub_tab' => $key,
2158 'options' => $info,
2159 );
2160 } else {
2161 $tabs = array(
2162 'tab' => $key,
2163 'options' => $info,
2164 );
2165 }
2166 break;
2167 }
2168 }
2169
2170 $panel_page = isset( $this->settings['page'] ) ? $this->settings['page'] : 'general';
2171
2172 return apply_filters( "yith_plugin_fw_panel_{$panel_page}_get_post_type_tabs", $tabs, $post_type );
2173 }
2174
2175 /**
2176 * Get the taxonomy tabs.
2177 *
2178 * @param string $taxonomy The taxonomy.
2179 *
2180 * @return array
2181 */
2182 public function get_taxonomy_tabs( $taxonomy ) {
2183 $tabs = array();
2184
2185 foreach ( $this->get_tabs_hierarchy() as $key => $info ) {
2186 if ( isset( $info['type'], $info['taxonomy'] ) && 'taxonomy' === $info['type'] && $taxonomy === $info['taxonomy'] ) {
2187 if ( ! empty( $info['parent'] ) ) {
2188 $tabs = array(
2189 'tab' => $info['parent'],
2190 'sub_tab' => $key,
2191 'options' => $info,
2192 );
2193 } else {
2194 $tabs = array(
2195 'tab' => $key,
2196 'options' => $info,
2197 );
2198 }
2199 break;
2200 }
2201 }
2202
2203 $panel_page = isset( $this->settings['page'] ) ? $this->settings['page'] : 'general';
2204
2205 return apply_filters( "yith_plugin_fw_panel_{$panel_page}_get_taxonomy_tabs", $tabs, $taxonomy );
2206 }
2207
2208
2209 /**
2210 * If the panel page is a WP Page, this will redirect you to the correct page
2211 * useful when a Post Type (Taxonomy) is the first tab of your panel, so when you open your panel it'll open the Post Type (Taxonomy) list
2212 *
2213 * @since 3.4.0
2214 */
2215 public function maybe_redirect_to_proper_wp_page() {
2216 // phpcs:disable WordPress.Security.NonceVerification.Recommended
2217 global $pagenow;
2218 if (
2219 'admin.php' === $pagenow && isset( $_GET['page'] ) && $this->settings['page'] === $_GET['page']
2220 &&
2221 ! $this->is_custom_taxonomy_page() && ! $this->is_custom_post_type_page()
2222 &&
2223 ! isset( $_REQUEST['yith-plugin-fw-panel-skip-redirect'] )
2224 ) {
2225 $url = $this->get_nav_url( $this->settings['page'], $this->get_current_tab(), $this->get_current_sub_tab() );
2226 if ( strpos( $url, 'edit.php' ) !== false || strpos( $url, 'edit-tags.php' ) !== false ) {
2227 wp_safe_redirect( add_query_arg( array( 'yith-plugin-fw-panel-skip-redirect' => 1 ), $url ) );
2228 exit;
2229 }
2230 }
2231 // phpcs:enable
2232 }
2233
2234 /**
2235 * Print the Panel tabs and sub-tabs navigation in WP pages
2236 * Important: this opens a wrapper <div> that will be closed through YIT_Plugin_Panel::print_panel_tabs_in_post_edit_page_end()
2237 *
2238 * @since 3.4.0
2239 */
2240 public function print_panel_tabs_in_wp_pages() {
2241 if ( self::$panel_tabs_in_wp_pages && 'all_admin_notices' === current_action() ) {
2242 global $pagenow;
2243
2244 wp_enqueue_script( 'yit-plugin-panel' );
2245
2246 $wrap_class = $this->settings['class'] ?? '';
2247 $options = self::$panel_tabs_in_wp_pages['options'] ?? array();
2248
2249 $options_to_classes = array( 'type', 'post_type', 'taxonomy' );
2250 $page_wrapper_classes = array(
2251 'yith-plugin-fw-wp-page-wrapper',
2252 $options['wrapper-class'] ?? '',
2253 );
2254
2255 if ( in_array( $pagenow, array( 'edit.php', 'edit-tags.php' ), true ) ) {
2256 $options_to_classes[] = 'wp-list-style';
2257 $options_to_classes[] = 'wp-list-auto-h-scroll';
2258 $page_wrapper_classes[] = 'yith-plugin-ui';
2259 }
2260
2261 foreach ( $options_to_classes as $key ) {
2262 if ( isset( $options[ $key ] ) ) {
2263 $option = $options[ $key ];
2264 $page_wrapper_classes[] = true === $option ? "yith-plugin-ui--{$key}" : "yith-plugin-ui--{$option}-{$key}";
2265 }
2266 }
2267 $page_wrapper_classes = implode( ' ', array_filter( $page_wrapper_classes ) );
2268
2269 $this->render_panel_header();
2270
2271 $this->get_template(
2272 'panel-wp-page-header.php',
2273 array(
2274 'panel' => $this,
2275 'page_wrapper_classes' => $page_wrapper_classes,
2276 'wrap_class' => $wrap_class,
2277 'tabs_nav_args' => self::$panel_tabs_in_wp_pages,
2278 'has_sub_tabs' => self::$panel_tabs_in_wp_pages['current_sub_tab'],
2279 )
2280 );
2281 }
2282 }
2283
2284 /**
2285 * Close the wrapper opened in YIT_Plugin_Panel::print_panel_tabs_in_wp_pages()
2286 *
2287 * @since 3.4.0
2288 */
2289 public function print_panel_tabs_in_wp_pages_end() {
2290 if ( self::$panel_tabs_in_wp_pages ) {
2291 $this->get_template(
2292 'panel-wp-page-footer.php',
2293 array(
2294 'panel' => $this,
2295 'has_sub_tabs' => self::$panel_tabs_in_wp_pages['current_sub_tab'],
2296 'page_args' => self::$panel_tabs_in_wp_pages['options'] ?? array(),
2297 )
2298 );
2299 }
2300 }
2301
2302 /**
2303 * Set the parent page to handle menu for WP Pages.
2304 *
2305 * @param string $parent_file The parent file.
2306 *
2307 * @return string
2308 */
2309 public function set_parent_file_to_handle_menu_for_wp_pages( $parent_file ) {
2310 if ( self::$panel_tabs_in_wp_pages ) {
2311 return 'yith_plugin_panel';
2312 }
2313
2314 return $parent_file;
2315 }
2316
2317 /**
2318 * Set the submenu page to handle menu for WP Pages.
2319 *
2320 * @param string $submenu_file The submenu file.
2321 * @param string $parent_file The parent file.
2322 *
2323 * @return mixed
2324 */
2325 public function set_submenu_file_to_handle_menu_for_wp_pages( $submenu_file, $parent_file ) {
2326 if ( self::$panel_tabs_in_wp_pages ) {
2327 return $this->settings['page'];
2328 }
2329
2330 return $submenu_file;
2331 }
2332
2333 /**
2334 * Save the toggle element options.
2335 *
2336 * @return bool
2337 */
2338 public function save_toggle_element_options() {
2339 return true;
2340 }
2341
2342 /**
2343 * Add UTM data in premium tab
2344 *
2345 * @param string $url The url that want to track.
2346 * @param string $slug Plugin slug.
2347 *
2348 * @since 3.8.4
2349 */
2350 public function add_utm_data_on_premium_tab( $url, $slug ) {
2351 $plugin_slug = $this->get_plugin_slug();
2352
2353 return ! ! $plugin_slug && $slug === $plugin_slug && 'premium' === $this->get_current_tab() ? $this->add_utm_data( $url, 'premium-tab-button-upgrade' ) : $url;
2354 }
2355
2356 /**
2357 * Get the data of the current page.
2358 *
2359 * @return array
2360 * @since 4.0.0
2361 */
2362 protected function get_page_data() {
2363 $tab = $this->get_current_tab();
2364 $sub_tab = $this->get_current_sub_tab();
2365
2366 $hierarchy = $this->get_tabs_hierarchy();
2367
2368 return $hierarchy[ $sub_tab ] ?? $hierarchy[ $tab ] ?? array();
2369 }
2370
2371 /**
2372 * Get the title of the current page.
2373 *
2374 * @return string
2375 * @since 4.0.0
2376 */
2377 public function get_page_title() {
2378 $data = $this->get_page_data();
2379
2380 return $data['title'] ?? '';
2381 }
2382
2383 /**
2384 * Get the title of the current page.
2385 *
2386 * @return string
2387 * @since 4.0.0
2388 */
2389 public function get_page_description() {
2390 $data = $this->get_page_data();
2391
2392 return $data['description'] ?? '';
2393 }
2394
2395 /**
2396 * Get options from path.
2397 * Useful to prevent issues with defined variables where including the file.
2398 *
2399 * @param string $path The options' file path.
2400 *
2401 * @return mixed
2402 * @since 4.0.0
2403 */
2404 public function get_options_from_path( $path ) {
2405 return include $path;
2406 }
2407
2408 /**
2409 * Get the plugin name.
2410 *
2411 * @return string
2412 */
2413 protected function get_plugin_name() {
2414 return $this->settings['plugin_name'] ?? $this->settings['page_title'] ?? '';
2415 }
2416
2417 /**
2418 * Get the plugin slug.
2419 *
2420 * @return string
2421 */
2422 public function get_plugin_slug() {
2423 return $this->settings['plugin_slug'] ?? '';
2424 }
2425
2426 /**
2427 * Get the title shown in the header of the panel.
2428 *
2429 * @return string
2430 */
2431 protected function get_header_title() {
2432 $stop_words = array( 'YITH', 'for WordPress & WooCommerce', 'for WordPress and WooCommerce', 'for WordPress', 'for WooCommerce', 'WooCommerce' );
2433
2434 return $this->settings['menu_title'] ?? trim( str_replace( $stop_words, '', $this->get_plugin_name() ) );
2435 }
2436
2437 /**
2438 * Print the YITH logo and the plugin name.
2439 *
2440 * @since 4.0.0
2441 */
2442 public function print_sidebar_header() {
2443 if ( $this->get_ui_version() > 1 ) {
2444 $this->get_template(
2445 'panel-sidebar-header.php',
2446 array(
2447 'header_title' => $this->get_header_title(),
2448 )
2449 );
2450 }
2451 }
2452
2453 /**
2454 * Get a template based on the ui_version.
2455 *
2456 * @param string $template The template.
2457 * @param array $args Arguments.
2458 *
2459 * @since 4.0.0
2460 */
2461 public function get_template( $template, $args = array() ) {
2462 $_template_args = array(
2463 'template' => $template,
2464 'base_path' => YIT_CORE_PLUGIN_TEMPLATE_PATH . '/panel/',
2465 'ui_version' => $this->get_ui_version(),
2466 'template_path' => '',
2467 );
2468 if ( isset( $args['_template_args'] ) ) {
2469 unset( $args['_template_args'] );
2470 }
2471
2472 if ( $_template_args['ui_version'] > 1 ) {
2473 $versioned_base_path = $_template_args['base_path'] . 'v' . $_template_args['ui_version'] . '/';
2474 $versioned_path = $versioned_base_path . $_template_args['template'];
2475 if ( file_exists( $versioned_path ) ) {
2476 $_template_args['template_path'] = $versioned_path;
2477 }
2478 }
2479
2480 if ( ! $_template_args['template_path'] ) {
2481 $_template_args['template_path'] = $_template_args['base_path'] . $_template_args['template'];
2482 }
2483
2484 if ( file_exists( $_template_args['template_path'] ) ) {
2485 extract( $args ); // phpcs:ignore WordPress.PHP.DontExtract.extract_extract
2486 include $_template_args['template_path'];
2487 }
2488 }
2489
2490 /**
2491 * Return true if the current page is rendered by this panel.
2492 *
2493 * @param bool $include_wp_pages Set true to consider WP Pages as part of the current panel.
2494 *
2495 * @return bool
2496 * @since 4.0.0
2497 */
2498 protected function is_current_panel( $include_wp_pages = true ) {
2499 global $plugin_page;
2500
2501 $is_panel = $plugin_page === $this->settings['page'];
2502 if ( ! $is_panel && $include_wp_pages ) {
2503 $is_panel = ! ! $this->get_current_tab();
2504 }
2505
2506 return $is_panel;
2507 }
2508
2509 /**
2510 * Return the UTM source.
2511 *
2512 * @return string
2513 * @since 4.1.0
2514 */
2515 protected function get_plugin_version_type() {
2516 if ( $this->is_free() ) {
2517 return 'free';
2518 }
2519
2520 if ( $this->is_extended() ) {
2521 return 'extended';
2522 }
2523
2524 if ( $this->is_premium() ) {
2525 return 'premium';
2526 }
2527
2528 return '';
2529 }
2530
2531 /**
2532 * Add UTM data to an URL.
2533 *
2534 * @param string $url The url.
2535 * @param string $campaign The campaign.
2536 * @param string $content The content.
2537 * @param string $term The term.
2538 *
2539 * @return string
2540 * @since 4.1.0
2541 * @since 4.5.8 Added $content and $term prams.
2542 */
2543 public function add_utm_data( $url, $campaign, $content = '', $term = '' ) {
2544 $plugin_slug = $this->get_plugin_slug();
2545 if ( $plugin_slug ) {
2546 $url = yith_plugin_fw_add_utm_data( $url, $plugin_slug, $campaign, $this->get_plugin_version_type(), $content, $term );
2547 }
2548
2549 return $url;
2550 }
2551
2552 /**
2553 * Apply filters by creating a hook by using the panel page.
2554 *
2555 * @param string $partial_hook_name The partial hook name.
2556 * @param mixed $value The value to filter.
2557 * @param array ...$args The arguments.
2558 *
2559 * @return mixed
2560 */
2561 public function apply_filters( $partial_hook_name, $value, ...$args ) {
2562 $panel_page = $this->settings['page'] ?? '';
2563 if ( $panel_page ) {
2564 $hook_name = "yith_plugin_fw_panel_{$panel_page}_{$partial_hook_name}";
2565
2566 array_unshift( $args, $value );
2567
2568 $value = apply_filters_ref_array( $hook_name, $args );
2569 }
2570
2571 return $value;
2572
2573 }
2574 }
2575 }
2576