set_cache_key(); if ( false === self::$sales ) { $this->set_sales(); } } /** * @since 6.17 * * @return void */ protected function set_cache_key() { $this->cache_key = 'frm_sales_cache'; } /** * @since 6.17 * * @return string */ protected function api_url() { return 'https://plapi.formidableforms.com/sales/'; } /** * @since 6.17 * * @return void */ private function set_sales() { self::$sales = array(); $api = $this->get_api_info(); if ( empty( $api ) ) { return; } foreach ( $api as $sale ) { $this->add_sale( $sale ); } } /** * @param array|string $sale * * @return void */ private function add_sale( $sale ) { if ( ! is_array( self::$sales ) ) { // This gets set in the constructor. // This check is just here for Psalm analysis. return; } if ( ! is_array( $sale ) || ! isset( $sale['key'] ) ) { // if the API response is invalid, $sale may not be an array. // if there are no sales from the API, it is returning a "No Entries Found" item with no key, so check for a key as well. return; } if ( ! $this->sale_is_active( $sale ) ) { return; } self::$sales[ $sale['key'] ] = $this->fill_sale( $sale ); } /** * @param array $sale * @return array */ private function fill_sale( $sale ) { $defaults = array( 'key' => '', 'starts' => '', 'expires' => '', // Use 'free', 'personal', 'business', 'elite', 'grandfathered'. 'who' => 'all', 'discount_percent' => 0, 'test_group' => '', 'lite_banner_cta_link' => '', 'lite_banner_cta_text' => '', 'menu_cta_link' => '', 'menu_cta_text' => '', 'dashboard_license_cta_link' => '', 'dashboard_license_cta_text' => '', 'global_settings_license_cta_link' => '', 'global_settings_license_cta_text' => '', 'global_settings_unlock_more_cta_link' => '', 'global_settings_unlock_more_cta_text' => '', 'global_settings_upgrade_cta_link' => '', 'builder_sidebar_cta_link' => '', 'builder_sidebar_cta_text' => '', 'banner_title' => '', 'banner_body' => '', 'banner_icon' => '', 'banner_text_color' => '', 'banner_bg_color' => '', 'banner_cta_link' => '', 'banner_cta_text' => '', 'banner_cta_text_color' => '', 'banner_cta_bg_color' => '', ); return array_merge( $defaults, $sale ); } /** * Check if a sale is within the active period. * * @since 6.17 * * @param array $sale * @return bool */ private function sale_is_active( $sale ) { $starts = $sale['starts']; $expires = $sale['expires'] + DAY_IN_SECONDS; $date = new DateTime( 'now', new DateTimeZone( 'America/New_York' ) ); $today = $date->getTimestamp(); return $today >= $starts && $today <= $expires; } /** * @since 6.17 * * @return array|false */ public function get_best_sale() { if ( ! self::$sales ) { return false; } if ( isset( self::$best_sale ) ) { return self::$best_sale; } $best_sale = false; foreach ( self::$sales as $sale ) { if ( ! FrmApiHelper::is_for_user( $sale ) ) { continue; } if ( ! $this->matches_ab_group( $sale ) ) { continue; } if ( ! $best_sale || $sale['discount_percent'] > $best_sale['discount_percent'] ) { $best_sale = $sale; } } self::$best_sale = $best_sale; return self::$best_sale; } /** * Get text for best sale if applicable. * * @since 6.17 * * @param string $key * @return false|string False if no sale is active. */ public static function get_best_sale_value( $key ) { if ( ! isset( self::$instance ) ) { self::$instance = new FrmSalesApi(); } $sale = self::$instance->get_best_sale(); return is_array( $sale ) && ! empty( $sale[ $key ] ) ? $sale[ $key ] : false; } /** * @since 6.17 * * @param array $sale * @return bool True if the sale is a match for the applicable group (if one is defined). */ private function matches_ab_group( $sale ) { if ( ! is_numeric( $sale['test_group'] ) ) { // No test group, so return true. return true; } $ab_group = $this->get_ab_group_for_current_site(); return $ab_group === $sale['test_group']; } /** * @since 6.17 * * @return int 1 or 0. */ private function get_ab_group_for_current_site() { $option = get_option( 'frm_sale_ab_group' ); if ( ! is_numeric( $option ) ) { // Generate either 0 or 1. $option = mt_rand( 0, 1 ); update_option( 'frm_sale_ab_group', $option, false ); } return (int) $option; } /** * Maybe show banner for the best sale. * * @since 6.21 * * @return bool */ public static function maybe_show_banner() { if ( ! current_user_can( 'frm_change_settings' ) ) { return false; } if ( ! isset( self::$instance ) ) { self::$instance = new FrmSalesApi(); } $sale = self::$instance->get_best_sale(); if ( ! $sale || ! is_array( $sale ) ) { return false; } $banner_title = ! empty( $sale['banner_title'] ) ? $sale['banner_title'] : false; $banner_body = ! empty( $sale['banner_body'] ) ? $sale['banner_body'] : false; if ( false === $banner_title || false === $banner_body ) { return false; } if ( self::is_banner_dismissed( $sale['key'] ) ) { return false; } $banner_icon = ! empty( $sale['banner_icon'] ) ? $sale['banner_icon'] : 'generic'; $banner_bg_color = ! empty( $sale['banner_bg_color'] ) ? $sale['banner_bg_color'] : false; $banner_text_color = ! empty( $sale['banner_text_color'] ) ? $sale['banner_text_color'] : false; $banner_cta_link = ! empty( $sale['banner_cta_link'] ) ? $sale['banner_cta_link'] : false; // translators: %s is the discount percentage. $banner_cta_text = ! empty( $sale['banner_cta_text'] ) ? $sale['banner_cta_text'] : sprintf( __( 'GET %s OFF NOW', 'formidable' ), $sale['discount_percent'] . '%' ); $banner_cta_text_color = ! empty( $sale['banner_cta_text_color'] ) ? $sale['banner_cta_text_color'] : false; $banner_cta_bg_color = ! empty( $sale['banner_cta_bg_color'] ) ? $sale['banner_cta_bg_color'] : false; if ( false === $banner_cta_link ) { $banner_cta_link = FrmAppHelper::admin_upgrade_link( array( 'medium' => 'sales-api-banner', 'content' => $sale['key'], ) ); } $banner_attrs = array( 'id' => 'frm_sale_banner', 'data-url' => $banner_cta_link, ); if ( false === $banner_bg_color || 'gradient' === $banner_bg_color ) { $banner_attrs['class'] = 'frm-gradient'; } else { $banner_attrs['style'] = 'background-color: ' . esc_attr( $banner_bg_color ) . ';'; } $cta_attrs = array( 'href' => '#', 'style' => '', ); if ( false !== $banner_cta_text_color ) { $cta_attrs['style'] .= 'color: ' . esc_attr( $banner_cta_text_color ) . ';'; } if ( false !== $banner_cta_bg_color ) { $cta_attrs['style'] .= 'background-color: ' . esc_attr( $banner_cta_bg_color ) . ';'; } $dismiss_attrs = array( 'href' => '#', 'class' => 'dismiss', ); $content_attrs = array(); if ( false !== $banner_text_color ) { $content_attrs['style'] = 'color: ' . esc_attr( $banner_text_color ) . ';'; $dismiss_attrs['style'] = 'color: ' . esc_attr( $banner_text_color ) . ';'; } ?>
>
<?php echo esc_attr( $banner_title ); ?>
>
>
>
get_best_sale(); if ( ! $sale || ! is_array( $sale ) ) { wp_send_json_error(); } $dismissed_sales = get_user_option( 'frm_dismissed_sales', get_current_user_id() ); if ( ! is_array( $dismissed_sales ) ) { $dismissed_sales = array(); } $dismissed_sales[] = $sale['key']; update_user_option( get_current_user_id(), 'frm_dismissed_sales', $dismissed_sales ); wp_send_json_success(); } /** * @param string $key * @return bool */ private static function is_banner_dismissed( $key ) { $dismissed_sales = get_user_option( 'frm_dismissed_sales', get_current_user_id() ); return is_array( $dismissed_sales ) && in_array( $key, $dismissed_sales, true ); } }