' . esc_html__( 'Settings', 'cartpin' ) . '' ); if ( ! Plugin::pro_installed() ) { $own[] = '' . esc_html__( 'Get Pro', 'cartpin' ) . ''; } return array_merge( $own, $links ); } /** * Settings page URL. * * @param string $tab Tab ID. * @return string */ public static function url( $tab = '' ) { $url = admin_url( 'admin.php?page=' . self::SLUG ); return $tab ? $url . '#' . $tab : $url; } /** * Whether the current screen is ours. * * @return bool */ public static function is_our_screen() { $screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null; return $screen && ( false !== strpos( $screen->id, self::SLUG ) ); } /** * Loads admin files on our screen only. */ public static function assets() { if ( ! self::is_our_screen() ) { return; } wp_enqueue_style( 'wp-color-picker' ); add_thickbox(); // "More details" on the More plugins tab opens WordPress's own plugin window. wp_enqueue_style( 'satcbar-admin', SATCBAR_URL . 'assets/css/admin.css', array(), SATCBAR_VERSION ); wp_enqueue_script( 'satcbar-admin', SATCBAR_URL . 'assets/js/admin.js', array( 'jquery', 'wp-color-picker' ), SATCBAR_VERSION, array( 'in_footer' => true ) ); wp_add_inline_script( 'satcbar-admin', 'window.satcbarAdmin = ' . wp_json_encode( array( 'unsaved' => __( 'You have unsaved changes.', 'cartpin' ), 'preview' => self::preview_data(), /** * Filters the tabs that show the live preview beside them. * * @param string[] $tabs Tab IDs. */ 'previewTabs' => array_values( (array) apply_filters( 'satcbar_preview_tabs', array( 'bar', 'style' ) ) ), ) ) . ';', 'before' ); } /** * Tabs on the settings page. * * @return array ID => label. */ public static function tabs() { $tabs = array( 'bar' => __( 'Bar', 'cartpin' ), 'style' => __( 'Style', 'cartpin' ), 'help' => __( 'Help', 'cartpin' ), ); if ( ! Plugin::pro_installed() ) { $tabs['pro'] = __( 'Pro', 'cartpin' ); } /** * Filters the settings tabs. Add-ons add their own. * * @param array $tabs ID => label. */ $tabs = apply_filters( 'satcbar_admin_tabs', $tabs ); // Always last: our other free plugins. $tabs['more'] = __( 'More plugins', 'cartpin' ); return $tabs; } /** * Saves the settings form. */ public static function save() { if ( ! current_user_can( self::capability() ) ) { wp_die( esc_html__( 'Sorry, you are not allowed to change these settings.', 'cartpin' ), 403 ); } check_admin_referer( 'satcbar_save' ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Cleaned in Settings::sanitize(). $input = isset( $_POST['satcbar'] ) && is_array( $_POST['satcbar'] ) ? wp_unslash( $_POST['satcbar'] ) : array(); Settings::save( $input ); /** * Runs after settings are saved. Add-ons save their own fields here. */ do_action( 'satcbar_settings_saved' ); $tab = isset( $_POST['satcbar_tab'] ) ? sanitize_key( wp_unslash( $_POST['satcbar_tab'] ) ) : ''; wp_safe_redirect( add_query_arg( 'updated', '1', admin_url( 'admin.php?page=' . self::SLUG ) ) . ( $tab ? '#' . $tab : '' ) ); exit; } /** * A product to preview the bar with. * * @return \WC_Product|null */ private static function preview_product() { static $found = false; if ( false !== $found ) { return $found; } $found = null; $ids = wc_get_products( array( 'status' => 'publish', 'limit' => 10, 'type' => array( 'simple', 'variable' ), 'stock_status' => 'instock', 'return' => 'ids', ) ); foreach ( $ids as $id ) { $product = wc_get_product( $id ); if ( ! $product || ! Frontend::can_show_for( $product ) ) { continue; } if ( $product->get_image_id() ) { $found = $product; break; } if ( ! $found ) { $found = $product; } } return $found; } /** * Data for the live preview. * * @return array */ private static function preview_data() { $product = self::preview_product(); $image = $product && $product->get_image_id() ? wp_get_attachment_image_url( $product->get_image_id(), 'woocommerce_single' ) : ''; $thumb = $product && $product->get_image_id() ? wp_get_attachment_image_url( $product->get_image_id(), 'woocommerce_gallery_thumbnail' ) : ''; return array( 'css' => SATCBAR_URL . 'assets/css/bar.css?ver=' . SATCBAR_VERSION, 'name' => $product ? wp_strip_all_tags( $product->get_name() ) : __( 'Your product', 'cartpin' ), 'price' => $product ? wp_kses_post( $product->get_price_html() ) : wp_kses_post( wc_price( 25 ) ), 'image' => $image ? $image : wc_placeholder_img_src( 'woocommerce_single' ), 'thumb' => $thumb ? $thumb : wc_placeholder_img_src( 'woocommerce_gallery_thumbnail' ), 'addToCart' => $product ? wp_strip_all_tags( $product->single_add_to_cart_text() ) : __( 'Add to cart', 'cartpin' ), 'i18n' => array( 'quantity' => __( 'Quantity', 'cartpin' ), 'shop' => get_bloginfo( 'name' ), 'offAll' => __( 'The bar is switched off.', 'cartpin' ), 'offPhone' => __( 'The bar is off on phones.', 'cartpin' ), 'offComputer' => __( 'The bar is off on computers.', 'cartpin' ), ), ); } /** * Renders the settings page. */ public static function render() { if ( ! current_user_can( self::capability() ) ) { return; } $s = Settings::get(); $tabs = self::tabs(); $product = self::preview_product(); ?>

