_fs = $fs; $this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_' . $fs->get_slug() . '_info', WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK ); // Remove default plugin information action. remove_all_actions( 'install_plugins_pre_plugin-information' ); // Override action with custom plugins function for add-ons. add_action( 'install_plugins_pre_plugin-information', array( &$this, 'install_plugin_information' ) ); // Override request for plugin information for Add-ons. add_filter( 'fs_plugins_api', array( &$this, '_get_addon_info_filter' ), WP_FS__DEFAULT_PRIORITY, 3 ); } /** * Generate add-on plugin information. * * @author Vova Feldman (@svovaf) * @since 1.0.6 * * @param array $data * @param string $action * @param object|null $args * * @return array|null */ function _get_addon_info_filter( $data, $action = '', $args = null ) { $this->_logger->entrance(); $parent_plugin_id = fs_request_get( 'parent_plugin_id', $this->_fs->get_id() ); if ( $this->_fs->get_id() != $parent_plugin_id || ( 'plugin_information' !== $action ) || ! isset( $args->slug ) ) { return $data; } // Find add-on by slug. $selected_addon = $this->_fs->get_addon_by_slug( $args->slug, WP_FS__DEV_MODE ); if ( false === $selected_addon ) { return $data; } if ( ! isset( $selected_addon->info ) ) { // Setup some default info. $selected_addon->info = new stdClass(); $selected_addon->info->selling_point_0 = 'Selling Point 1'; $selected_addon->info->selling_point_1 = 'Selling Point 2'; $selected_addon->info->selling_point_2 = 'Selling Point 3'; $selected_addon->info->description = '

Tell your users all about your add-on

