LLMS_Helper_Upgrader
Contents
Source Source
File: libraries/lifterlms-helper/includes/class-llms-helper-upgrader.php
class LLMS_Helper_Upgrader { /** * Singleton instance * * @var null|LLMS_Helper_Upgrader */ protected static $instance = null; /** * Main Instance of LLMS_Helper_Upgrader * * @since 3.0.0 * @since version] Use `self::$instance` in favor of `self::$_instance`. * * @return LLMS_Helper_Upgrader */ public static function instance() { if ( is_null( self::$instance ) ) { self::$instance = new self(); } return self::$instance; } /** * Constructor * * @since 3.0.0 * @since 3.0.2 Unknown. * * @return void */ private function __construct() { // Setup a llms add-on plugin info. add_filter( 'plugins_api', array( $this, 'plugins_api' ), 10, 3 ); // Authenticate and get a real download link during add-on upgrade attempts. add_filter( 'upgrader_package_options', array( $this, 'upgrader_package_options' ) ); // Add llms add-on info to list of available updates. add_filter( 'pre_set_site_transient_update_themes', array( $this, 'pre_set_site_transient_update_things' ) ); add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'pre_set_site_transient_update_things' ) ); $products = llms_get_add_ons(); if ( ! is_wp_error( $products ) && isset( $products['items'] ) ) { foreach ( (array) $products['items'] as $product ) { if ( 'plugin' === $product['type'] && $product['update_file'] ) { add_action( "in_plugin_update_message-{$product['update_file']}", array( $this, 'in_plugin_update_message' ), 10, 2 ); } } } } /** * Install an add-on from LifterLMS.com * * @since 3.0.0 * @since 3.2.0 Use strict comparison for `in_array()`. * @since 3.4.0 Use core textdomain. * * @param string|obj $addon_or_id ID for the add-on or an instance of the LLMS_Add_On. * @param string $action Installation type [install|update]. * @return WP_Error|true */ public function install_addon( $addon_or_id, $action = 'install' ) { // Setup the addon. $addon = is_a( $addon_or_id, 'LLMS_Add_On' ) ? $addon_or_id : llms_get_add_on( $addon_or_id ); if ( ! $addon ) { return new WP_Error( 'invalid_addon', __( 'Invalid add-on ID.', 'lifterlms' ) ); } if ( ! in_array( $action, array( 'install', 'update' ), true ) ) { return new WP_Error( 'invalid_action', __( 'Invalid action.', 'lifterlms' ) ); } if ( ! $addon->is_installable() ) { return new WP_Error( 'not_installable', __( 'Add-on cannot be installable.', 'lifterlms' ) ); } // Make sure it's not already installed. if ( 'install' === $action && $addon->is_installed() ) { // Translators: %s = Add-on name. return new WP_Error( 'installed', sprintf( __( '%s is already installed', 'lifterlms' ), $addon->get( 'title' ) ) ); } // Get download info via llms.com api. $dl_info = $addon->get_download_info(); if ( is_wp_error( $dl_info ) ) { return $dl_info; } if ( ! isset( $dl_info['data']['url'] ) ) { return new WP_Error( 'no_url', __( 'An error occured while attempting to retrieve add-on download information. Please try again.', 'lifterlms' ) ); } require_once ABSPATH . 'wp-admin/includes/file.php'; include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; WP_Filesystem(); $skin = new Automatic_Upgrader_Skin(); if ( 'plugin' === $addon->get_type() ) { $upgrader = new Plugin_Upgrader( $skin ); } elseif ( 'theme' === $addon->get_type() ) { $upgrader = new Theme_Upgrader( $skin ); } else { return new WP_Error( 'inconceivable', __( 'The requested action is not possible.', 'lifterlms' ) ); } if ( 'install' === $action ) { remove_filter( 'upgrader_package_options', array( $this, 'upgrader_package_options' ) ); $result = $upgrader->install( $dl_info['data']['url'] ); add_filter( 'upgrader_package_options', array( $this, 'upgrader_package_options' ) ); } elseif ( 'update' === $action ) { $result = $upgrader->upgrade( $addon->get( 'update_file' ) ); } if ( is_wp_error( $result ) ) { return $result; } elseif ( is_wp_error( $skin->result ) ) { return $skin->result; } elseif ( is_null( $result ) ) { return new WP_Error( 'filesystem', __( 'Unable to connect to the filesystem. Please confirm your credentials.', 'lifterlms' ) ); } return true; } /** * Output additional information on plugins update screen when updates are available for an unlicensed addon * * @since 3.0.0 * @since 3.0.2 Unknown. * @since 3.4.0 Use core textdomain. * * @param array $plugin_data Array of plugin data. * @param array $res Response data. * @return void */ public function in_plugin_update_message( $plugin_data, $res ) { if ( empty( $plugin_data['package'] ) ) { echo '<style>p.llms-msg:before { content: ""; }</style>'; echo '<p class="llms-msg"><strong>'; _e( 'Your LifterLMS add-on is currently unlicensed and cannot be updated!', 'lifterlms' ); echo '</strong></p>'; echo '<p class="llms-msg">'; // Translators: %1$s = Opening anchor tag; %2$s = Closing anchor tag. printf( __( 'If you already have a license, you can activate it on the %1$sadd-ons management screen%2$s.', 'lifterlms' ), '<a href="' . esc_url( admin_url( 'admin.php?page=llms-add-ons' ) ) . '">', '</a>' ); echo '</p>'; echo '<p class="llms-msg">'; // Translators: %s = URI to licensing FAQ. printf( __( 'Learn more about LifterLMS add-on licensing at %s.', 'lifterlms' ), make_clickable( 'https://lifterlms.com/docs/lifterlms-helper/' ) ); echo '</p><p style="display:none;">'; } } /** * Filter API calls to get plugin information and replace it with data from LifterLMS.com API for our addons * * @since 3.0.0 * * @param bool $response False (denotes API call should be made to wp.org for plugin info). * @param string $action Name of the API action. * @param obj $args Additional API call args. * @return false|obj */ public function plugins_api( $response, $action = '', $args = null ) { if ( 'plugin_information' !== $action ) { return $response; } if ( empty( $args->slug ) ) { return $response; } $core = false; if ( 'lifterlms' === $args->slug ) { remove_filter( 'plugins_api', array( $this, 'plugins_api' ), 10, 3 ); $args->slug = 'lifterlms-com-lifterlms'; $core = true; } if ( 0 !== strpos( $args->slug, 'lifterlms-com-' ) ) { return $response; } $response = $this->set_plugins_api( $args->slug, true ); if ( $core ) { add_filter( 'plugins_api', array( $this, 'plugins_api' ), 10, 3 ); } return $response; } /** * Handle setting the site transient for plugin updates * * @since 3.0.0 * @since 3.0.2 Unknown. * * @param obj $value Transient value. * @return obj */ public function pre_set_site_transient_update_things( $value ) { if ( empty( $value ) ) { return $value; } $which = current_filter(); if ( 'pre_set_site_transient_update_plugins' === $which ) { $type = 'plugin'; } elseif ( 'pre_set_site_transient_update_themes' === $which ) { $type = 'theme'; } else { return $value; } $all_products = llms_get_add_ons( false ); if ( is_wp_error( $all_products ) || ! isset( $all_products['items'] ) ) { return $value; } foreach ( $all_products['items'] as $addon_data ) { $addon = llms_get_add_on( $addon_data ); if ( ! $addon->is_installable() || ! $addon->is_installed() ) { continue; } if ( $type !== $addon->get_type() ) { continue; } $file = $addon->get( 'update_file' ); if ( 'plugin' === $type ) { if ( 'lifterlms-com-lifterlms' === $addon->get( 'id' ) ) { if ( 'stable' === $addon->get_channel_subscription() || ! $addon->get( 'version_beta' ) ) { continue; } } $item = (object) $this->set_plugins_api( $addon->get( 'id' ), false ); } elseif ( 'theme' === $type ) { $item = array( 'theme' => $file, 'new_version' => $addon->get_latest_version(), 'url' => $addon->get_permalink(), 'package' => true, ); } if ( $addon->has_available_update() ) { $value->response[ $file ] = $item; unset( $value->no_update[ $file ] ); } else { $value->no_update[ $file ] = $item; unset( $value->response[ $file ] ); } } return $value; } /** * Setup an object of addon data for use when requesting plugin information normally acquired from wp.org. * * @since 3.0.0 * @since 3.2.1 Set package to `true` for add-ons which don't require a license. * @since 3.4.2 Added a `plugin` property to the returned plugin object, * which is required by `WP_Plugin_Install_List_Table::prepare_items()`. * * @param string $id Addon id. * @param bool $include_sections Whether or not to include additional sections like the description and changelog. * @return object */ private function set_plugins_api( $id, $include_sections = true ) { $addon = llms_get_add_on( $id ); if ( 'lifterlms-com-lifterlms' === $id && false !== strpos( $addon->get_latest_version(), 'beta' ) ) { require_once ABSPATH . 'wp-admin/includes/plugin-install.php'; $item = plugins_api( 'plugin_information', array( 'slug' => 'lifterlms', 'fields' => array( 'banners' => true, 'icons' => true, ), ) ); $item->version = $addon->get_latest_version(); $item->new_version = $addon->get_latest_version(); $item->package = true; unset( $item->versions ); $item->sections['changelog'] = $this->get_changelog_for_api( $addon ); return $item; } $item = array( 'name' => $addon->get( 'title' ), 'slug' => $id, 'plugin' => $addon->get( 'update_file' ), 'version' => $addon->get_latest_version(), 'new_version' => $addon->get_latest_version(), 'author' => '<a href="https://lifterlms.com/">' . $addon->get( 'author' )['name'] . '</a>', 'author_profile' => $addon->get( 'author' )['link'], 'requires' => $addon->get( 'version_wp' ), 'tested' => '', 'requires_php' => $addon->get( 'version_php' ), 'compatibility' => '', 'homepage' => $addon->get( 'permalink' ), 'download_link' => '', 'package' => ( $addon->is_licensed() || ! $addon->requires_license() ), 'banners' => array( 'low' => $addon->get( 'image' ), ), ); if ( $include_sections ) { $item['sections'] = array( 'description' => $addon->get( 'description' ), 'changelog' => $this->get_changelog_for_api( $addon ), ); } return (object) $item; } /** * Retrieve the changelog for an addon * * Attempts to retrieve changelog HTML from the make blog. * * If the add-on's changelog is empty or a static html file, returns an error * with a link to the release notes category on the make blog. * * @since 3.0.0 * @since 3.1.0 Retrieve changelog from the make blog in favor of legacy static html changelogs. * @since 3.2.0 Fix usage of incorrect textdomain. * * @param LLMS_Add_On $addon Add-on object. * @return string */ private function get_changelog_for_api( $addon ) { $src = $addon->get( 'changelog' ); $split = array_filter( explode( '/', $src ) ); $tag = end( $split ); $logs = false; if ( ! empty( $tag ) && false === strpos( $tag, '.html' ) ) { $logs = $this->get_changelog_html( $tag, $src ); } // Translators: %s = URL for the changelog website. return $logs ? $logs : make_clickable( sprintf( __( 'There was an error retrieving the changelog.<br>Try visiting %s for recent changelogs.', 'lifterlms' ), 'https://make.lifterlms.com/category/release-notes/' ) ); } /** * Retrieve changelog information from the make blog * * Retrieves the most recent 10 changelog entries for the add-on, formats the returned information * into a format suitable to display within the thickbox, adds a link to the full changelog, * and returns the html string. * * If an error is encountered, returns an empty string. * * @since 3.1.0 * @since 3.2.0 Fix usage of incorrect textdomain. * * @param string $tag Tag slug for the add-on on the blog. * @param string $url Full URL to the changelog entries for the add-on. * @return string */ private function get_changelog_html( $tag, $url ) { $ret = ''; $req = wp_remote_get( add_query_arg( 'slug', $tag, 'https://make.lifterlms.com/wp-json/wp/v2/tags' ) ); $body = json_decode( wp_remote_retrieve_body( $req ), true ); if ( ! empty( $body ) && ! empty( $body[0]['_links']['wp:post_type'][0]['href'] ) ) { $logs_url = $body[0]['_links']['wp:post_type'][0]['href']; $logs_req = wp_remote_get( $logs_url ); $logs = json_decode( wp_remote_retrieve_body( $logs_req ), true ); if ( ! empty( $logs ) && is_array( $logs ) ) { foreach ( $logs as $log ) { $ts = strtotime( $log['date_gmt'] ); $date = function_exists( 'wp_date' ) ? wp_date( 'Y-m-d', $ts ) : gmdate( 'Y-m-d', $ts ); $split = array_filter( explode( ' ', $log['title']['rendered'] ) ); $ver = end( $split ); // Translators: %1$s - Version number; %2$s - Release date. $ret .= '<h4>' . sprintf( __( 'Version %1$s - %2$s', 'lifterlms' ), sanitize_text_field( wp_strip_all_tags( trim( $ver ) ) ), $date ) . '</h4>'; $ret .= strip_tags( $log['content']['rendered'], '<ul><li><p><a><b><strong><em><i>' ); } } $ret .= '<br>'; // Translators: %s = URL to the full changelog. $ret .= '<p>' . make_clickable( sprintf( __( 'View the full changelog at %s.', 'lifterlms' ), $url ) ) . '</p>'; } return $ret; } /** * Get a real package download url for a LifterLMS add-on * * This is called immediately prior to package upgrades. * * @since 3.0.0 * @since 3.0.2 Unknown. * @since 3.2.1 Correctly process addons which do not require a license (e.g. free products). * * @param array $options Package option data. * @return array */ public function upgrader_package_options( $options ) { if ( ! isset( $options['hook_extra'] ) ) { return $options; } if ( isset( $options['hook_extra']['plugin'] ) ) { $file = $options['hook_extra']['plugin']; } elseif ( isset( $options['hook_extra']['theme'] ) ) { $file = $options['hook_extra']['theme']; } else { return $options; } $addon = llms_get_add_on( $file, 'update_file' ); if ( ! $addon || ! $addon->is_installable() || ( $addon->requires_license() && ! $addon->is_licensed() ) ) { return $options; } $info = $addon->get_download_info(); if ( is_wp_error( $info ) || ! isset( $info['data'] ) || ! isset( $info['data']['url'] ) ) { return $options; } if ( true === $options['package'] ) { $options['package'] = $info['data']['url']; } return $options; } }
Expand full source code Collapse full source code View on GitHub
Methods Methods
- __construct — Constructor
- get_changelog_for_api — Retrieve the changelog for an addon
- get_changelog_html — Retrieve changelog information from the make blog
- in_plugin_update_message — Output additional information on plugins update screen when updates are available for an unlicensed addon
- install_addon — Install an add-on from LifterLMS.com
- instance — Main Instance of LLMS_Helper_Upgrader
- plugins_api — Filter API calls to get plugin information and replace it with data from LifterLMS.com API for our addons
- pre_set_site_transient_update_things — Handle setting the site transient for plugin updates
- set_plugins_api — Setup an object of addon data for use when requesting plugin information normally acquired from wp.org.
- upgrader_package_options — Get a real package download url for a LifterLMS add-on
Changelog Changelog
Version | Description |
---|---|
3.1.0 | Load changelogs from the make blog in favor of static html changelogs. |
3.0.2 | Unknown. |
3.0.0 | Introduced. |