' . esc_html__( 'Pro', 'cartpin' ) . ''; } ?>

$label ) : ?>
array( __( 'Bottom of the screen', 'cartpin' ), __( 'Recommended. Easy to reach with a thumb.', 'cartpin' ) ), 'top' => array( __( 'Top of the screen', 'cartpin' ), __( 'Like a header that follows the shopper.', 'cartpin' ) ), ) ); self::choices( 'trigger', __( 'Show the bar', 'cartpin' ), $s['trigger'], array( 'scroll' => array( __( 'After scrolling past the button', 'cartpin' ), __( 'Recommended. Appears once the real Add to cart button is above the screen.', 'cartpin' ) ), 'always' => array( __( 'Whenever the button is out of sight', 'cartpin' ), __( 'Also before shoppers reach the real button.', 'cartpin' ) ), ) ); self::card_end(); self::card_start( __( 'What the bar shows', 'cartpin' ) ); self::toggle( 'show_image', __( 'Product picture', 'cartpin' ), $s['show_image'] ); self::toggle( 'show_price', __( 'Price', 'cartpin' ), $s['show_price'], __( 'Changes to the chosen option\'s price on variable products.', 'cartpin' ) ); self::toggle( 'show_qty', __( 'Quantity box', 'cartpin' ), $s['show_qty'], __( 'On computers. Phones show only the button to keep the bar small.', 'cartpin' ) ); self::text( 'button_text', __( 'Button text', 'cartpin' ), $s['button_text'], __( 'Add to cart', 'cartpin' ), __( 'Leave empty to use the same text as your product page button.', 'cartpin' ) ); self::card_end(); } /** * Style tab. * * @param array $s Settings. */ private static function tab_style( array $s ) { self::card_start( __( 'Look', 'cartpin' ) ); self::choices( 'style', __( 'Bar', 'cartpin' ), $s['style'], array( 'light' => array( __( 'Light', 'cartpin' ), __( 'White bar with dark text.', 'cartpin' ) ), 'dark' => array( __( 'Dark', 'cartpin' ), __( 'Dark bar with light text.', 'cartpin' ) ), ) ); self::row_start( 'button_color', __( 'Button color', 'cartpin' ) ); echo ''; self::row_end( __( 'Leave empty to use your theme\'s button style. The text color is picked for you so it is easy to read.', 'cartpin' ) ); self::card_end(); } /** * Help tab. * * @param array $s Settings. */ private static function tab_help( array $s ) { self::card_start( __( 'How it works', 'cartpin' ) ); ?>
' . esc_html__( 'Works with classic themes and block themes that use the normal WooCommerce product form. On Storefront, the theme\'s own sticky bar is switched off while this bar is on.', 'cartpin' ) . '

'; echo '

' . esc_html__( 'Does your theme have its own sticky add to cart? Turn it off in the theme settings so shoppers see only one bar.', 'cartpin' ) . '

'; echo '

' . esc_html__( 'To hide the bar on one product: edit the product, open Product data → Advanced, and tick "Hide the sticky bar on this product".', 'cartpin' ) . '

'; self::card_end(); self::card_start( __( 'Need help?', 'cartpin' ) ); echo '

'; printf( /* translators: %s: support email link. */ esc_html__( 'Email us at %s and we will reply as soon as we can.', 'cartpin' ), 'pluginnest1@gmail.com' ); echo '

' . esc_html__( 'Like the plugin? Please leave a review.', 'cartpin' ) . '