'; } fs_enqueue_local_style( 'fs_addons', '/admin/add-ons.css' ); $data = $args; $has_free_plan = false; $has_paid_plan = false; // Load add-on pricing. $has_pricing = false; $has_features = false; $plans = false; $result = $this->_fs->get_api_plugin_scope()->get( $this->_fs->add_show_pending( "/addons/{$selected_addon->id}/pricing.json?type=visible" ) ); if ( ! isset( $result->error ) ) { $plans = $result->plans; if ( is_array( $plans ) ) { for ( $i = 0, $len = count( $plans ); $i < $len; $i ++ ) { $pricing = isset( $plans[ $i ]->pricing ) ? $plans[ $i ]->pricing : null; $features = isset( $plans[ $i ]->features ) ? $plans[ $i ]->features : null; $plans[ $i ] = new FS_Plugin_Plan( $plans[ $i ] ); $plan = $plans[ $i ]; if ( 'free' == $plans[ $i ]->name || ! is_array( $pricing ) || 0 == count( $pricing ) ) { $has_free_plan = true; } if ( is_array( $pricing ) && 0 < count( $pricing ) ) { $filtered_pricing = array(); foreach ( $pricing as $prices ) { $prices = new FS_Pricing( $prices ); if ( ! $prices->is_usd() ) { /** * Skip non-USD pricing. * * @author Leo Fajardo (@leorw) * @since 2.3.1 */ continue; } if ( ( $prices->has_monthly() && $prices->monthly_price > 1.0 ) || ( $prices->has_annual() && $prices->annual_price > 1.0 ) || ( $prices->has_lifetime() && $prices->lifetime_price > 1.0 ) ) { $filtered_pricing[] = $prices; } } if ( ! empty( $filtered_pricing ) ) { $has_paid_plan = true; $plan->pricing = $filtered_pricing; $has_pricing = true; } } if ( is_array( $features ) && 0 < count( $features ) ) { $plan->features = $features; $has_features = true; } } } } $latest = null; if ( ! $has_paid_plan && $selected_addon->is_wp_org_compliant ) { $repo_data = FS_Plugin_Updater::_fetch_plugin_info_from_repository( 'plugin_information', (object) array( 'slug' => $selected_addon->slug, 'is_ssl' => is_ssl(), 'fields' => array( 'banners' => true, 'reviews' => true, 'downloaded' => false, 'active_installs' => true ) ) ); if ( ! empty( $repo_data ) ) { $data = $repo_data; $data->wp_org_missing = false; } else { // Couldn't find plugin on .org. $selected_addon->is_wp_org_compliant = false; // Plugin is missing, not on Freemius nor WP.org. $data->wp_org_missing = true; } $data->fs_missing = ( ! $has_free_plan || $data->wp_org_missing ); } else { $data->has_purchased_license = false; $data->wp_org_missing = false; $fs_addon = null; $current_addon_version = false; if ( $this->_fs->is_addon_activated( $selected_addon->id ) ) { $fs_addon = $this->_fs->get_addon_instance( $selected_addon->id ); $current_addon_version = $fs_addon->get_plugin_version(); } else if ( $this->_fs->is_addon_installed( $selected_addon->id ) ) { $addon_plugin_data = get_plugin_data( ( WP_PLUGIN_DIR . '/' . $this->_fs->get_addon_basename( $selected_addon->id ) ), false, false ); if ( ! empty( $addon_plugin_data ) ) { $current_addon_version = $addon_plugin_data['Version']; } } // Fetch latest version from Freemius. $latest = $this->_fs->_fetch_latest_version( $selected_addon->id, true, WP_FS__TIME_24_HOURS_IN_SEC, $current_addon_version ); if ( $has_paid_plan ) { $blog_id = fs_request_get( 'fs_blog_id' ); $has_valid_blog_id = is_numeric( $blog_id ); if ( $has_valid_blog_id ) { switch_to_blog( $blog_id ); } $data->checkout_link = $this->_fs->checkout_url( WP_FS__PERIOD_ANNUALLY, false, array(), ( $has_valid_blog_id ? false : null ) ); if ( $has_valid_blog_id ) { restore_current_blog(); } } /** * Check if there's a purchased license in case the add-on can only be installed/downloaded as part of a purchased bundle. * * @author Leo Fajardo (@leorw) * @since 2.4.1 */ if ( is_object( $fs_addon ) ) { $data->has_purchased_license = $fs_addon->has_active_valid_license(); } else { $account_addons = $this->_fs->get_account_addons(); if ( ! empty( $account_addons ) && in_array( $selected_addon->id, $account_addons ) ) { $data->has_purchased_license = true; } } if ( $has_free_plan || $data->has_purchased_license ) { $data->download_link = $this->_fs->_get_latest_download_local_url( $selected_addon->id ); } $data->fs_missing = ( false === $latest && ( empty( $selected_addon->premium_releases_count ) || ! ( $selected_addon->premium_releases_count > 0 ) ) ); // Fetch as much as possible info from local files. $plugin_local_data = $this->_fs->get_plugin_data(); $data->author = $plugin_local_data['Author']; if ( ! empty( $selected_addon->info->banner_url ) ) { $data->banners = array( 'low' => $selected_addon->info->banner_url, ); } if ( ! empty( $selected_addon->info->screenshots ) ) { $view_vars = array( 'screenshots' => $selected_addon->info->screenshots, 'plugin' => $selected_addon, ); $data->sections['screenshots'] = fs_get_template( '/plugin-info/screenshots.php', $view_vars ); } if ( is_object( $latest ) ) { $data->version = $latest->version; $data->last_updated = $latest->created; $data->requires = $latest->requires_platform_version; $data->requires_php = $latest->requires_programming_language_version; $data->tested = $latest->tested_up_to_version; } else if ( ! empty( $current_addon_version ) ) { $data->version = $current_addon_version; } else { // Add dummy version. $data->version = '1.0.0'; // Add message to developer to deploy the plugin through Freemius. } } $data->name = $selected_addon->title; $view_vars = array( 'plugin' => $selected_addon ); if ( is_object( $latest ) && isset( $latest->readme ) && is_object( $latest->readme ) ) { $latest_version_readme_data = $latest->readme; if ( isset( $latest_version_readme_data->sections ) ) { $data->sections = (array) $latest_version_readme_data->sections; } else { $data->sections = array(); } } $data->sections['description'] = fs_get_template( '/plugin-info/description.php', $view_vars ); if ( $has_pricing ) { // Add plans to data. $data->plans = $plans; if ( $has_features ) { $view_vars = array( 'plans' => $plans, 'plugin' => $selected_addon, ); $data->sections['features'] = fs_get_template( '/plugin-info/features.php', $view_vars ); } } $data->has_free_plan = $has_free_plan; $data->has_paid_plan = $has_paid_plan; $data->is_paid = $has_paid_plan; $data->is_wp_org_compliant = $selected_addon->is_wp_org_compliant; $data->premium_slug = $selected_addon->premium_slug; $data->addon_id = $selected_addon->id; if ( ! isset( $data->has_purchased_license ) ) { $data->has_purchased_license = false; } return $data; } /** * @author Vova Feldman (@svovaf) * @since 1.1.7 * * @param FS_Plugin_Plan $plan * * @return string */ private function get_billing_cycle( FS_Plugin_Plan $plan ) { $billing_cycle = null; if ( 1 === count( $plan->pricing ) && 1 == $plan->pricing[0]->licenses ) { $pricing = $plan->pricing[0]; if ( isset( $pricing->annual_price ) ) { $billing_cycle = 'annual'; } else if ( isset( $pricing->monthly_price ) ) { $billing_cycle = 'monthly'; } else if ( isset( $pricing->lifetime_price ) ) { $billing_cycle = 'lifetime'; } } else { foreach ( $plan->pricing as $pricing ) { if ( isset( $pricing->annual_price ) ) { $billing_cycle = 'annual'; } else if ( isset( $pricing->monthly_price ) ) { $billing_cycle = 'monthly'; } else if ( isset( $pricing->lifetime_price ) ) { $billing_cycle = 'lifetime'; } if ( ! is_null( $billing_cycle ) ) { break; } } } return $billing_cycle; } /** * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param FS_Plugin_Plan $plan * @param FS_Pricing $pricing * * @return float|null|string */ private function get_price_tag( FS_Plugin_Plan $plan, FS_Pricing $pricing ) { $price_tag = ''; if ( isset( $pricing->annual_price ) ) { $price_tag = $pricing->annual_price . ( $plan->is_block_features ? ' / year' : '' ); } else if ( isset( $pricing->monthly_price ) ) { $price_tag = $pricing->monthly_price . ' / mo'; } else if ( isset( $pricing->lifetime_price ) ) { $price_tag = $pricing->lifetime_price; } return '$' . $price_tag; } /** * @author Leo Fajardo (@leorw) * @since 2.3.0 * * @param object $api * @param FS_Plugin_Plan $plan * * @return string */ private function get_actions_dropdown( $api, $plan = null ) { $this->actions = isset( $this->actions ) ? $this->actions : $this->get_plugin_actions( $api ); $actions = $this->actions; $checkout_cta = $this->get_checkout_cta( $api, $plan ); if ( ! empty( $checkout_cta ) ) { /** * If there's no license yet, make the checkout button the main CTA. Otherwise, make it the last item in * the actions dropdown. * * @author Leo Fajardo (@leorw) * @since 2.3.0 */ if ( ! $api->has_purchased_license ) { array_unshift( $actions, $checkout_cta ); } else { $actions[] = $checkout_cta; } } if ( empty( $actions ) ) { return ''; } $total_actions = count( $actions ); if ( 1 === $total_actions ) { return $actions[0]; } ob_start(); ?>
checkout_link ) || ! isset( $api->plans ) || ! is_array( $api->plans ) || 0 == count( $api->plans ) ) { return ''; } if ( is_null( $plan ) ) { foreach ( $api->plans as $p ) { if ( ! empty( $p->pricing ) ) { $plan = $p; break; } } } $blog_id = fs_request_get( 'fs_blog_id' ); $has_valid_blog_id = is_numeric( $blog_id ); if ( $has_valid_blog_id ) { switch_to_blog( $blog_id ); } $addon_checkout_url = $this->_fs->addon_checkout_url( $plan->plugin_id, $plan->pricing[0]->id, $this->get_billing_cycle( $plan ), $plan->has_trial(), ( $has_valid_blog_id ? false : null ) ); if ( $has_valid_blog_id ) { restore_current_blog(); } return '' . esc_html( ! $plan->has_trial() ? ( $api->has_purchased_license ? fs_text_inline( 'Purchase More', 'purchase-more', $api->slug ) : fs_text_x_inline( 'Purchase', 'verb', 'purchase', $api->slug ) ) : sprintf( /* translators: %s: N-days trial */ fs_text_inline( 'Start my free %s', 'start-free-x', $api->slug ), $this->get_trial_period( $plan ) ) ) . ''; } /** * @author Leo Fajardo (@leorw) * @since 2.3.0 * * @param object $api * * @return string[] */ private function get_plugin_actions( $api ) { $this->status = isset( $this->status ) ? $this->status : install_plugin_install_status( $api ); $is_update_available = ( 'update_available' === $this->status['status'] ); if ( $is_update_available && empty( $this->status['url'] ) ) { return array(); } $blog_id = fs_request_get( 'fs_blog_id' ); $active_plugins_directories_map = Freemius::get_active_plugins_directories_map( $blog_id ); $actions = array(); $is_addon_activated = $this->_fs->is_addon_activated( $api->slug ); $fs_addon = null; $is_free_installed = null; $is_premium_installed = null; $has_installed_version = ( 'install' !== $this->status['status'] ); if ( ! $api->has_paid_plan && ! $api->has_purchased_license ) { /** * Free-only add-on. * * @author Leo Fajardo (@leorw) * @since 2.3.0 */ $is_free_installed = $has_installed_version; $is_premium_installed = false; } else if ( ! $api->has_free_plan ) { /** * Premium-only add-on. * * @author Leo Fajardo (@leorw) * @since 2.3.0 */ $is_free_installed = false; $is_premium_installed = $has_installed_version; } else { /** * Freemium add-on. * * @author Leo Fajardo (@leorw) * @since 2.3.0 */ if ( ! $has_installed_version ) { $is_free_installed = false; $is_premium_installed = false; } else { $fs_addon = $is_addon_activated ? $this->_fs->get_addon_instance( $api->slug ) : null; if ( is_object( $fs_addon ) ) { if ( $fs_addon->is_premium() ) { $is_premium_installed = true; } else { $is_free_installed = true; } } if ( is_null( $is_free_installed ) ) { $is_free_installed = file_exists( fs_normalize_path( WP_PLUGIN_DIR . "/{$api->slug}/{$api->slug}.php" ) ); if ( ! $is_free_installed ) { /** * Check if there's a plugin installed in a directory named `$api->slug`. * * @author Leo Fajardo (@leorw) * @since 2.3.0 */ $installed_plugins = get_plugins( '/' . $api->slug ); $is_free_installed = ( ! empty( $installed_plugins ) ); } } if ( is_null( $is_premium_installed ) ) { $is_premium_installed = file_exists( fs_normalize_path( WP_PLUGIN_DIR . "/{$api->premium_slug}/{$api->slug}.php" ) ); if ( ! $is_premium_installed ) { /** * Check if there's a plugin installed in a directory named `$api->premium_slug`. * * @author Leo Fajardo (@leorw) * @since 2.3.0 */ $installed_plugins = get_plugins( '/' . $api->premium_slug ); $is_premium_installed = ( ! empty( $installed_plugins ) ); } } } $has_installed_version = ( $is_free_installed || $is_premium_installed ); } $this->status['is_free_installed'] = $is_free_installed; $this->status['is_premium_installed'] = $is_premium_installed; $can_install_free_version = false; $can_install_free_version_update = false; $can_download_free_version = false; $can_activate_free_version = false; $can_install_premium_version = false; $can_install_premium_version_update = false; $can_download_premium_version = false; $can_activate_premium_version = false; if ( ! $api->has_purchased_license ) { if ( $api->has_free_plan ) { if ( $has_installed_version ) { if ( $is_update_available ) { $can_install_free_version_update = true; } else if ( ! $is_premium_installed && ! isset( $active_plugins_directories_map[ dirname( $this->status['file'] ) ] ) ) { $can_activate_free_version = true; } } else { if ( $this->_fs->is_premium() || ! $this->_fs->is_org_repo_compliant() || $api->is_wp_org_compliant ) { $can_install_free_version = true; } else { $can_download_free_version = true; } } } } else { if ( ! is_object( $fs_addon ) && $is_addon_activated ) { $fs_addon = $this->_fs->get_addon_instance( $api->slug ); } $can_download_premium_version = true; if ( ! isset( $active_plugins_directories_map[ dirname( $this->status['file'] ) ] ) ) { if ( $is_premium_installed ) { $can_activate_premium_version = ( ! $is_addon_activated || ! $fs_addon->is_premium() ); } else if ( $is_free_installed ) { $can_activate_free_version = ( ! $is_addon_activated ); } } if ( $this->_fs->is_premium() || ! $this->_fs->is_org_repo_compliant() ) { if ( $is_update_available ) { $can_install_premium_version_update = true; } else if ( ! $is_premium_installed ) { $can_install_premium_version = true; } } } if ( $can_install_premium_version || $can_install_premium_version_update ) { if ( is_numeric( $blog_id ) ) { /** * Replace the network status URL with a blog admin–based status URL if the `Add-Ons` page is loaded * from a specific blog admin page (when `fs_blog_id` is valid) in order for plugin installation/update * to work. * * @author Leo Fajardo (@leorw) * @since 2.3.0 */ $this->status['url'] = self::get_blog_status_url( $blog_id, $this->status['url'], $this->status['status'] ); } /** * Add the `fs_allow_updater_and_dialog` param to the install/update URL so that the add-on can be * installed/updated. * * @author Leo Fajardo (@leorw) * @since 2.3.0 */ $this->status['url'] = str_replace( '?', '?fs_allow_updater_and_dialog=true&', $this->status['url'] ); } if ( $can_install_free_version_update || $can_install_premium_version_update ) { $actions[] = $this->get_cta( ( $can_install_free_version_update ? fs_esc_html_inline( 'Install Free Version Update Now', 'install-free-version-update-now', $api->slug ) : fs_esc_html_inline( 'Install Update Now', 'install-update-now', $api->slug ) ), true, false, $this->status['url'], '_parent' ); } else if ( $can_install_free_version || $can_install_premium_version ) { $actions[] = $this->get_cta( ( $can_install_free_version ? fs_esc_html_inline( 'Install Free Version Now', 'install-free-version-now', $api->slug ) : fs_esc_html_inline( 'Install Now', 'install-now', $api->slug ) ), true, false, $this->status['url'], '_parent' ); } $download_latest_action = ''; if ( ! empty( $api->download_link ) && ( $can_download_free_version || $can_download_premium_version ) ) { $download_latest_action = $this->get_cta( ( $can_download_free_version ? fs_esc_html_x_inline( 'Download Latest Free Version', 'as download latest version', 'download-latest-free-version', $api->slug ) : fs_esc_html_x_inline( 'Download Latest', 'as download latest version', 'download-latest', $api->slug ) ), true, false, esc_url( $api->download_link ) ); } if ( ! $can_activate_free_version && ! $can_activate_premium_version ) { if ( ! empty( $download_latest_action ) ) { $actions[] = $download_latest_action; } } else { $activate_action = sprintf( '%s', wp_nonce_url( ( is_numeric( $blog_id ) ? trailingslashit( get_admin_url( $blog_id ) ) : '' ) . 'plugins.php?action=activate&plugin=' . $this->status['file'], 'activate-plugin_' . $this->status['file'] ), fs_esc_attr_inline( 'Activate this add-on', 'activate-this-addon', $api->slug ), $can_activate_free_version ? fs_text_inline( 'Activate Free Version', 'activate-free', $api->slug ) : fs_text_inline( 'Activate', 'activate', $api->slug ) ); if ( ! $can_download_premium_version && ! empty( $download_latest_action ) ) { $actions[] = $download_latest_action; $download_latest_action = ''; } if ( $can_install_premium_version || $can_install_premium_version_update ) { if ( $can_download_premium_version && ! empty( $download_latest_action ) ) { $actions[] = $download_latest_action; $download_latest_action = ''; } $actions[] = $activate_action; } else { array_unshift( $actions, $activate_action ); } if ( ! empty ($download_latest_action ) ) { $actions[] = $download_latest_action; } } return $actions; } /** * Rebuilds the status URL based on the admin URL. * * @author Leo Fajardo (@leorw) * @since 2.3.0 * * @param int $blog_id * @param string $network_status_url * @param string $status * * @return string */ private static function get_blog_status_url( $blog_id, $network_status_url, $status ) { if ( ! in_array( $status, array( 'install', 'update_available' ) ) ) { return $network_status_url; } $action = ( 'install' === $status ) ? 'install-plugin' : 'upgrade-plugin'; $url_params = fs_parse_url_params( $network_status_url, true ); if ( empty( $url_params ) || ! isset( $url_params['plugin'] ) ) { return $network_status_url; } $plugin = $url_params['plugin']; return wp_nonce_url( get_admin_url( $blog_id,"update.php?action={$action}&plugin={$plugin}"), "{$action}_{$plugin}"); } /** * Helper method to get a CTA button HTML. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param string $label * @param bool $is_primary * @param bool $is_disabled * @param string $href * @param string $target * * @return string */ private function get_cta( $label, $is_primary = true, $is_disabled = false, $href = '', $target = '_blank' ) { $classes = array(); if ( ! $is_primary ) { $classes[] = 'left'; } else { $classes[] = 'button-primary'; $classes[] = 'right'; } if ( $is_disabled ) { $classes[] = 'disabled'; } $rel = ( '_blank' === $target ) ? ' rel="noopener noreferrer"' : ''; return sprintf( '%s', empty( $href ) ? '' : 'href="' . $href . '" target="' . $target . '"' . $rel, implode( ' ', $classes ), $label ); } /** * @author Vova Feldman (@svovaf) * @since 1.1.7 * * @param FS_Plugin_Plan $plan * * @return string */ private function get_trial_period( $plan ) { $trial_period = (int) $plan->trial_period; switch ( $trial_period ) { case 30: return 'month'; case 60: return '2 months'; default: return "{$plan->trial_period} days"; } } /** * Display plugin information in dialog box form. * * Based on core install_plugin_information() function. * * @author Vova Feldman (@svovaf) * @since 1.0.6 */ function install_plugin_information() { global $tab; if ( empty( $_REQUEST['plugin'] ) ) { return; } $args = array( 'slug' => wp_unslash( $_REQUEST['plugin'] ), 'is_ssl' => is_ssl(), 'fields' => array( 'banners' => true, 'reviews' => true, 'downloaded' => false, 'active_installs' => true ) ); if ( is_array( $args ) ) { $args = (object) $args; } if ( ! isset( $args->per_page ) ) { $args->per_page = 24; } if ( ! isset( $args->locale ) ) { $args->locale = get_locale(); } $api = apply_filters( 'fs_plugins_api', false, 'plugin_information', $args ); if ( is_wp_error( $api ) ) { wp_die( $api ); } $plugins_allowedtags = array( 'a' => array( 'href' => array(), 'title' => array(), 'target' => array(), // Add image style for screenshots. 'class' => array() ), 'style' => array(), 'abbr' => array( 'title' => array() ), 'acronym' => array( 'title' => array() ), 'code' => array(), 'pre' => array(), 'em' => array(), 'strong' => array(), 'div' => array( 'class' => array() ), 'span' => array( 'class' => array() ), 'p' => array(), 'ul' => array(), 'ol' => array(), 'li' => array( 'class' => array() ), 'i' => array( 'class' => array() ), 'h1' => array(), 'h2' => array(), 'h3' => array(), 'h4' => array(), 'h5' => array(), 'h6' => array(), 'img' => array( 'src' => array(), 'class' => array(), 'alt' => array() ), // 'table' => array(), // 'td' => array(), // 'tr' => array(), // 'th' => array(), // 'thead' => array(), // 'tbody' => array(), ); $plugins_section_titles = array( 'description' => fs_text_x_inline( 'Description', 'Plugin installer section title', 'description', $api->slug ), 'installation' => fs_text_x_inline( 'Installation', 'Plugin installer section title', 'installation', $api->slug ), 'faq' => fs_text_x_inline( 'FAQ', 'Plugin installer section title', 'faq', $api->slug ), 'screenshots' => fs_text_inline( 'Screenshots', 'screenshots', $api->slug ), 'changelog' => fs_text_x_inline( 'Changelog', 'Plugin installer section title', 'changelog', $api->slug ), 'reviews' => fs_text_x_inline( 'Reviews', 'Plugin installer section title', 'reviews', $api->slug ), 'other_notes' => fs_text_x_inline( 'Other Notes', 'Plugin installer section title', 'other-notes', $api->slug ), ); // Sanitize HTML // foreach ( (array) $api->sections as $section_name => $content ) { // $api->sections[$section_name] = wp_kses( $content, $plugins_allowedtags ); // } foreach ( array( 'version', 'author', 'requires', 'tested', 'homepage', 'downloaded', 'slug' ) as $key ) { if ( isset( $api->$key ) ) { $api->$key = wp_kses( $api->$key, $plugins_allowedtags ); } } // Add after $api->slug is ready. $plugins_section_titles['features'] = fs_text_x_inline( 'Features & Pricing', 'Plugin installer section title', 'features-and-pricing', $api->slug ); $_tab = esc_attr( $tab ); $section = isset( $_REQUEST['section'] ) ? wp_unslash( $_REQUEST['section'] ) : 'description'; // Default to the Description tab, Do not translate, API returns English. if ( empty( $section ) || ! isset( $api->sections[ $section ] ) ) { $section_titles = array_keys( (array) $api->sections ); $section = array_shift( $section_titles ); } iframe_header( fs_text_inline( 'Plugin Install', 'plugin-install', $api->slug ) ); $_with_banner = ''; // var_dump($api->banners); if ( ! empty( $api->banners ) && ( ! empty( $api->banners['low'] ) || ! empty( $api->banners['high'] ) ) ) { $_with_banner = 'with-banner'; $low = empty( $api->banners['low'] ) ? $api->banners['high'] : $api->banners['low']; $high = empty( $api->banners['high'] ) ? $api->banners['low'] : $api->banners['high']; ?> '; echo "

{$api->name}

"; echo "
\n"; foreach ( (array) $api->sections as $section_name => $content ) { if ( 'reviews' === $section_name && ( empty( $api->ratings ) || 0 === array_sum( (array) $api->ratings ) ) ) { continue; } if ( isset( $plugins_section_titles[ $section_name ] ) ) { $title = $plugins_section_titles[ $section_name ]; } else { $title = ucwords( str_replace( '_', ' ', $section_name ) ); } $class = ( $section_name === $section ) ? ' class="current"' : ''; $href = add_query_arg( array( 'tab' => $tab, 'section' => $section_name ) ); $href = esc_url( $href ); $san_section = esc_attr( $section_name ); echo "\t" . esc_html( $title ) . "\n"; } echo "
\n"; ?>
is_paid ) : ?> plans ) ) : ?>
plans as $plan ) : ?> pricing ) ) { continue; } /** * @var FS_Plugin_Plan $plan */ ?> pricing[0] ?> is_multi_cycle() ?>

