_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', false ); 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( "/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 ) ) { $has_paid_plan = true; foreach ( $pricing as &$prices ) { $prices = new FS_Pricing( $prices ); } $plan->pricing = $pricing; $has_pricing = true; } if ( is_array( $features ) && 0 < count( $features ) ) { $plan->features = $features; $has_features = true; } } } } 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; } } else { $data->wp_org_missing = false; // Fetch latest version from Freemius. $latest = $this->_fs->_fetch_latest_version( $selected_addon->id ); if ( $has_paid_plan ) { $data->checkout_link = $this->_fs->checkout_url(); } if ( $has_free_plan ) { $data->download_link = $this->_fs->_get_latest_download_local_url( $selected_addon->id ); } $data->fs_missing = ( false === $latest ); // Fetch as much as possible info from local files. $plugin_local_data = $this->_fs->get_plugin_data(); $data->name = $selected_addon->title; $data->author = $plugin_local_data['Author']; $view_vars = array( 'plugin' => $selected_addon ); $data->sections = array( 'description' => fs_get_template( '/plugin-info/description.php', $view_vars ), ); 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 = ! is_null( $latest->updated ) ? $latest->updated : $latest->created; $data->requires = $latest->requires_platform_version; $data->tested = $latest->tested_up_to_version; } else { // Add dummy version. $data->version = '1.0.0'; // Add message to developer to deploy the plugin through Freemius. } } 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; 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 Vova Feldman (@svovaf) * @since 1.1.7 * * @param object $api * @param FS_Plugin_Plan $plan * * @return string */ private function get_checkout_cta( $api, $plan = null ) { if ( empty( $api->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; } } } return '' . ( ! $plan->has_trial() ? 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 Vova Feldman (@svovaf) * @since 2.0.0 * * @param object $api * @param bool $is_primary * * @return string */ private function get_download_cta( $api, $is_primary = true ) { if ( empty( $api->download_link ) ) { return ''; } $status = install_plugin_install_status( $api ); $has_paid_version = $api->has_paid_plan; // Hosted on WordPress.org. switch ( $status['status'] ) { case 'install': if ( $api->is_wp_org_compliant || ! $this->_fs->is_org_repo_compliant() || $this->_fs->is_premium() ) { /** * Allow immediate installation if one of the following: * 1. WordPress.org add-on. * 2. The core module is NOT wp.org compliant. * 3. The core module is running the premium version which is not wp.org compliant. */ if ( $status['url'] ) { return $this->get_cta( ( $has_paid_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 ) ), $is_primary, false, $status['url'], '_parent' ); } } return $this->get_cta( ( $has_paid_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 ) ), $is_primary, false, esc_url( $api->download_link ) ); break; case 'update_available': if ( $status['url'] ) { return $this->get_cta( ( $has_paid_version ? 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 ) ), $is_primary, false, $status['url'], '_parent' ); } break; case 'newer_installed': return $this->get_cta( ( $has_paid_version ? esc_html( sprintf( fs_text_inline( 'Newer Free Version (%s) Installed', 'newer-free-installed', $api->slug ), $status['version'] ) ) : esc_html( sprintf( fs_text_inline( 'Newer Version (%s) Installed', 'newer-installed', $api->slug ), $status['version'] ) ) ), $is_primary, true ); break; case 'latest_installed': return $this->get_cta( ( $has_paid_version ? fs_esc_html_inline( 'Latest Free Version Installed', 'latest-free-installed', $api->slug ) : fs_esc_html_inline( 'Latest Version Installed', 'latest-installed', $api->slug ) ), $is_primary, true ); break; } return ''; } /** * 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'; } return sprintf( '%s', empty( $href ) ? '' : 'href="' . $href . '" target="' . $target . '"', 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$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_checkout_cta( $api, $plan, false ) ?>
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; ?>
  • 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 ) && empty( $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 ) ?> »
tested ) && version_compare( substr( $GLOBALS['wp_version'], 0, strlen( $api->tested ) ), $api->tested, '>' ) ) { 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 ( ! empty( $api->requires ) && version_compare( substr( $GLOBALS['wp_version'], 0, strlen( $api->requires ) ), $api->requires, '<' ) ) { 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"; iframe_footer(); exit; } }