'; self::card_end(); self::card_start( __( 'When deleting the plugin', 'cartpin' ) ); self::toggle( 'delete_data', __( 'Remove settings', 'cartpin' ), $s['delete_data'], __( 'Delete this plugin\'s settings when the plugin is deleted.', 'cartpin' ) ); self::card_end(); } /** * More plugins tab. * * @param array $s Settings. */ private static function tab_more( array $s ) { unset( $s ); More_Plugins::render(); } /** * Pro tab (shown while Pro is not installed). * * @param array $s Settings. */ private static function tab_pro( array $s ) { unset( $s ); $features = array( array( __( 'Add without page reload', 'cartpin' ), __( 'The product goes into the cart in a moment. The bar shows "Added" and a View cart link, and your header cart updates.', 'cartpin' ) ), array( __( 'Buy now button', 'cartpin' ), __( 'A second button that adds the product and goes straight to checkout.', 'cartpin' ) ), array( __( 'Choose options in the bar', 'cartpin' ), __( 'Size, color and other options right inside the bar.', 'cartpin' ) ), array( __( 'Rating, sale badge, stock', 'cartpin' ), __( 'Star rating, "Save 20%" badge and "Only 3 left" when stock is low.', 'cartpin' ) ), array( __( 'Full design', 'cartpin' ), __( 'Every color, corners, shadow, size and animation. Hide the bar while shoppers scroll down.', 'cartpin' ) ), array( __( 'Choose where it shows', 'cartpin' ), __( 'Only in some categories, or never in some categories.', 'cartpin' ) ), array( __( 'Sales report', 'cartpin' ), __( 'Taps, products added and sales that came from the bar.', 'cartpin' ) ), ); ?>

value. * @return string */ public static function attrs( array $attrs ) { $html = ''; foreach ( $attrs as $name => $value ) { $html .= ' ' . esc_attr( $name ) . '="' . esc_attr( (string) $value ) . '"'; } return $html; } /** * Name attribute for a setting. * * @param string $key Setting key. * @param string $group Form group (add-ons use their own). * @return string */ public static function name( $key, $group = 'satcbar' ) { return $group . '[' . $key . ']'; } /** * Opens a card. * * @param string $title Title. * @param string $text Optional intro. * @param array $attrs Extra attributes. */ public static function card_start( $title, $text = '', array $attrs = array() ) { echo '
'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- attrs() escapes. echo '

' . esc_html( $title ) . '

'; if ( $text ) { echo '

' . esc_html( $text ) . '

'; } } /** * Closes a card. */ public static function card_end() { echo '
'; } /** * Row wrapper start. * * @param string $key Setting key. * @param string $label Label. * @param array $attrs Row attributes. * @param bool $label_for Whether the label points at an input with the key's ID. */ public static function row_start( $key, $label, array $attrs = array(), $label_for = true ) { echo '
'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- attrs() escapes. if ( $label_for ) { echo ''; } else { echo '
' . esc_html( $label ) . '
'; } echo '
'; } /** * Row wrapper end with an optional description. * * @param string $desc Description. */ public static function row_end( $desc = '' ) { if ( $desc ) { echo '

' . esc_html( $desc ) . '

'; } echo '
'; } /** * On/off switch. * * @param string $key Setting key. * @param string $label Label. * @param bool $value Value. * @param string $desc Description. * @param array $attrs Row attributes. * @param string $group Form group. */ public static function toggle( $key, $label, $value, $desc = '', array $attrs = array(), $group = 'satcbar' ) { self::row_start( $key, $label, $attrs ); echo ''; echo ''; self::row_end( $desc ); } /** * Text input. * * @param string $key Setting key. * @param string $label Label. * @param string $value Value. * @param string $placeholder Placeholder (usually the default text). * @param string $desc Description. * @param array $attrs Row attributes. * @param string $group Form group. */ public static function text( $key, $label, $value, $placeholder = '', $desc = '', array $attrs = array(), $group = 'satcbar' ) { self::row_start( $key, $label, $attrs ); echo ''; self::row_end( $desc ); } /** * Number input. * * @param string $key Setting key. * @param string $label Label. * @param int $value Value. * @param int $min Minimum. * @param int $max Maximum. * @param string $desc Description. * @param array $attrs Row attributes. * @param string $group Form group. */ public static function number( $key, $label, $value, $min, $max, $desc = '', array $attrs = array(), $group = 'satcbar' ) { self::row_start( $key, $label, $attrs ); echo ''; self::row_end( $desc ); } /** * Dropdown. * * @param string $key Setting key. * @param string $label Label. * @param string $value Value. * @param array $options Value => label. * @param string $desc Description. * @param array $attrs Row attributes. * @param string $group Form group. */ public static function select( $key, $label, $value, array $options, $desc = '', array $attrs = array(), $group = 'satcbar' ) { self::row_start( $key, $label, $attrs ); echo ''; self::row_end( $desc ); } /** * Choice cards (radio buttons). * * @param string $key Setting key. * @param string $label Label. * @param string $value Value. * @param array $options Value => array( title, description ). * @param array $attrs Row attributes. * @param string $group Form group. */ public static function choices( $key, $label, $value, array $options, array $attrs = array(), $group = 'satcbar' ) { self::row_start( $key, $label, $attrs, false ); echo '
'; foreach ( $options as $option => $texts ) { $id = 'satcbar-' . $key . '-' . $option; echo ''; } echo '
'; self::row_end(); } }