slug ), $plan->title ) ) ?>

has_annual() ?> has_monthly() ?>
pricing[0]->annual_discount_percentage() : 0 ?> 0 ) : ?> slug ), $annual_discount . '%' ) ?>
get_actions_dropdown( $api, $plan ) ?>
has_trial() ) : ?> get_trial_period( $plan ) ?>
  • slug ), $trial_period ) ) ?>
  • slug ) ), $trial_period, '' . $this->get_price_tag( $plan, $plan->pricing[0] ) . '' ) ?>

slug ) ?>

    version ) ) { ?>
  • slug ); ?> : version; ?>
  • author ) ) { ?>
  • slug ); ?> : author, '_blank' ); ?>
  • last_updated ) ) { ?>
  • slug ); ?> : slug ), human_time_diff( strtotime( $api->last_updated ) ) ) ) ?>
  • requires ) ) { ?>
  • slug ) ?> : slug ), $api->requires ) ) ?>
  • tested ) ) { ?>
  • slug ); ?> : tested; ?>
  • requires_php ) ) { ?>
  • slug ); ?>: slug ), $api->requires_php ) ); ?>
  • downloaded ) ) { ?>
  • slug ) ?> : downloaded ) ? /* translators: %s: 1 or One (Number of times downloaded) */ fs_text_inline( '%s time', 'x-time', $api->slug ) : /* translators: %s: Number of times downloaded */ fs_text_inline( '%s times', 'x-times', $api->slug ) ), number_format_i18n( $api->downloaded ) ) ); ?>
  • slug ) && true == $api->is_wp_org_compliant ) { ?>
  • slug ) ?> »
  • homepage ) ) { ?>
  • slug ) ?> »
  • donate_link ) && empty( $api->contributors ) ) { ?>
  • slug ) ?> »
rating ) ) { ?>

slug ); ?>

$api->rating, 'type' => 'percent', 'number' => $api->num_ratings ) ); ?> (slug ), sprintf( ( ( 1 == $api->num_ratings ) ? /* translators: %s: 1 or One */ fs_text_inline( '%s rating', 'x-rating', $api->slug ) : /* translators: %s: Number larger than 1 */ fs_text_inline( '%s ratings', 'x-ratings', $api->slug ) ), number_format_i18n( $api->num_ratings ) ) ) ) ?>) ratings ) && array_sum( (array) $api->ratings ) > 0 ) { foreach ( $api->ratings as $key => $ratecount ) { // Avoid div-by-zero. $_rating = $api->num_ratings ? ( $ratecount / $api->num_ratings ) : 0; $stars_label = sprintf( ( ( 1 == $key ) ? /* translators: %s: 1 or One */ fs_text_inline( '%s star', 'x-star', $api->slug ) : /* translators: %s: Number larger than 1 */ fs_text_inline( '%s stars', 'x-stars', $api->slug ) ), number_format_i18n( $key ) ); ?>
contributors ) ) { ?>

slug ); ?>

donate_link ) ) { ?> slug ) ?> »
requires_php ) ? $api->requires_php : null; $requires_wp = isset( $api->requires ) ? $api->requires : null; $compatible_php = empty( $requires_php ) || version_compare( PHP_VERSION, $requires_php, '>=' ); // Strip off any -alpha, -RC, -beta, -src suffixes. list( $wp_version ) = explode( '-', $GLOBALS['wp_version'] ); $compatible_wp = empty( $requires_wp ) || version_compare( $wp_version, $requires_wp, '>=' ); $tested_wp = ( empty( $api->tested ) || version_compare( $wp_version, $api->tested, '<=' ) ); if ( ! $compatible_php ) { echo '

' . fs_text_inline( 'Error', 'error', $api->slug ) . ': ' . fs_text_inline( 'This plugin requires a newer version of PHP.', 'newer-php-required-error', $api->slug ); if ( current_user_can( 'update_php' ) ) { $wp_get_update_php_url = function_exists( 'wp_get_update_php_url' ) ? wp_get_update_php_url() : 'https://wordpress.org/support/update-php/'; printf( /* translators: %s: URL to Update PHP page. */ ' ' . fs_text_inline( 'Click here to learn more about updating PHP.', 'php-update-learn-more-link', $api->slug ), esc_url( $wp_get_update_php_url ) ); if ( function_exists( 'wp_update_php_annotation' ) ) { wp_update_php_annotation( '

', '' ); } } else { echo '

'; } echo '
'; } if ( ! $tested_wp ) { echo '

' . '' . fs_text_inline( 'Warning', 'warning', $api->slug ) . ': ' . fs_text_inline( 'This plugin has not been tested with your current version of WordPress.', 'not-tested-warning', $api->slug ) . '

'; } else if ( ! $compatible_wp ) { echo '

' . '' . fs_text_inline( 'Warning', 'warning', $api->slug ) . ': ' . fs_text_inline( 'This plugin has not been marked as compatible with your version of WordPress.', 'not-compatible-warning', $api->slug ) . '

'; } foreach ( (array) $api->sections as $section_name => $content ) { $content = links_add_base_url( $content, 'https://wordpress.org/plugins/' . $api->slug . '/' ); $content = links_add_target( $content, '_blank' ); $san_section = esc_attr( $section_name ); $display = ( $section_name === $section ) ? 'block' : 'none'; if ( 'description' === $section_name && ( ( $api->is_wp_org_compliant && $api->wp_org_missing ) || ( ! $api->is_wp_org_compliant && $api->fs_missing ) ) ) { $missing_notice = array( 'type' => 'error', 'id' => md5( microtime() ), 'message' => $api->is_paid ? fs_text_inline( 'Paid add-on must be deployed to Freemius.', 'paid-addon-not-deployed', $api->slug ) : fs_text_inline( 'Add-on must be deployed to WordPress.org or Freemius.', 'free-addon-not-deployed', $api->slug ), ); fs_require_template( 'admin-notice.php', $missing_notice ); } echo "\t
\n"; echo $content; echo "\t
\n"; } echo "
\n"; echo "
\n"; echo "\n"; // #plugin-information-scrollable echo "\n"; ?>