Файловый менеджер - Редактировать - /home/infrafs/INFRABIKEIT/wp-content/plugins/helper.zip
Назад
PK ɥ3\�SDZh h class-wc-helper-options.phpnu �[��� <?php /** * WooCommerce Admin Helper Options * * @package WooCommerce\Admin\Helper */ if ( ! defined( 'ABSPATH' ) ) { exit; } /** * WC_Helper_Options Class * * An interface to the woocommerce_helper_data entry in the wp_options table. */ class WC_Helper_Options { /** * The option name used to store the helper data. * * @var string */ private static $option_name = 'woocommerce_helper_data'; /** * Update an option by key * * All helper options are grouped in a single options entry. This method * is not thread-safe, use with caution. * * @param string $key The key to update. * @param mixed $value The new option value. * * @return bool True if the option has been updated. */ public static function update( $key, $value ) { $options = get_option( self::$option_name, array() ); $options[ $key ] = $value; return update_option( self::$option_name, $options, true ); } /** * Get an option by key * * @see self::update * * @param string $key The key to fetch. * @param mixed $default The default option to return if the key does not exist. * * @return mixed An option or the default. */ public static function get( $key, $default = false ) { $options = get_option( self::$option_name, array() ); if ( array_key_exists( $key, $options ) ) { return $options[ $key ]; } return $default; } } PK ɥ3\)�q$7 7 class-wc-helper-api.phpnu �[��� <?php /** * WooCommerce Admin Helper API * * @package WooCommerce\Admin\Helper */ if ( ! defined( 'ABSPATH' ) ) { exit; } /** * WC_Helper_API Class * * Provides a communication interface with the WooCommerce.com Helper API. */ class WC_Helper_API { /** * Base path for API routes. * * @var $api_base */ public static $api_base; /** * Load * * Allow devs to point the API base to a local API development or staging server. * Note that sslverify will be turned off for the woocommerce.dev + WP_DEBUG combination. * The URL can be changed on plugins_loaded before priority 10. */ public static function load() { self::$api_base = apply_filters( 'woocommerce_helper_api_base', 'https://woocommerce.com/wp-json/helper/1.0' ); } /** * Perform an HTTP request to the Helper API. * * @param string $endpoint The endpoint to request. * @param array $args Additional data for the request. Set authenticated to a truthy value to enable auth. * * @return array|WP_Error The response from wp_safe_remote_request() */ public static function request( $endpoint, $args = array() ) { $url = self::url( $endpoint ); if ( ! empty( $args['authenticated'] ) ) { if ( ! self::_authenticate( $url, $args ) ) { return new WP_Error( 'authentication', 'Authentication failed.' ); } } /** * Allow developers to filter the request args passed to wp_safe_remote_request(). * Useful to remove sslverify when working on a local api dev environment. */ $args = apply_filters( 'woocommerce_helper_api_request_args', $args, $endpoint ); // TODO: Check response signatures on certain endpoints. return wp_safe_remote_request( $url, $args ); } /** * Adds authentication headers to an HTTP request. * * @param string $url The request URI. * @param array $args By-ref, the args that will be passed to wp_remote_request(). * @return bool Were the headers added? */ private static function _authenticate( &$url, &$args ) { $auth = WC_Helper_Options::get( 'auth' ); if ( empty( $auth['access_token'] ) || empty( $auth['access_token_secret'] ) ) { return false; } $request_uri = parse_url( $url, PHP_URL_PATH ); $query_string = parse_url( $url, PHP_URL_QUERY ); if ( is_string( $query_string ) ) { $request_uri .= '?' . $query_string; } $data = array( 'host' => parse_url( $url, PHP_URL_HOST ), 'request_uri' => $request_uri, 'method' => ! empty( $args['method'] ) ? $args['method'] : 'GET', ); if ( ! empty( $args['body'] ) ) { $data['body'] = $args['body']; } $signature = hash_hmac( 'sha256', json_encode( $data ), $auth['access_token_secret'] ); if ( empty( $args['headers'] ) ) { $args['headers'] = array(); } $headers = array( 'Authorization' => 'Bearer ' . $auth['access_token'], 'X-Woo-Signature' => $signature, ); $args['headers'] = wp_parse_args( $headers, $args['headers'] ); $url = add_query_arg( array( 'token' => $auth['access_token'], 'signature' => $signature, ), $url ); return true; } /** * Wrapper for self::request(). * * @param string $endpoint The helper API endpoint to request. * @param array $args Arguments passed to wp_remote_request(). * * @return array The response object from wp_safe_remote_request(). */ public static function get( $endpoint, $args = array() ) { $args['method'] = 'GET'; return self::request( $endpoint, $args ); } /** * Wrapper for self::request(). * * @param string $endpoint The helper API endpoint to request. * @param array $args Arguments passed to wp_remote_request(). * * @return array The response object from wp_safe_remote_request(). */ public static function post( $endpoint, $args = array() ) { $args['method'] = 'POST'; return self::request( $endpoint, $args ); } /** * Wrapper for self::request(). * * @param string $endpoint The helper API endpoint to request. * @param array $args Arguments passed to wp_remote_request(). * * @return array The response object from wp_safe_remote_request(). */ public static function put( $endpoint, $args = array() ) { $args['method'] = 'PUT'; return self::request( $endpoint, $args ); } /** * Using the API base, form a request URL from a given endpoint. * * @param string $endpoint The endpoint to request. * * @return string The absolute endpoint URL. */ public static function url( $endpoint ) { $endpoint = ltrim( $endpoint, '/' ); $endpoint = sprintf( '%s/%s', self::$api_base, $endpoint ); $endpoint = esc_url_raw( $endpoint ); return $endpoint; } } WC_Helper_API::load(); PK ɥ3\�{ |� � class-wc-helper-compat.phpnu �[��� <?php /** * WooCommerce Admin Helper Compat * * @package WooCommerce\Admin\Helper */ if ( ! defined( 'ABSPATH' ) ) { exit; } /** * WC_Helper_Compat Class * * Some level of compatibility with the legacy WooCommerce Helper plugin. */ class WC_Helper_Compat { /** * Loads the class, runs on init. */ public static function load() { add_action( 'woocommerce_helper_loaded', array( __CLASS__, 'helper_loaded' ) ); } /** * Runs during woocommerce_helper_loaded */ public static function helper_loaded() { // Stop the nagging about WooThemes Updater remove_action( 'admin_notices', 'woothemes_updater_notice' ); // A placeholder dashboard menu for legacy helper users. add_action( 'admin_menu', array( __CLASS__, 'admin_menu' ) ); if ( empty( $GLOBALS['woothemes_updater'] ) ) { return; } self::remove_actions(); self::migrate_connection(); self::deactivate_plugin(); } /** * Remove legacy helper actions (notices, menus, etc.) */ public static function remove_actions() { // Remove WooThemes Updater notices remove_action( 'network_admin_notices', array( $GLOBALS['woothemes_updater']->admin, 'maybe_display_activation_notice' ) ); remove_action( 'admin_notices', array( $GLOBALS['woothemes_updater']->admin, 'maybe_display_activation_notice' ) ); remove_action( 'network_admin_menu', array( $GLOBALS['woothemes_updater']->admin, 'register_settings_screen' ) ); remove_action( 'admin_menu', array( $GLOBALS['woothemes_updater']->admin, 'register_settings_screen' ) ); } /** * Attempt to migrate a legacy connection to a new one. */ public static function migrate_connection() { // Don't attempt to migrate if attempted before. if ( WC_Helper_Options::get( 'did-migrate' ) ) { return; } $auth = WC_Helper_Options::get( 'auth' ); if ( ! empty( $auth ) ) { return; } WC_Helper::log( 'Attempting oauth/migrate' ); WC_Helper_Options::update( 'did-migrate', true ); $master_key = get_option( 'woothemes_helper_master_key' ); if ( empty( $master_key ) ) { WC_Helper::log( 'Master key not found, aborting' ); return; } $request = WC_Helper_API::post( 'oauth/migrate', array( 'body' => array( 'home_url' => home_url(), 'master_key' => $master_key, ), ) ); if ( is_wp_error( $request ) || wp_remote_retrieve_response_code( $request ) !== 200 ) { WC_Helper::log( 'Call to oauth/migrate returned a non-200 response code' ); return; } $request_token = json_decode( wp_remote_retrieve_body( $request ) ); if ( empty( $request_token ) ) { WC_Helper::log( 'Call to oauth/migrate returned an empty token' ); return; } // Obtain an access token. $request = WC_Helper_API::post( 'oauth/access_token', array( 'body' => array( 'request_token' => $request_token, 'home_url' => home_url(), 'migrate' => true, ), ) ); if ( is_wp_error( $request ) || wp_remote_retrieve_response_code( $request ) !== 200 ) { WC_Helper::log( 'Call to oauth/access_token returned a non-200 response code' ); return; } $access_token = json_decode( wp_remote_retrieve_body( $request ), true ); if ( empty( $access_token ) ) { WC_Helper::log( 'Call to oauth/access_token returned an invalid token' ); return; } WC_Helper_Options::update( 'auth', array( 'access_token' => $access_token['access_token'], 'access_token_secret' => $access_token['access_token_secret'], 'site_id' => $access_token['site_id'], 'user_id' => null, // Set this later 'updated' => time(), ) ); // Obtain the connected user info. if ( ! WC_Helper::_flush_authentication_cache() ) { WC_Helper::log( 'Could not obtain connected user info in migrate_connection' ); WC_Helper_Options::update( 'auth', array() ); return; } } /** * Attempt to deactivate the legacy helper plugin. */ public static function deactivate_plugin() { include_once ABSPATH . 'wp-admin/includes/plugin.php'; if ( ! function_exists( 'deactivate_plugins' ) ) { return; } if ( is_plugin_active( 'woothemes-updater/woothemes-updater.php' ) ) { deactivate_plugins( 'woothemes-updater/woothemes-updater.php' ); // Notify the user when the plugin is deactivated. add_action( 'pre_current_active_plugins', array( __CLASS__, 'plugin_deactivation_notice' ) ); } } /** * Display admin notice directing the user where to go. */ public static function plugin_deactivation_notice() { ?> <div id="message" class="error is-dismissible"> <p><?php printf( __( 'The WooCommerce Helper plugin is no longer needed. <a href="%s">Manage subscriptions</a> from the extensions tab instead.', 'woocommerce' ), esc_url( admin_url( 'admin.php?page=wc-addons§ion=helper' ) ) ); ?></p> </div> <?php } /** * Register menu item. */ public static function admin_menu() { // No additional menu items for users who did not have a connected helper before. $master_key = get_option( 'woothemes_helper_master_key' ); if ( empty( $master_key ) ) { return; } // Do not show the menu item if user has already seen the new screen. $auth = WC_Helper_Options::get( 'auth' ); if ( ! empty( $auth['user_id'] ) ) { return; } add_dashboard_page( __( 'WooCommerce Helper', 'woocommerce' ), __( 'WooCommerce Helper', 'woocommerce' ), 'manage_options', 'woothemes-helper', array( __CLASS__, 'render_compat_menu' ) ); } /** * Render the legacy helper compat view. */ public static function render_compat_menu() { $helper_url = add_query_arg( array( 'page' => 'wc-addons', 'section' => 'helper', ), admin_url( 'admin.php' ) ); include WC_Helper::get_view_filename( 'html-helper-compat.php' ); } } WC_Helper_Compat::load(); PK ɥ3\��1qp p class-wc-helper-plugin-info.phpnu �[��� <?php /** * WooCommerce Admin Helper Plugin Info * * @package WooCommerce\Admin\Helper */ if ( ! defined( 'ABSPATH' ) ) { exit; } /** * WC_Helper_Plugin_Info Class * * Provides the "View Information" core modals with data for WooCommerce.com * hosted extensions. */ class WC_Helper_Plugin_Info { /** * Loads the class, runs on init. */ public static function load() { add_filter( 'plugins_api', array( __CLASS__, 'plugins_api' ), 20, 3 ); } /** * Plugin information callback for Woo extensions. * * @param object $response The response core needs to display the modal. * @param string $action The requested plugins_api() action. * @param object $args Arguments passed to plugins_api(). * * @return object An updated $response. */ public static function plugins_api( $response, $action, $args ) { if ( 'plugin_information' !== $action ) { return $response; } if ( empty( $args->slug ) ) { return $response; } // Only for slugs that start with woo- if ( 0 !== strpos( $args->slug, 'woocommerce-com-' ) ) { return $response; } $clean_slug = str_replace( 'woocommerce-com-', '', $args->slug ); // Look through update data by slug. $update_data = WC_Helper_Updater::get_update_data(); $products = wp_list_filter( $update_data, array( 'slug' => $clean_slug ) ); if ( empty( $products ) ) { return $response; } $product_id = array_keys( $products ); $product_id = array_shift( $product_id ); // Fetch the product information from the Helper API. $request = WC_Helper_API::get( add_query_arg( array( 'product_id' => absint( $product_id ), ), 'info' ), array( 'authenticated' => true ) ); $results = json_decode( wp_remote_retrieve_body( $request ), true ); if ( ! empty( $results ) ) { $response = (object) $results; } return $response; } } WC_Helper_Plugin_Info::load(); PK ɥ3\:a�B� B� class-wc-helper.phpnu �[��� <?php /** * WooCommerce Admin Helper * * @package WooCommerce\Admin\Helper */ use Automattic\Jetpack\Constants; if ( ! defined( 'ABSPATH' ) ) { exit; } /** * WC_Helper Class * * The main entry-point for all things related to the Helper. */ class WC_Helper { /** * A log object returned by wc_get_logger(). * * @var $log */ public static $log; /** * Get an absolute path to the requested helper view. * * @param string $view The requested view file. * * @return string The absolute path to the view file. */ public static function get_view_filename( $view ) { return dirname( __FILE__ ) . "/views/$view"; } /** * Loads the helper class, runs on init. */ public static function load() { self::includes(); add_action( 'current_screen', array( __CLASS__, 'current_screen' ) ); add_action( 'woocommerce_helper_output', array( __CLASS__, 'render_helper_output' ) ); add_action( 'admin_enqueue_scripts', array( __CLASS__, 'admin_enqueue_scripts' ) ); add_action( 'admin_notices', array( __CLASS__, 'admin_notices' ) ); do_action( 'woocommerce_helper_loaded' ); } /** * Include supporting helper classes. */ protected static function includes() { include_once dirname( __FILE__ ) . '/class-wc-helper-options.php'; include_once dirname( __FILE__ ) . '/class-wc-helper-api.php'; include_once dirname( __FILE__ ) . '/class-wc-helper-updater.php'; include_once dirname( __FILE__ ) . '/class-wc-helper-plugin-info.php'; include_once dirname( __FILE__ ) . '/class-wc-helper-compat.php'; } /** * Render the helper section content based on context. */ public static function render_helper_output() { $auth = WC_Helper_Options::get( 'auth' ); $auth_user_data = WC_Helper_Options::get( 'auth_user_data' ); // Return success/error notices. $notices = self::_get_return_notices(); // No active connection. if ( empty( $auth['access_token'] ) ) { $connect_url = add_query_arg( array( 'page' => 'wc-addons', 'section' => 'helper', 'wc-helper-connect' => 1, 'wc-helper-nonce' => wp_create_nonce( 'connect' ), ), admin_url( 'admin.php' ) ); include self::get_view_filename( 'html-oauth-start.php' ); return; } $disconnect_url = add_query_arg( array( 'page' => 'wc-addons', 'section' => 'helper', 'wc-helper-disconnect' => 1, 'wc-helper-nonce' => wp_create_nonce( 'disconnect' ), ), admin_url( 'admin.php' ) ); $current_filter = self::get_current_filter(); $refresh_url = add_query_arg( array( 'page' => 'wc-addons', 'section' => 'helper', 'filter' => $current_filter, 'wc-helper-refresh' => 1, 'wc-helper-nonce' => wp_create_nonce( 'refresh' ), ), admin_url( 'admin.php' ) ); // Installed plugins and themes, with or without an active subscription. $woo_plugins = self::get_local_woo_plugins(); $woo_themes = self::get_local_woo_themes(); $site_id = absint( $auth['site_id'] ); $subscriptions = self::get_subscriptions(); $updates = WC_Helper_Updater::get_update_data(); $subscriptions_product_ids = wp_list_pluck( $subscriptions, 'product_id' ); foreach ( $subscriptions as &$subscription ) { $subscription['active'] = in_array( $site_id, $subscription['connections'] ); $subscription['activate_url'] = add_query_arg( array( 'page' => 'wc-addons', 'section' => 'helper', 'filter' => $current_filter, 'wc-helper-activate' => 1, 'wc-helper-product-key' => $subscription['product_key'], 'wc-helper-product-id' => $subscription['product_id'], 'wc-helper-nonce' => wp_create_nonce( 'activate:' . $subscription['product_key'] ), ), admin_url( 'admin.php' ) ); $subscription['deactivate_url'] = add_query_arg( array( 'page' => 'wc-addons', 'section' => 'helper', 'filter' => $current_filter, 'wc-helper-deactivate' => 1, 'wc-helper-product-key' => $subscription['product_key'], 'wc-helper-product-id' => $subscription['product_id'], 'wc-helper-nonce' => wp_create_nonce( 'deactivate:' . $subscription['product_key'] ), ), admin_url( 'admin.php' ) ); $subscription['local'] = array( 'installed' => false, 'active' => false, 'version' => null, ); $subscription['update_url'] = admin_url( 'update-core.php' ); $local = wp_list_filter( array_merge( $woo_plugins, $woo_themes ), array( '_product_id' => $subscription['product_id'] ) ); if ( ! empty( $local ) ) { $local = array_shift( $local ); $subscription['local']['installed'] = true; $subscription['local']['version'] = $local['Version']; if ( 'plugin' == $local['_type'] ) { if ( is_plugin_active( $local['_filename'] ) ) { $subscription['local']['active'] = true; } elseif ( is_multisite() && is_plugin_active_for_network( $local['_filename'] ) ) { $subscription['local']['active'] = true; } // A magic update_url. $subscription['update_url'] = wp_nonce_url( self_admin_url( 'update.php?action=upgrade-plugin&plugin=' ) . $local['_filename'], 'upgrade-plugin_' . $local['_filename'] ); } elseif ( 'theme' == $local['_type'] ) { if ( in_array( $local['_stylesheet'], array( get_stylesheet(), get_template() ) ) ) { $subscription['local']['active'] = true; } // Another magic update_url. $subscription['update_url'] = wp_nonce_url( self_admin_url( 'update.php?action=upgrade-theme&theme=' . $local['_stylesheet'] ), 'upgrade-theme_' . $local['_stylesheet'] ); } } $subscription['has_update'] = false; if ( $subscription['local']['installed'] && ! empty( $updates[ $subscription['product_id'] ] ) ) { $subscription['has_update'] = version_compare( $updates[ $subscription['product_id'] ]['version'], $subscription['local']['version'], '>' ); } $subscription['download_primary'] = true; $subscription['download_url'] = 'https://woocommerce.com/my-account/downloads/'; if ( ! $subscription['local']['installed'] && ! empty( $updates[ $subscription['product_id'] ] ) ) { $subscription['download_url'] = $updates[ $subscription['product_id'] ]['package']; } $subscription['actions'] = array(); if ( $subscription['has_update'] && ! $subscription['expired'] ) { $action = array( /* translators: %s: version number */ 'message' => sprintf( __( 'Version %s is <strong>available</strong>.', 'woocommerce' ), esc_html( $updates[ $subscription['product_id'] ]['version'] ) ), 'button_label' => __( 'Update', 'woocommerce' ), 'button_url' => $subscription['update_url'], 'status' => 'update-available', 'icon' => 'dashicons-update', ); // Subscription is not active on this site. if ( ! $subscription['active'] ) { $action['message'] .= ' ' . __( 'To enable this update you need to <strong>activate</strong> this subscription.', 'woocommerce' ); $action['button_label'] = null; $action['button_url'] = null; } $subscription['actions'][] = $action; } if ( $subscription['has_update'] && $subscription['expired'] ) { $action = array( /* translators: %s: version number */ 'message' => sprintf( __( 'Version %s is <strong>available</strong>.', 'woocommerce' ), esc_html( $updates[ $subscription['product_id'] ]['version'] ) ), 'status' => 'expired', 'icon' => 'dashicons-info', ); $action['message'] .= ' ' . __( 'To enable this update you need to <strong>purchase</strong> a new subscription.', 'woocommerce' ); $action['button_label'] = __( 'Purchase', 'woocommerce' ); $action['button_url'] = $subscription['product_url']; $subscription['actions'][] = $action; } elseif ( $subscription['expired'] && ! empty( $subscription['master_user_email'] ) ) { $action = array( 'message' => sprintf( __( 'This subscription has expired. Contact the owner to <strong>renew</strong> the subscription to receive updates and support.', 'woocommerce' ) ), 'status' => 'expired', 'icon' => 'dashicons-info', ); $subscription['actions'][] = $action; } elseif ( $subscription['expired'] ) { $action = array( 'message' => sprintf( __( 'This subscription has expired. Please <strong>renew</strong> to receive updates and support.', 'woocommerce' ) ), 'button_label' => __( 'Renew', 'woocommerce' ), 'button_url' => 'https://woocommerce.com/my-account/my-subscriptions/', 'status' => 'expired', 'icon' => 'dashicons-info', ); $subscription['actions'][] = $action; } if ( $subscription['expiring'] && ! $subscription['autorenew'] ) { $action = array( 'message' => __( 'Subscription is <strong>expiring</strong> soon.', 'woocommerce' ), 'button_label' => __( 'Enable auto-renew', 'woocommerce' ), 'button_url' => 'https://woocommerce.com/my-account/my-subscriptions/', 'status' => 'expired', 'icon' => 'dashicons-info', ); $subscription['download_primary'] = false; $subscription['actions'][] = $action; } elseif ( $subscription['expiring'] ) { $action = array( 'message' => sprintf( __( 'This subscription is expiring soon. Please <strong>renew</strong> to continue receiving updates and support.', 'woocommerce' ) ), 'button_label' => __( 'Renew', 'woocommerce' ), 'button_url' => 'https://woocommerce.com/my-account/my-subscriptions/', 'status' => 'expired', 'icon' => 'dashicons-info', ); $subscription['download_primary'] = false; $subscription['actions'][] = $action; } // Mark the first action primary. foreach ( $subscription['actions'] as $key => $action ) { if ( ! empty( $action['button_label'] ) ) { $subscription['actions'][ $key ]['primary'] = true; break; } } } // Break the by-ref. unset( $subscription ); // Installed products without a subscription. $no_subscriptions = array(); foreach ( array_merge( $woo_plugins, $woo_themes ) as $filename => $data ) { if ( in_array( $data['_product_id'], $subscriptions_product_ids ) ) { continue; } $data['_product_url'] = '#'; $data['_has_update'] = false; if ( ! empty( $updates[ $data['_product_id'] ] ) ) { $data['_has_update'] = version_compare( $updates[ $data['_product_id'] ]['version'], $data['Version'], '>' ); if ( ! empty( $updates[ $data['_product_id'] ]['url'] ) ) { $data['_product_url'] = $updates[ $data['_product_id'] ]['url']; } elseif ( ! empty( $data['PluginURI'] ) ) { $data['_product_url'] = $data['PluginURI']; } } $data['_actions'] = array(); if ( $data['_has_update'] ) { $action = array( /* translators: %s: version number */ 'message' => sprintf( __( 'Version %s is <strong>available</strong>. To enable this update you need to <strong>purchase</strong> a new subscription.', 'woocommerce' ), esc_html( $updates[ $data['_product_id'] ]['version'] ) ), 'button_label' => __( 'Purchase', 'woocommerce' ), 'button_url' => $data['_product_url'], 'status' => 'expired', 'icon' => 'dashicons-info', ); $data['_actions'][] = $action; } else { $action = array( /* translators: 1: subscriptions docs 2: subscriptions docs */ 'message' => sprintf( __( 'To receive updates and support for this extension, you need to <strong>purchase</strong> a new subscription or consolidate your extensions to one connected account by <strong><a href="%1$s" title="Sharing Docs">sharing</a> or <a href="%2$s" title="Transferring Docs">transferring</a></strong> this extension to this connected account.', 'woocommerce' ), 'https://docs.woocommerce.com/document/managing-woocommerce-com-subscriptions/#section-10', 'https://docs.woocommerce.com/document/managing-woocommerce-com-subscriptions/#section-5' ), 'button_label' => __( 'Purchase', 'woocommerce' ), 'button_url' => $data['_product_url'], 'status' => 'expired', 'icon' => 'dashicons-info', ); $data['_actions'][] = $action; } $no_subscriptions[ $filename ] = $data; } // Update the user id if it came from a migrated connection. if ( empty( $auth['user_id'] ) ) { $auth['user_id'] = get_current_user_id(); WC_Helper_Options::update( 'auth', $auth ); } // Sort alphabetically. uasort( $subscriptions, array( __CLASS__, '_sort_by_product_name' ) ); uasort( $no_subscriptions, array( __CLASS__, '_sort_by_name' ) ); // Filters. self::get_filters_counts( $subscriptions ); // Warm it up. self::_filter( $subscriptions, self::get_current_filter() ); // We have an active connection. include self::get_view_filename( 'html-main.php' ); return; } /** * Get available subscriptions filters. * * @return array An array of filter keys and labels. */ public static function get_filters() { $filters = array( 'all' => __( 'All', 'woocommerce' ), 'active' => __( 'Active', 'woocommerce' ), 'inactive' => __( 'Inactive', 'woocommerce' ), 'installed' => __( 'Installed', 'woocommerce' ), 'update-available' => __( 'Update Available', 'woocommerce' ), 'expiring' => __( 'Expiring Soon', 'woocommerce' ), 'expired' => __( 'Expired', 'woocommerce' ), 'download' => __( 'Download', 'woocommerce' ), ); return $filters; } /** * Get counts data for the filters array. * * @param array $subscriptions The array of all available subscriptions. * * @return array Filter counts (filter => count). */ public static function get_filters_counts( $subscriptions = null ) { static $filters; if ( isset( $filters ) ) { return $filters; } $filters = array_fill_keys( array_keys( self::get_filters() ), 0 ); if ( empty( $subscriptions ) ) { return array(); } foreach ( $filters as $key => $count ) { $_subs = $subscriptions; self::_filter( $_subs, $key ); $filters[ $key ] = count( $_subs ); } return $filters; } /** * Get current filter. * * @return string The current filter. */ public static function get_current_filter() { $current_filter = 'all'; $valid_filters = array_keys( self::get_filters() ); if ( ! empty( $_GET['filter'] ) && in_array( wp_unslash( $_GET['filter'] ), $valid_filters ) ) { $current_filter = wc_clean( wp_unslash( $_GET['filter'] ) ); } return $current_filter; } /** * Filter an array of subscriptions by $filter. * * @param array $subscriptions The subscriptions array, passed by ref. * @param string $filter The filter. */ private static function _filter( &$subscriptions, $filter ) { switch ( $filter ) { case 'active': $subscriptions = wp_list_filter( $subscriptions, array( 'active' => true ) ); break; case 'inactive': $subscriptions = wp_list_filter( $subscriptions, array( 'active' => false ) ); break; case 'installed': foreach ( $subscriptions as $key => $subscription ) { if ( empty( $subscription['local']['installed'] ) ) { unset( $subscriptions[ $key ] ); } } break; case 'update-available': $subscriptions = wp_list_filter( $subscriptions, array( 'has_update' => true ) ); break; case 'expiring': $subscriptions = wp_list_filter( $subscriptions, array( 'expiring' => true ) ); break; case 'expired': $subscriptions = wp_list_filter( $subscriptions, array( 'expired' => true ) ); break; case 'download': foreach ( $subscriptions as $key => $subscription ) { if ( $subscription['local']['installed'] || $subscription['expired'] ) { unset( $subscriptions[ $key ] ); } } break; } } /** * Enqueue admin scripts and styles. */ public static function admin_enqueue_scripts() { $screen = get_current_screen(); $screen_id = $screen ? $screen->id : ''; $wc_screen_id = sanitize_title( __( 'WooCommerce', 'woocommerce' ) ); if ( $wc_screen_id . '_page_wc-addons' === $screen_id && isset( $_GET['section'] ) && 'helper' === $_GET['section'] ) { wp_enqueue_style( 'woocommerce-helper', WC()->plugin_url() . '/assets/css/helper.css', array(), Constants::get_constant( 'WC_VERSION' ) ); wp_style_add_data( 'woocommerce-helper', 'rtl', 'replace' ); } } /** * Various success/error notices. * * Runs during admin page render, so no headers/redirects here. * * @return array Array pairs of message/type strings with notices. */ private static function _get_return_notices() { $return_status = isset( $_GET['wc-helper-status'] ) ? wc_clean( wp_unslash( $_GET['wc-helper-status'] ) ) : null; $notices = array(); switch ( $return_status ) { case 'activate-success': $product_id = isset( $_GET['wc-helper-product-id'] ) ? absint( $_GET['wc-helper-product-id'] ) : 0; $subscription = self::_get_subscriptions_from_product_id( $product_id ); $notices[] = array( 'type' => 'updated', 'message' => sprintf( /* translators: %s: product name */ __( '%s activated successfully. You will now receive updates for this product.', 'woocommerce' ), '<strong>' . esc_html( $subscription['product_name'] ) . '</strong>' ), ); break; case 'activate-error': $product_id = isset( $_GET['wc-helper-product-id'] ) ? absint( $_GET['wc-helper-product-id'] ) : 0; $subscription = self::_get_subscriptions_from_product_id( $product_id ); $notices[] = array( 'type' => 'error', 'message' => sprintf( /* translators: %s: product name */ __( 'An error has occurred when activating %s. Please try again later.', 'woocommerce' ), '<strong>' . esc_html( $subscription['product_name'] ) . '</strong>' ), ); break; case 'deactivate-success': $product_id = isset( $_GET['wc-helper-product-id'] ) ? absint( $_GET['wc-helper-product-id'] ) : 0; $subscription = self::_get_subscriptions_from_product_id( $product_id ); $local = self::_get_local_from_product_id( $product_id ); $message = sprintf( /* translators: %s: product name */ __( 'Subscription for %s deactivated successfully. You will no longer receive updates for this product.', 'woocommerce' ), '<strong>' . esc_html( $subscription['product_name'] ) . '</strong>' ); if ( $local && is_plugin_active( $local['_filename'] ) && current_user_can( 'activate_plugins' ) ) { $deactivate_plugin_url = add_query_arg( array( 'page' => 'wc-addons', 'section' => 'helper', 'filter' => self::get_current_filter(), 'wc-helper-deactivate-plugin' => 1, 'wc-helper-product-id' => $subscription['product_id'], 'wc-helper-nonce' => wp_create_nonce( 'deactivate-plugin:' . $subscription['product_id'] ), ), admin_url( 'admin.php' ) ); $message = sprintf( /* translators: %1$s: product name, %2$s: deactivate url */ __( 'Subscription for %1$s deactivated successfully. You will no longer receive updates for this product. <a href="%2$s">Click here</a> if you wish to deactivate the plugin as well.', 'woocommerce' ), '<strong>' . esc_html( $subscription['product_name'] ) . '</strong>', esc_url( $deactivate_plugin_url ) ); } $notices[] = array( 'message' => $message, 'type' => 'updated', ); break; case 'deactivate-error': $product_id = isset( $_GET['wc-helper-product-id'] ) ? absint( $_GET['wc-helper-product-id'] ) : 0; $subscription = self::_get_subscriptions_from_product_id( $product_id ); $notices[] = array( 'type' => 'error', 'message' => sprintf( /* translators: %s: product name */ __( 'An error has occurred when deactivating the subscription for %s. Please try again later.', 'woocommerce' ), '<strong>' . esc_html( $subscription['product_name'] ) . '</strong>' ), ); break; case 'deactivate-plugin-success': $product_id = isset( $_GET['wc-helper-product-id'] ) ? absint( $_GET['wc-helper-product-id'] ) : 0; $subscription = self::_get_subscriptions_from_product_id( $product_id ); $notices[] = array( 'type' => 'updated', 'message' => sprintf( /* translators: %s: product name */ __( 'The extension %s has been deactivated successfully.', 'woocommerce' ), '<strong>' . esc_html( $subscription['product_name'] ) . '</strong>' ), ); break; case 'deactivate-plugin-error': $product_id = isset( $_GET['wc-helper-product-id'] ) ? absint( $_GET['wc-helper-product-id'] ) : 0; $subscription = self::_get_subscriptions_from_product_id( $product_id ); $notices[] = array( 'type' => 'error', 'message' => sprintf( /* translators: %1$s: product name, %2$s: plugins screen url */ __( 'An error has occurred when deactivating the extension %1$s. Please proceed to the <a href="%2$s">Plugins screen</a> to deactivate it manually.', 'woocommerce' ), '<strong>' . esc_html( $subscription['product_name'] ) . '</strong>', admin_url( 'plugins.php' ) ), ); break; case 'helper-connected': $notices[] = array( 'message' => __( 'You have successfully connected your store to WooCommerce.com', 'woocommerce' ), 'type' => 'updated', ); break; case 'helper-disconnected': $notices[] = array( 'message' => __( 'You have successfully disconnected your store from WooCommerce.com', 'woocommerce' ), 'type' => 'updated', ); break; case 'helper-refreshed': $notices[] = array( 'message' => __( 'Authentication and subscription caches refreshed successfully.', 'woocommerce' ), 'type' => 'updated', ); break; } return $notices; } /** * Various early-phase actions with possible redirects. * * @param object $screen WP screen object. */ public static function current_screen( $screen ) { $wc_screen_id = sanitize_title( __( 'WooCommerce', 'woocommerce' ) ); if ( $wc_screen_id . '_page_wc-addons' !== $screen->id ) { return; } if ( empty( $_GET['section'] ) || 'helper' !== $_GET['section'] ) { return; } if ( ! empty( $_GET['wc-helper-connect'] ) ) { return self::_helper_auth_connect(); } if ( ! empty( $_GET['wc-helper-return'] ) ) { return self::_helper_auth_return(); } if ( ! empty( $_GET['wc-helper-disconnect'] ) ) { return self::_helper_auth_disconnect(); } if ( ! empty( $_GET['wc-helper-refresh'] ) ) { return self::_helper_auth_refresh(); } if ( ! empty( $_GET['wc-helper-activate'] ) ) { return self::_helper_subscription_activate(); } if ( ! empty( $_GET['wc-helper-deactivate'] ) ) { return self::_helper_subscription_deactivate(); } if ( ! empty( $_GET['wc-helper-deactivate-plugin'] ) ) { return self::_helper_plugin_deactivate(); } } /** * Initiate a new OAuth connection. */ private static function _helper_auth_connect() { if ( empty( $_GET['wc-helper-nonce'] ) || ! wp_verify_nonce( wp_unslash( $_GET['wc-helper-nonce'] ), 'connect' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized self::log( 'Could not verify nonce in _helper_auth_connect' ); wp_die( 'Could not verify nonce' ); } $redirect_uri = add_query_arg( array( 'page' => 'wc-addons', 'section' => 'helper', 'wc-helper-return' => 1, 'wc-helper-nonce' => wp_create_nonce( 'connect' ), ), admin_url( 'admin.php' ) ); $request = WC_Helper_API::post( 'oauth/request_token', array( 'body' => array( 'home_url' => home_url(), 'redirect_uri' => $redirect_uri, ), ) ); $code = wp_remote_retrieve_response_code( $request ); if ( 200 !== $code ) { self::log( sprintf( 'Call to oauth/request_token returned a non-200 response code (%d)', $code ) ); wp_die( 'Something went wrong' ); } $secret = json_decode( wp_remote_retrieve_body( $request ) ); if ( empty( $secret ) ) { self::log( sprintf( 'Call to oauth/request_token returned an invalid body: %s', wp_remote_retrieve_body( $request ) ) ); wp_die( 'Something went wrong' ); } /** * Fires when the Helper connection process is initiated. */ do_action( 'woocommerce_helper_connect_start' ); $connect_url = add_query_arg( array( 'home_url' => rawurlencode( home_url() ), 'redirect_uri' => rawurlencode( $redirect_uri ), 'secret' => rawurlencode( $secret ), ), WC_Helper_API::url( 'oauth/authorize' ) ); wp_redirect( esc_url_raw( $connect_url ) ); die(); } /** * Return from WooCommerce.com OAuth flow. */ private static function _helper_auth_return() { if ( empty( $_GET['wc-helper-nonce'] ) || ! wp_verify_nonce( wp_unslash( $_GET['wc-helper-nonce'] ), 'connect' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized self::log( 'Could not verify nonce in _helper_auth_return' ); wp_die( 'Something went wrong' ); } // Bail if the user clicked deny. if ( ! empty( $_GET['deny'] ) ) { /** * Fires when the Helper connection process is denied/cancelled. */ do_action( 'woocommerce_helper_denied' ); wp_safe_redirect( admin_url( 'admin.php?page=wc-addons§ion=helper' ) ); die(); } // We do need a request token... if ( empty( $_GET['request_token'] ) ) { self::log( 'Request token not found in _helper_auth_return' ); wp_die( 'Something went wrong' ); } // Obtain an access token. $request = WC_Helper_API::post( 'oauth/access_token', array( 'body' => array( 'request_token' => wp_unslash( $_GET['request_token'] ), // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized 'home_url' => home_url(), ), ) ); $code = wp_remote_retrieve_response_code( $request ); if ( 200 !== $code ) { self::log( sprintf( 'Call to oauth/access_token returned a non-200 response code (%d)', $code ) ); wp_die( 'Something went wrong' ); } $access_token = json_decode( wp_remote_retrieve_body( $request ), true ); if ( ! $access_token ) { self::log( sprintf( 'Call to oauth/access_token returned an invalid body: %s', wp_remote_retrieve_body( $request ) ) ); wp_die( 'Something went wrong' ); } WC_Helper_Options::update( 'auth', array( 'access_token' => $access_token['access_token'], 'access_token_secret' => $access_token['access_token_secret'], 'site_id' => $access_token['site_id'], 'user_id' => get_current_user_id(), 'updated' => time(), ) ); // Obtain the connected user info. if ( ! self::_flush_authentication_cache() ) { self::log( 'Could not obtain connected user info in _helper_auth_return' ); WC_Helper_Options::update( 'auth', array() ); wp_die( 'Something went wrong.' ); } self::_flush_subscriptions_cache(); self::_flush_updates_cache(); /** * Fires when the Helper connection process has completed successfully. */ do_action( 'woocommerce_helper_connected' ); // Enable tracking when connected. if ( class_exists( 'WC_Tracker' ) ) { update_option( 'woocommerce_allow_tracking', 'yes' ); WC_Tracker::send_tracking_data( true ); } // If connecting through in-app purchase, redirects back to WooCommerce.com // for product installation. if ( ! empty( $_GET['wccom-install-url'] ) ) { wp_redirect( wp_unslash( $_GET['wccom-install-url'] ) ); exit; } wp_safe_redirect( add_query_arg( array( 'page' => 'wc-addons', 'section' => 'helper', 'wc-helper-status' => 'helper-connected', ), admin_url( 'admin.php' ) ) ); die(); } /** * Disconnect from WooCommerce.com, clear OAuth tokens. */ private static function _helper_auth_disconnect() { if ( empty( $_GET['wc-helper-nonce'] ) || ! wp_verify_nonce( wp_unslash( $_GET['wc-helper-nonce'] ), 'disconnect' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized self::log( 'Could not verify nonce in _helper_auth_disconnect' ); wp_die( 'Could not verify nonce' ); } /** * Fires when the Helper has been disconnected. */ do_action( 'woocommerce_helper_disconnected' ); $redirect_uri = add_query_arg( array( 'page' => 'wc-addons', 'section' => 'helper', 'wc-helper-status' => 'helper-disconnected', ), admin_url( 'admin.php' ) ); WC_Helper_API::post( 'oauth/invalidate_token', array( 'authenticated' => true, ) ); WC_Helper_Options::update( 'auth', array() ); WC_Helper_Options::update( 'auth_user_data', array() ); self::_flush_subscriptions_cache(); self::_flush_updates_cache(); wp_safe_redirect( $redirect_uri ); die(); } /** * User hit the Refresh button, clear all caches. */ private static function _helper_auth_refresh() { if ( empty( $_GET['wc-helper-nonce'] ) || ! wp_verify_nonce( wp_unslash( $_GET['wc-helper-nonce'] ), 'refresh' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized self::log( 'Could not verify nonce in _helper_auth_refresh' ); wp_die( 'Could not verify nonce' ); } /** * Fires when Helper subscriptions are refreshed. */ do_action( 'woocommerce_helper_subscriptions_refresh' ); $redirect_uri = add_query_arg( array( 'page' => 'wc-addons', 'section' => 'helper', 'filter' => self::get_current_filter(), 'wc-helper-status' => 'helper-refreshed', ), admin_url( 'admin.php' ) ); self::_flush_authentication_cache(); self::_flush_subscriptions_cache(); self::_flush_updates_cache(); wp_safe_redirect( $redirect_uri ); die(); } /** * Active a product subscription. */ private static function _helper_subscription_activate() { $product_key = isset( $_GET['wc-helper-product-key'] ) ? wc_clean( wp_unslash( $_GET['wc-helper-product-key'] ) ) : ''; $product_id = isset( $_GET['wc-helper-product-id'] ) ? absint( $_GET['wc-helper-product-id'] ) : 0; if ( empty( $_GET['wc-helper-nonce'] ) || ! wp_verify_nonce( wp_unslash( $_GET['wc-helper-nonce'] ), 'activate:' . $product_key ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized self::log( 'Could not verify nonce in _helper_subscription_activate' ); wp_die( 'Could not verify nonce' ); } // Activate subscription. $activation_response = WC_Helper_API::post( 'activate', array( 'authenticated' => true, 'body' => wp_json_encode( array( 'product_key' => $product_key, ) ), ) ); $activated = wp_remote_retrieve_response_code( $activation_response ) === 200; $body = json_decode( wp_remote_retrieve_body( $activation_response ), true ); if ( ! $activated && ! empty( $body['code'] ) && 'already_connected' === $body['code'] ) { $activated = true; } if ( $activated ) { /** * Fires when the Helper activates a product successfully. * * @param int $product_id Product ID being activated. * @param string $product_key Subscription product key. * @param array $activation_response The response object from wp_safe_remote_request(). */ do_action( 'woocommerce_helper_subscription_activate_success', $product_id, $product_key, $activation_response ); } else { /** * Fires when the Helper fails to activate a product. * * @param int $product_id Product ID being activated. * @param string $product_key Subscription product key. * @param array $activation_response The response object from wp_safe_remote_request(). */ do_action( 'woocommerce_helper_subscription_activate_error', $product_id, $product_key, $activation_response ); } // Attempt to activate this plugin. $local = self::_get_local_from_product_id( $product_id ); if ( $local && 'plugin' == $local['_type'] && current_user_can( 'activate_plugins' ) && ! is_plugin_active( $local['_filename'] ) ) { activate_plugin( $local['_filename'] ); } self::_flush_subscriptions_cache(); self::_flush_updates_cache(); $redirect_uri = add_query_arg( array( 'page' => 'wc-addons', 'section' => 'helper', 'filter' => self::get_current_filter(), 'wc-helper-status' => $activated ? 'activate-success' : 'activate-error', 'wc-helper-product-id' => $product_id, ), admin_url( 'admin.php' ) ); wp_safe_redirect( $redirect_uri ); die(); } /** * Deactivate a product subscription. */ private static function _helper_subscription_deactivate() { $product_key = isset( $_GET['wc-helper-product-key'] ) ? wc_clean( wp_unslash( $_GET['wc-helper-product-key'] ) ) : ''; $product_id = isset( $_GET['wc-helper-product-id'] ) ? absint( $_GET['wc-helper-product-id'] ) : 0; if ( empty( $_GET['wc-helper-nonce'] ) || ! wp_verify_nonce( wp_unslash( $_GET['wc-helper-nonce'] ), 'deactivate:' . $product_key ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized self::log( 'Could not verify nonce in _helper_subscription_deactivate' ); wp_die( 'Could not verify nonce' ); } $deactivation_response = WC_Helper_API::post( 'deactivate', array( 'authenticated' => true, 'body' => wp_json_encode( array( 'product_key' => $product_key, ) ), ) ); $code = wp_remote_retrieve_response_code( $deactivation_response ); $deactivated = 200 === $code; if ( $deactivated ) { /** * Fires when the Helper activates a product successfully. * * @param int $product_id Product ID being deactivated. * @param string $product_key Subscription product key. * @param array $deactivation_response The response object from wp_safe_remote_request(). */ do_action( 'woocommerce_helper_subscription_deactivate_success', $product_id, $product_key, $deactivation_response ); } else { self::log( sprintf( 'Deactivate API call returned a non-200 response code (%d)', $code ) ); /** * Fires when the Helper fails to activate a product. * * @param int $product_id Product ID being deactivated. * @param string $product_key Subscription product key. * @param array $deactivation_response The response object from wp_safe_remote_request(). */ do_action( 'woocommerce_helper_subscription_deactivate_error', $product_id, $product_key, $deactivation_response ); } self::_flush_subscriptions_cache(); $redirect_uri = add_query_arg( array( 'page' => 'wc-addons', 'section' => 'helper', 'filter' => self::get_current_filter(), 'wc-helper-status' => $deactivated ? 'deactivate-success' : 'deactivate-error', 'wc-helper-product-id' => $product_id, ), admin_url( 'admin.php' ) ); wp_safe_redirect( $redirect_uri ); die(); } /** * Deactivate a plugin. */ private static function _helper_plugin_deactivate() { $product_id = isset( $_GET['wc-helper-product-id'] ) ? absint( $_GET['wc-helper-product-id'] ) : 0; $deactivated = false; if ( empty( $_GET['wc-helper-nonce'] ) || ! wp_verify_nonce( wp_unslash( $_GET['wc-helper-nonce'] ), 'deactivate-plugin:' . $product_id ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized self::log( 'Could not verify nonce in _helper_plugin_deactivate' ); wp_die( 'Could not verify nonce' ); } if ( ! current_user_can( 'activate_plugins' ) ) { wp_die( 'You are not allowed to manage plugins on this site.' ); } $local = wp_list_filter( array_merge( self::get_local_woo_plugins(), self::get_local_woo_themes() ), array( '_product_id' => $product_id ) ); // Attempt to deactivate this plugin or theme. if ( ! empty( $local ) ) { $local = array_shift( $local ); if ( is_plugin_active( $local['_filename'] ) ) { deactivate_plugins( $local['_filename'] ); } $deactivated = ! is_plugin_active( $local['_filename'] ); } $redirect_uri = add_query_arg( array( 'page' => 'wc-addons', 'section' => 'helper', 'filter' => self::get_current_filter(), 'wc-helper-status' => $deactivated ? 'deactivate-plugin-success' : 'deactivate-plugin-error', 'wc-helper-product-id' => $product_id, ), admin_url( 'admin.php' ) ); wp_safe_redirect( $redirect_uri ); die(); } /** * Get a local plugin/theme entry from product_id. * * @param int $product_id The product id. * * @return array|bool The array containing the local plugin/theme data or false. */ private static function _get_local_from_product_id( $product_id ) { $local = wp_list_filter( array_merge( self::get_local_woo_plugins(), self::get_local_woo_themes() ), array( '_product_id' => $product_id ) ); if ( ! empty( $local ) ) { return array_shift( $local ); } return false; } /** * Checks whether current site has product subscription of a given ID. * * @since 3.7.0 * * @param int $product_id The product id. * * @return bool Returns true if product subscription exists, false otherwise. */ public static function has_product_subscription( $product_id ) { $subscription = self::_get_subscriptions_from_product_id( $product_id, true ); return ! empty( $subscription ); } /** * Get a subscription entry from product_id. If multiple subscriptions are * found with the same product id and $single is set to true, will return the * first one in the list, so you can use this method to get things like extension * name, version, etc. * * @param int $product_id The product id. * @param bool $single Whether to return a single subscription or all matching a product id. * * @return array|bool The array containing sub data or false. */ private static function _get_subscriptions_from_product_id( $product_id, $single = true ) { $subscriptions = wp_list_filter( self::get_subscriptions(), array( 'product_id' => $product_id ) ); if ( ! empty( $subscriptions ) ) { return $single ? array_shift( $subscriptions ) : $subscriptions; } return false; } /** * Obtain a list of data about locally installed Woo extensions. */ public static function get_local_woo_plugins() { if ( ! function_exists( 'get_plugins' ) ) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } $plugins = get_plugins(); /** * Check if plugins have WC headers, if not then clear cache and fetch again. * WC Headers will not be present if `wc_enable_wc_plugin_headers` hook was added after a `get_plugins` call -- for example when WC is activated/updated. * Also, get_plugins call is expensive so we should clear this cache very conservatively. */ if ( ! empty( $plugins ) && ! array_key_exists( 'Woo', current( $plugins ) ) ) { wp_clean_plugins_cache( false ); $plugins = get_plugins(); } $woo_plugins = array(); // Backwards compatibility for woothemes_queue_update(). $_compat = array(); if ( ! empty( $GLOBALS['woothemes_queued_updates'] ) ) { foreach ( $GLOBALS['woothemes_queued_updates'] as $_compat_plugin ) { $_compat[ $_compat_plugin->file ] = array( 'product_id' => $_compat_plugin->product_id, 'file_id' => $_compat_plugin->file_id, ); } } foreach ( $plugins as $filename => $data ) { if ( empty( $data['Woo'] ) && ! empty( $_compat[ $filename ] ) ) { $data['Woo'] = sprintf( '%d:%s', $_compat[ $filename ]['product_id'], $_compat[ $filename ]['file_id'] ); } if ( empty( $data['Woo'] ) ) { continue; } list( $product_id, $file_id ) = explode( ':', $data['Woo'] ); if ( empty( $product_id ) || empty( $file_id ) ) { continue; } $data['_filename'] = $filename; $data['_product_id'] = absint( $product_id ); $data['_file_id'] = $file_id; $data['_type'] = 'plugin'; $data['slug'] = dirname( $filename ); $woo_plugins[ $filename ] = $data; } return $woo_plugins; } /** * Get locally installed Woo themes. */ public static function get_local_woo_themes() { $themes = wp_get_themes(); $woo_themes = array(); foreach ( $themes as $theme ) { $header = $theme->get( 'Woo' ); // Backwards compatibility for theme_info.txt. if ( ! $header ) { $txt = $theme->get_stylesheet_directory() . '/theme_info.txt'; if ( is_readable( $txt ) ) { $txt = file_get_contents( $txt ); $txt = preg_split( '#\s#', $txt ); if ( count( $txt ) >= 2 ) { $header = sprintf( '%d:%s', $txt[0], $txt[1] ); } } } if ( empty( $header ) ) { continue; } list( $product_id, $file_id ) = explode( ':', $header ); if ( empty( $product_id ) || empty( $file_id ) ) { continue; } $data = array( 'Name' => $theme->get( 'Name' ), 'Version' => $theme->get( 'Version' ), 'Woo' => $header, '_filename' => $theme->get_stylesheet() . '/style.css', '_stylesheet' => $theme->get_stylesheet(), '_product_id' => absint( $product_id ), '_file_id' => $file_id, '_type' => 'theme', ); $woo_themes[ $data['_filename'] ] = $data; } return $woo_themes; } /** * Get the connected user's subscriptions. * * @return array */ public static function get_subscriptions() { $cache_key = '_woocommerce_helper_subscriptions'; $data = get_transient( $cache_key ); if ( false !== $data ) { return $data; } // Obtain the connected user info. $request = WC_Helper_API::get( 'subscriptions', array( 'authenticated' => true, ) ); if ( wp_remote_retrieve_response_code( $request ) !== 200 ) { set_transient( $cache_key, array(), 15 * MINUTE_IN_SECONDS ); return array(); } $data = json_decode( wp_remote_retrieve_body( $request ), true ); if ( empty( $data ) || ! is_array( $data ) ) { $data = array(); } set_transient( $cache_key, $data, 1 * HOUR_IN_SECONDS ); return $data; } /** * Runs when any plugin is activated. * * Depending on the activated plugin attempts to look through available * subscriptions and auto-activate one if possible, so the user does not * need to visit the Helper UI at all after installing a new extension. * * @param string $filename The filename of the activated plugin. */ public static function activated_plugin( $filename ) { $plugins = self::get_local_woo_plugins(); // Not a local woo plugin. if ( empty( $plugins[ $filename ] ) ) { return; } // Make sure we have a connection. $auth = WC_Helper_Options::get( 'auth' ); if ( empty( $auth ) ) { return; } $plugin = $plugins[ $filename ]; $product_id = $plugin['_product_id']; $subscriptions = self::_get_subscriptions_from_product_id( $product_id, false ); // No valid subscriptions for this product. if ( empty( $subscriptions ) ) { return; } $subscription = null; foreach ( $subscriptions as $_sub ) { // Don't attempt to activate expired subscriptions. if ( $_sub['expired'] ) { continue; } // No more sites available in this subscription. if ( $_sub['sites_max'] && $_sub['sites_active'] >= $_sub['sites_max'] ) { continue; } // Looks good. $subscription = $_sub; break; } // No valid subscription found. if ( ! $subscription ) { return; } $product_key = $subscription['product_key']; $activation_response = WC_Helper_API::post( 'activate', array( 'authenticated' => true, 'body' => wp_json_encode( array( 'product_key' => $product_key, ) ), ) ); $activated = wp_remote_retrieve_response_code( $activation_response ) === 200; $body = json_decode( wp_remote_retrieve_body( $activation_response ), true ); if ( ! $activated && ! empty( $body['code'] ) && 'already_connected' === $body['code'] ) { $activated = true; } if ( $activated ) { self::log( 'Auto-activated a subscription for ' . $filename ); /** * Fires when the Helper activates a product successfully. * * @param int $product_id Product ID being activated. * @param string $product_key Subscription product key. * @param array $activation_response The response object from wp_safe_remote_request(). */ do_action( 'woocommerce_helper_subscription_activate_success', $product_id, $product_key, $activation_response ); } else { self::log( 'Could not activate a subscription upon plugin activation: ' . $filename ); /** * Fires when the Helper fails to activate a product. * * @param int $product_id Product ID being activated. * @param string $product_key Subscription product key. * @param array $activation_response The response object from wp_safe_remote_request(). */ do_action( 'woocommerce_helper_subscription_activate_error', $product_id, $product_key, $activation_response ); } self::_flush_subscriptions_cache(); self::_flush_updates_cache(); } /** * Runs when any plugin is deactivated. * * When a user deactivates a plugin, attempt to deactivate any subscriptions * associated with the extension. * * @param string $filename The filename of the deactivated plugin. */ public static function deactivated_plugin( $filename ) { $plugins = self::get_local_woo_plugins(); // Not a local woo plugin. if ( empty( $plugins[ $filename ] ) ) { return; } // Make sure we have a connection. $auth = WC_Helper_Options::get( 'auth' ); if ( empty( $auth ) ) { return; } $plugin = $plugins[ $filename ]; $product_id = $plugin['_product_id']; $subscriptions = self::_get_subscriptions_from_product_id( $product_id, false ); $site_id = absint( $auth['site_id'] ); // No valid subscriptions for this product. if ( empty( $subscriptions ) ) { return; } $deactivated = 0; foreach ( $subscriptions as $subscription ) { // Don't touch subscriptions that aren't activated on this site. if ( ! in_array( $site_id, $subscription['connections'], true ) ) { continue; } $product_key = $subscription['product_key']; $deactivation_response = WC_Helper_API::post( 'deactivate', array( 'authenticated' => true, 'body' => wp_json_encode( array( 'product_key' => $product_key, ) ), ) ); if ( wp_remote_retrieve_response_code( $deactivation_response ) === 200 ) { $deactivated++; /** * Fires when the Helper activates a product successfully. * * @param int $product_id Product ID being deactivated. * @param string $product_key Subscription product key. * @param array $deactivation_response The response object from wp_safe_remote_request(). */ do_action( 'woocommerce_helper_subscription_deactivate_success', $product_id, $product_key, $deactivation_response ); } else { /** * Fires when the Helper fails to activate a product. * * @param int $product_id Product ID being deactivated. * @param string $product_key Subscription product key. * @param array $deactivation_response The response object from wp_safe_remote_request(). */ do_action( 'woocommerce_helper_subscription_deactivate_error', $product_id, $product_key, $deactivation_response ); } } if ( $deactivated ) { self::log( sprintf( 'Auto-deactivated %d subscription(s) for %s', $deactivated, $filename ) ); self::_flush_subscriptions_cache(); self::_flush_updates_cache(); } } /** * Various Helper-related admin notices. */ public static function admin_notices() { if ( apply_filters( 'woocommerce_helper_suppress_admin_notices', false ) ) { return; } $screen = get_current_screen(); $screen_id = $screen ? $screen->id : ''; if ( 'update-core' !== $screen_id ) { return; } // Don't nag if Woo doesn't have an update available. if ( ! self::_woo_core_update_available() ) { return; } // Add a note about available extension updates if Woo core has an update available. $notice = self::_get_extensions_update_notice(); if ( ! empty( $notice ) ) { echo '<div class="updated woocommerce-message"><p>' . $notice . '</p></div>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } } /** * Get an update notice if one or more Woo extensions has an update available. * * @return string|null The update notice or null if everything is up to date. */ private static function _get_extensions_update_notice() { $plugins = self::get_local_woo_plugins(); $updates = WC_Helper_Updater::get_update_data(); $available = 0; foreach ( $plugins as $data ) { if ( empty( $updates[ $data['_product_id'] ] ) ) { continue; } $product_id = $data['_product_id']; if ( version_compare( $updates[ $product_id ]['version'], $data['Version'], '>' ) ) { $available++; } } if ( ! $available ) { return; } return sprintf( /* translators: %1$s: helper url, %2$d: number of extensions */ _n( 'Note: You currently have <a href="%1$s">%2$d paid extension</a> which should be updated first before updating WooCommerce.', 'Note: You currently have <a href="%1$s">%2$d paid extensions</a> which should be updated first before updating WooCommerce.', $available, 'woocommerce' ), admin_url( 'admin.php?page=wc-addons§ion=helper' ), $available ); } /** * Whether WooCommerce has an update available. * * @return bool True if a Woo core update is available. */ private static function _woo_core_update_available() { $updates = get_site_transient( 'update_plugins' ); if ( empty( $updates->response ) ) { return false; } if ( empty( $updates->response['woocommerce/woocommerce.php'] ) ) { return false; } $data = $updates->response['woocommerce/woocommerce.php']; if ( version_compare( Constants::get_constant( 'WC_VERSION' ), $data->new_version, '>=' ) ) { return false; } return true; } /** * Flush subscriptions cache. */ public static function _flush_subscriptions_cache() { delete_transient( '_woocommerce_helper_subscriptions' ); } /** * Flush auth cache. */ public static function _flush_authentication_cache() { $request = WC_Helper_API::get( 'oauth/me', array( 'authenticated' => true, ) ); if ( wp_remote_retrieve_response_code( $request ) !== 200 ) { return false; } $user_data = json_decode( wp_remote_retrieve_body( $request ), true ); if ( ! $user_data ) { return false; } WC_Helper_Options::update( 'auth_user_data', array( 'name' => $user_data['name'], 'email' => $user_data['email'], ) ); return true; } /** * Flush updates cache. */ private static function _flush_updates_cache() { WC_Helper_Updater::flush_updates_cache(); } /** * Sort subscriptions by the product_name. * * @param array $a Subscription array. * @param array $b Subscription array. * * @return int */ public static function _sort_by_product_name( $a, $b ) { return strcmp( $a['product_name'], $b['product_name'] ); } /** * Sort subscriptions by the Name. * * @param array $a Product array. * @param array $b Product array. * * @return int */ public static function _sort_by_name( $a, $b ) { return strcmp( $a['Name'], $b['Name'] ); } /** * Log a helper event. * * @param string $message Log message. * @param string $level Optional, defaults to info, valid levels: emergency|alert|critical|error|warning|notice|info|debug. */ public static function log( $message, $level = 'info' ) { if ( ! Constants::is_true( 'WP_DEBUG' ) ) { return; } if ( ! isset( self::$log ) ) { self::$log = wc_get_logger(); } self::$log->log( $level, $message, array( 'source' => 'helper' ) ); } } WC_Helper::load(); PK ɥ3\YcS�: �: class-wc-helper-updater.phpnu �[��� <?php /** * The update helper for WooCommerce.com plugins. * * @class WC_Helper_Updater * @package WooCommerce\Admin\Helper */ if ( ! defined( 'ABSPATH' ) ) { exit; } /** * WC_Helper_Updater Class * * Contains the logic to fetch available updates and hook into Core's update * routines to serve WooCommerce.com-provided packages. */ class WC_Helper_Updater { /** * Loads the class, runs on init. */ public static function load() { add_action( 'pre_set_site_transient_update_plugins', array( __CLASS__, 'transient_update_plugins' ), 21, 1 ); add_action( 'pre_set_site_transient_update_themes', array( __CLASS__, 'transient_update_themes' ), 21, 1 ); add_action( 'upgrader_process_complete', array( __CLASS__, 'upgrader_process_complete' ) ); add_action( 'upgrader_pre_download', array( __CLASS__, 'block_expired_updates' ), 10, 2 ); } /** * Runs in a cron thread, or in a visitor thread if triggered * by _maybe_update_plugins(), or in an auto-update thread. * * @param object $transient The update_plugins transient object. * * @return object The same or a modified version of the transient. */ public static function transient_update_plugins( $transient ) { $update_data = self::get_update_data(); foreach ( WC_Helper::get_local_woo_plugins() as $plugin ) { if ( empty( $update_data[ $plugin['_product_id'] ] ) ) { continue; } $data = $update_data[ $plugin['_product_id'] ]; $filename = $plugin['_filename']; $item = array( 'id' => 'woocommerce-com-' . $plugin['_product_id'], 'slug' => 'woocommerce-com-' . $data['slug'], 'plugin' => $filename, 'new_version' => $data['version'], 'url' => $data['url'], 'package' => $data['package'], 'upgrade_notice' => $data['upgrade_notice'], ); if ( isset( $data['requires_php'] ) ) { $item['requires_php'] = $data['requires_php']; } // We don't want to deliver a valid upgrade package when their subscription has expired. // To avoid the generic "no_package" error that empty strings give, we will store an // indication of expiration for the `upgrader_pre_download` filter to error on. if ( ! self::_has_active_subscription( $plugin['_product_id'] ) ) { $item['package'] = 'woocommerce-com-expired-' . $plugin['_product_id']; } if ( version_compare( $plugin['Version'], $data['version'], '<' ) ) { $transient->response[ $filename ] = (object) $item; unset( $transient->no_update[ $filename ] ); } else { $transient->no_update[ $filename ] = (object) $item; unset( $transient->response[ $filename ] ); } } $translations = self::get_translations_update_data(); $transient->translations = array_merge( isset( $transient->translations ) ? $transient->translations : array(), $translations ); return $transient; } /** * Runs on pre_set_site_transient_update_themes, provides custom * packages for WooCommerce.com-hosted extensions. * * @param object $transient The update_themes transient object. * * @return object The same or a modified version of the transient. */ public static function transient_update_themes( $transient ) { $update_data = self::get_update_data(); foreach ( WC_Helper::get_local_woo_themes() as $theme ) { if ( empty( $update_data[ $theme['_product_id'] ] ) ) { continue; } $data = $update_data[ $theme['_product_id'] ]; $slug = $theme['_stylesheet']; $item = array( 'theme' => $slug, 'new_version' => $data['version'], 'url' => $data['url'], 'package' => '', ); if ( self::_has_active_subscription( $theme['_product_id'] ) ) { $item['package'] = $data['package']; } if ( version_compare( $theme['Version'], $data['version'], '<' ) ) { $transient->response[ $slug ] = $item; } else { unset( $transient->response[ $slug ] ); $transient->checked[ $slug ] = $data['version']; } } return $transient; } /** * Get update data for all extensions. * * Scans through all subscriptions for the connected user, as well * as all Woo extensions without a subscription, and obtains update * data for each product. * * @return array Update data {product_id => data} */ public static function get_update_data() { $payload = array(); // Scan subscriptions. foreach ( WC_Helper::get_subscriptions() as $subscription ) { $payload[ $subscription['product_id'] ] = array( 'product_id' => $subscription['product_id'], 'file_id' => '', ); } // Scan local plugins which may or may not have a subscription. foreach ( WC_Helper::get_local_woo_plugins() as $data ) { if ( ! isset( $payload[ $data['_product_id'] ] ) ) { $payload[ $data['_product_id'] ] = array( 'product_id' => $data['_product_id'], ); } $payload[ $data['_product_id'] ]['file_id'] = $data['_file_id']; } // Scan local themes. foreach ( WC_Helper::get_local_woo_themes() as $data ) { if ( ! isset( $payload[ $data['_product_id'] ] ) ) { $payload[ $data['_product_id'] ] = array( 'product_id' => $data['_product_id'], ); } $payload[ $data['_product_id'] ]['file_id'] = $data['_file_id']; } return self::_update_check( $payload ); } /** * Get translations updates informations. * * Scans through all subscriptions for the connected user, as well * as all Woo extensions without a subscription, and obtains update * data for each product. * * @return array Update data {product_id => data} */ public static function get_translations_update_data() { $payload = array(); $installed_translations = wp_get_installed_translations( 'plugins' ); $locales = array_values( get_available_languages() ); /** * Filters the locales requested for plugin translations. * * @since 3.7.0 * @since 4.5.0 The default value of the `$locales` parameter changed to include all locales. * * @param array $locales Plugin locales. Default is all available locales of the site. */ $locales = apply_filters( 'plugins_update_check_locales', $locales ); $locales = array_unique( $locales ); // No locales, the respone will be empty, we can return now. if ( empty( $locales ) ) { return array(); } // Scan local plugins which may or may not have a subscription. $plugins = WC_Helper::get_local_woo_plugins(); $active_woo_plugins = array_intersect( array_keys( $plugins ), get_option( 'active_plugins', array() ) ); /* * Use only plugins that are subscribed to the automatic translations updates. */ $active_for_translations = array_filter( $active_woo_plugins, function( $plugin ) use ( $plugins ) { return apply_filters( 'woocommerce_translations_updates_for_' . $plugins[ $plugin ]['slug'], false ); } ); // Nothing to check for, exit. if ( empty( $active_for_translations ) ) { return array(); } if ( wp_doing_cron() ) { $timeout = 30; } else { // Three seconds, plus one extra second for every 10 plugins. $timeout = 3 + (int) ( count( $active_for_translations ) / 10 ); } $request_body = array( 'locales' => $locales, 'plugins' => array(), ); foreach ( $active_for_translations as $active_plugin ) { $plugin = $plugins[ $active_plugin ]; $request_body['plugins'][ $plugin['slug'] ] = array( 'version' => $plugin['Version'] ); } $raw_response = wp_remote_post( 'https://translate.wordpress.com/api/translations-updates/woocommerce', array( 'body' => json_encode( $request_body ), 'headers' => array( 'Content-Type: application/json' ), 'timeout' => $timeout, ) ); // Something wrong happened on the translate server side. $response_code = wp_remote_retrieve_response_code( $raw_response ); if ( 200 !== $response_code ) { return array(); } $response = json_decode( wp_remote_retrieve_body( $raw_response ), true ); // API error, api returned but something was wrong. if ( array_key_exists( 'success', $response ) && false === $response['success'] ) { return array(); } $translations = array(); foreach ( $response['data'] as $plugin_name => $language_packs ) { foreach ( $language_packs as $language_pack ) { // Maybe we have this language pack already installed so lets check revision date. if ( array_key_exists( $plugin_name, $installed_translations ) && array_key_exists( $language_pack['wp_locale'], $installed_translations[ $plugin_name ] ) ) { $installed_translation_revision_time = new DateTime( $installed_translations[ $plugin_name ][ $language_pack['wp_locale'] ]['PO-Revision-Date'] ); $new_translation_revision_time = new DateTime( $language_pack['last_modified'] ); // Skip if translation language pack is not newer than what is installed already. if ( $new_translation_revision_time <= $installed_translation_revision_time ) { continue; } } $translations[] = array( 'type' => 'plugin', 'slug' => $plugin_name, 'language' => $language_pack['wp_locale'], 'version' => $language_pack['version'], 'updated' => $language_pack['last_modified'], 'package' => $language_pack['package'], 'autoupdate' => true, ); } } return $translations; } /** * Run an update check API call. * * The call is cached based on the payload (product ids, file ids). If * the payload changes, the cache is going to miss. * * @param array $payload Information about the plugin to update. * @return array Update data for each requested product. */ private static function _update_check( $payload ) { ksort( $payload ); $hash = md5( wp_json_encode( $payload ) ); $cache_key = '_woocommerce_helper_updates'; $data = get_transient( $cache_key ); if ( false !== $data ) { if ( hash_equals( $hash, $data['hash'] ) ) { return $data['products']; } } $data = array( 'hash' => $hash, 'updated' => time(), 'products' => array(), 'errors' => array(), ); $request = WC_Helper_API::post( 'update-check', array( 'body' => wp_json_encode( array( 'products' => $payload ) ), 'authenticated' => true, ) ); if ( wp_remote_retrieve_response_code( $request ) !== 200 ) { $data['errors'][] = 'http-error'; } else { $data['products'] = json_decode( wp_remote_retrieve_body( $request ), true ); } set_transient( $cache_key, $data, 12 * HOUR_IN_SECONDS ); return $data['products']; } /** * Check for an active subscription. * * Checks a given product id against all subscriptions on * the current site. Returns true if at least one active * subscription is found. * * @param int $product_id The product id to look for. * * @return bool True if active subscription found. */ private static function _has_active_subscription( $product_id ) { if ( ! isset( $auth ) ) { $auth = WC_Helper_Options::get( 'auth' ); } if ( ! isset( $subscriptions ) ) { $subscriptions = WC_Helper::get_subscriptions(); } if ( empty( $auth['site_id'] ) || empty( $subscriptions ) ) { return false; } // Check for an active subscription. foreach ( $subscriptions as $subscription ) { if ( $subscription['product_id'] != $product_id ) { continue; } if ( in_array( absint( $auth['site_id'] ), $subscription['connections'] ) ) { return true; } } return false; } /** * Get the number of products that have updates. * * @return int The number of products with updates. */ public static function get_updates_count() { $cache_key = '_woocommerce_helper_updates_count'; $count = get_transient( $cache_key ); if ( false !== $count ) { return $count; } // Don't fetch any new data since this function in high-frequency. if ( ! get_transient( '_woocommerce_helper_subscriptions' ) ) { return 0; } if ( ! get_transient( '_woocommerce_helper_updates' ) ) { return 0; } $count = 0; $update_data = self::get_update_data(); if ( empty( $update_data ) ) { set_transient( $cache_key, $count, 12 * HOUR_IN_SECONDS ); return $count; } // Scan local plugins. foreach ( WC_Helper::get_local_woo_plugins() as $plugin ) { if ( empty( $update_data[ $plugin['_product_id'] ] ) ) { continue; } if ( version_compare( $plugin['Version'], $update_data[ $plugin['_product_id'] ]['version'], '<' ) ) { $count++; } } // Scan local themes. foreach ( WC_Helper::get_local_woo_themes() as $theme ) { if ( empty( $update_data[ $theme['_product_id'] ] ) ) { continue; } if ( version_compare( $theme['Version'], $update_data[ $theme['_product_id'] ]['version'], '<' ) ) { $count++; } } set_transient( $cache_key, $count, 12 * HOUR_IN_SECONDS ); return $count; } /** * Return the updates count markup. * * @return string Updates count markup, empty string if no updates avairable. */ public static function get_updates_count_html() { $count = self::get_updates_count(); if ( ! $count ) { return ''; } $count_html = sprintf( '<span class="update-plugins count-%d"><span class="update-count">%d</span></span>', $count, number_format_i18n( $count ) ); return $count_html; } /** * Flushes cached update data. */ public static function flush_updates_cache() { delete_transient( '_woocommerce_helper_updates' ); delete_transient( '_woocommerce_helper_updates_count' ); delete_site_transient( 'update_plugins' ); delete_site_transient( 'update_themes' ); } /** * Fires when a user successfully updated a theme or a plugin. */ public static function upgrader_process_complete() { delete_transient( '_woocommerce_helper_updates_count' ); } /** * Hooked into the upgrader_pre_download filter in order to better handle error messaging around expired * plugin updates. Initially we were using an empty string, but the error message that no_package * results in does not fit the cause. * * @since 4.1.0 * @param bool $reply Holds the current filtered response. * @param string $package The path to the package file for the update. * @return false|WP_Error False to proceed with the update as normal, anything else to be returned instead of updating. */ public static function block_expired_updates( $reply, $package ) { // Don't override a reply that was set already. if ( false !== $reply ) { return $reply; } // Only for packages with expired subscriptions. if ( 0 !== strpos( $package, 'woocommerce-com-expired-' ) ) { return false; } return new WP_Error( 'woocommerce_subscription_expired', sprintf( // translators: %s: URL of WooCommerce.com subscriptions tab. __( 'Please visit the <a href="%s" target="_blank">subscriptions page</a> and renew to continue receiving updates.', 'woocommerce' ), esc_url( admin_url( 'admin.php?page=wc-addons§ion=helper' ) ) ) ); } } WC_Helper_Updater::load(); PK ɥ3\K�r� � views/html-section-account.phpnu �[��� <?php defined( 'ABSPATH' ) or exit(); ?> <a class="button button-update" href="<?php echo esc_url( $refresh_url ); ?>"><span class="dashicons dashicons-image-rotate"></span> <?php _e( 'Update', 'woocommerce' ); ?></a> <div class="user-info"> <header> <p><?php printf( __( 'Connected to WooCommerce.com', 'woocommerce' ) ); ?> <span class="chevron dashicons dashicons-arrow-down-alt2"></span></p> </header> <section> <p><?php echo get_avatar( $auth_user_data['email'], 48 ); ?> <?php echo esc_html( $auth_user_data['email'] ); ?></p> <div class="actions"> <a class="" href="https://woocommerce.com/my-account/my-subscriptions/" target="_blank"><span class="dashicons dashicons-admin-generic"></span> <?php _e( 'My Subscriptions', 'woocommerce' ); ?></a> <a class="" href="<?php echo esc_url( $disconnect_url ); ?>"><span class="dashicons dashicons-no"></span> <?php _e( 'Disconnect', 'woocommerce' ); ?></a> </div> </section> </div> PK ɥ3\Uݞ�� � views/html-oauth-start.phpnu �[��� <?php /** * Admin -> WooCommerce -> Extensions -> WooCommerce.com Subscriptions main page. * * @package WooCommerce\Views */ defined( 'ABSPATH' ) || exit(); ?> <div class="wrap woocommerce wc-addons-wrap wc-helper"> <h1 class="screen-reader-text"><?php esc_html_e( 'WooCommerce Extensions', 'woocommerce' ); ?></h1> <?php require WC_Helper::get_view_filename( 'html-section-notices.php' ); ?> <div class="start-container"> <div class="text"> <img src="<?php echo esc_url( WC()->plugin_url() . '/assets/images/woocommerce_logo.png' ); ?>" alt="<?php esc_attr_e( 'WooCommerce', 'woocommerce' ); ?>" style="width:180px;"> <?php if ( ! empty( $_GET['wc-helper-status'] ) && 'helper-disconnected' === $_GET['wc-helper-status'] ) : ?> <p><strong><?php esc_html_e( 'Sorry to see you go.', 'woocommerce' ); ?></strong> <?php esc_html_e( 'Feel free to reconnect again using the button below.', 'woocommerce' ); ?></p> <?php endif; ?> <h2><?php esc_html_e( 'Manage your subscriptions, get important product notifications, and updates, all from the convenience of your WooCommerce dashboard', 'woocommerce' ); ?></h2> <p><?php esc_html_e( 'Once connected, your WooCommerce.com purchases will be listed here.', 'woocommerce' ); ?></p> <p><a class="button button-primary button-helper-connect" href="<?php echo esc_url( $connect_url ); ?>"><?php esc_html_e( 'Connect', 'woocommerce' ); ?></a></p> </div> </div> </div> PK ɥ3\���+ �+ views/html-main.phpnu �[��� <?php /** * Helper main view * * @package WooCommerce\Helper */ ?> <?php defined( 'ABSPATH' ) || exit(); ?> <div class="wrap woocommerce wc-subscriptions-wrap wc-helper"> <h1 class="screen-reader-text"><?php esc_html_e( 'My Subscriptions', 'woocommerce' ); ?></h1> <?php require WC_Helper::get_view_filename( 'html-section-notices.php' ); ?> <div class="subscriptions-header"> <h2><?php esc_html_e( 'Subscriptions', 'woocommerce' ); ?></h2> <?php require WC_Helper::get_view_filename( 'html-section-account.php' ); ?> <p> <?php printf( wp_kses( /* translators: Introduction to list of WooCommerce.com extensions the merchant has subscriptions for. */ __( 'Below is a list of extensions available on your WooCommerce.com account. To receive extension updates please make sure the extension is installed, and its subscription activated and connected to your WooCommerce.com account. Extensions can be activated from the <a href="%s">Plugins</a> screen.', 'woocommerce' ), array( 'a' => array( 'href' => array(), ), ) ), esc_url( admin_url( 'plugins.php' ) ) ); ?> </p> </div> <ul class="subscription-filter"> <label><?php esc_html_e( 'Sort by:', 'woocommerce' ); ?> <span class="chevron dashicons dashicons-arrow-up-alt2"></span></label> <?php $filters = array_keys( WC_Helper::get_filters() ); $last_filter = array_pop( $filters ); $current_filter = WC_Helper::get_current_filter(); $counts = WC_Helper::get_filters_counts(); ?> <?php foreach ( WC_Helper::get_filters() as $key => $label ) : // Don't show empty filters. if ( empty( $counts[ $key ] ) ) { continue; } $url = admin_url( 'admin.php?page=wc-addons§ion=helper&filter=' . $key ); $class_html = $current_filter === $key ? 'class="current"' : ''; ?> <li> <a <?php echo esc_html( $class_html ); ?> href="<?php echo esc_url( $url ); ?>"> <?php echo esc_html( $label ); ?> <span class="count">(<?php echo absint( $counts[ $key ] ); ?>)</span> </a> </li> <?php endforeach; ?> </ul> <table class="wp-list-table widefat fixed striped"> <?php if ( ! empty( $subscriptions ) ) : ?> <?php foreach ( $subscriptions as $subscription ) : ?> <tbody> <tr class="wp-list-table__row is-ext-header"> <td class="wp-list-table__ext-details"> <div class="wp-list-table__ext-title"> <a href="<?php echo esc_url( $subscription['product_url'] ); ?>" target="_blank"> <?php echo esc_html( $subscription['product_name'] ); ?> </a> </div> <div class="wp-list-table__ext-description"> <?php if ( $subscription['lifetime'] ) : ?> <span class="renews"> <?php esc_html_e( 'Lifetime Subscription', 'woocommerce' ); ?> </span> <?php elseif ( $subscription['expired'] ) : ?> <span class="renews"> <strong><?php esc_html_e( 'Expired :(', 'woocommerce' ); ?></strong> <?php echo esc_html( date_i18n( 'F jS, Y', $subscription['expires'] ) ); ?> </span> <?php elseif ( $subscription['autorenew'] ) : ?> <span class="renews"> <?php esc_html_e( 'Auto renews on:', 'woocommerce' ); ?> <?php echo esc_html( date_i18n( 'F jS, Y', $subscription['expires'] ) ); ?> </span> <?php elseif ( $subscription['expiring'] ) : ?> <span class="renews"> <strong><?php esc_html_e( 'Expiring soon!', 'woocommerce' ); ?></strong> <?php echo esc_html( date_i18n( 'F jS, Y', $subscription['expires'] ) ); ?> </span> <?php else : ?> <span class="renews"> <?php esc_html_e( 'Expires on:', 'woocommerce' ); ?> <?php echo esc_html( date_i18n( 'F jS, Y', $subscription['expires'] ) ); ?> </span> <?php endif; ?> <br/> <span class="subscription"> <?php if ( ! $subscription['active'] && $subscription['maxed'] ) { /* translators: %1$d: sites active, %2$d max sites active */ printf( esc_html__( 'Subscription: Not available - %1$d of %2$d already in use', 'woocommerce' ), absint( $subscription['sites_active'] ), absint( $subscription['sites_max'] ) ); } elseif ( $subscription['sites_max'] > 0 ) { /* translators: %1$d: sites active, %2$d max sites active */ printf( esc_html__( 'Subscription: Using %1$d of %2$d sites available', 'woocommerce' ), absint( $subscription['sites_active'] ), absint( $subscription['sites_max'] ) ); } else { esc_html_e( 'Subscription: Unlimited', 'woocommerce' ); } // Check shared. if ( ! empty( $subscription['is_shared'] ) && ! empty( $subscription['owner_email'] ) ) { /* translators: Email address of person who shared the subscription. */ printf( '</br>' . esc_html__( 'Shared by %s', 'woocommerce' ), esc_html( $subscription['owner_email'] ) ); } elseif ( isset( $subscription['master_user_email'] ) ) { /* translators: Email address of person who shared the subscription. */ printf( '</br>' . esc_html__( 'Shared by %s', 'woocommerce' ), esc_html( $subscription['master_user_email'] ) ); } ?> </span> </div> </td> <td class="wp-list-table__ext-actions"> <?php if ( ! $subscription['active'] && $subscription['maxed'] ) : ?> <a class="button" href="https://woocommerce.com/my-account/my-subscriptions/" target="_blank"><?php esc_html_e( 'Upgrade', 'woocommerce' ); ?></a> <?php elseif ( ! $subscription['local']['installed'] && ! $subscription['expired'] ) : ?> <a class="button <?php echo empty( $subscription['download_primary'] ) ? 'button-secondary' : ''; ?>" href="<?php echo esc_url( $subscription['download_url'] ); ?>" target="_blank"><?php esc_html_e( 'Download', 'woocommerce' ); ?></a> <?php elseif ( $subscription['active'] ) : ?> <span class="form-toggle__wrapper"> <a href="<?php echo esc_url( $subscription['deactivate_url'] ); ?>" class="form-toggle active is-compact" role="link" aria-checked="true"><?php esc_html_e( 'Active', 'woocommerce' ); ?></a> <label class="form-toggle__label" for="activate-extension"> <span class="form-toggle__label-content"> <label for="activate-extension"><?php esc_html_e( 'Active', 'woocommerce' ); ?></label> </span> <span class="form-toggle__switch"></span> </label> </span> <?php elseif ( ! $subscription['expired'] ) : ?> <span class="form-toggle__wrapper"> <a href="<?php echo esc_url( $subscription['activate_url'] ); ?>" class="form-toggle is-compact" role="link" aria-checked="false"><?php esc_html_e( 'Inactive', 'woocommerce' ); ?></a> <label class="form-toggle__label" for="activate-extension"> <span class="form-toggle__label-content"> <label for="activate-extension"><?php esc_html_e( 'Inactive', 'woocommerce' ); ?></label> </span> <span class="form-toggle__switch"></span> </label> </span> <?php else : ?> <span class="form-toggle__wrapper"> <span class="form-toggle disabled is-compact"><?php esc_html_e( 'Inactive', 'woocommerce' ); ?></span> <label class="form-toggle__label" for="activate-extension"> <span class="form-toggle__label-content"> <label for="activate-extension"><?php esc_html_e( 'Inactive', 'woocommerce' ); ?></label> </span> </label> </span> <?php endif; ?> </td> </tr> <?php foreach ( $subscription['actions'] as $subscription_action ) : ?> <tr class="wp-list-table__row wp-list-table__ext-updates"> <td class="wp-list-table__ext-status <?php echo sanitize_html_class( $subscription_action['status'] ); ?>"> <p><span class="dashicons <?php echo sanitize_html_class( $subscription_action['icon'] ); ?>"></span> <?php echo wp_kses_post( $subscription_action['message'] ); ?> </p> </td> <td class="wp-list-table__ext-actions"> <?php if ( ! empty( $subscription_action['button_label'] ) && ! empty( $subscription_action['button_url'] ) ) : ?> <a class="button <?php echo empty( $subscription_action['primary'] ) ? 'button-secondary' : ''; ?>" href="<?php echo esc_url( $subscription_action['button_url'] ); ?>"><?php echo esc_html( $subscription_action['button_label'] ); ?></a> <?php endif; ?> </td> </tr> <?php endforeach; ?> </tbody> <?php endforeach; ?> <?php else : ?> <tr> <td colspan="3"><em><?php esc_html_e( 'Could not find any subscriptions on your WooCommerce.com account', 'woocommerce' ); ?></td> </tr> <?php endif; ?> </tbody> </table> <?php if ( ! empty( $no_subscriptions ) ) : ?> <h2><?php esc_html_e( 'Installed Extensions without a Subscription', 'woocommerce' ); ?></h2> <p>Below is a list of WooCommerce.com products available on your site - but are either out-dated or do not have a valid subscription.</p> <table class="wp-list-table widefat fixed striped"> <?php /* Extensions without a subscription. */ ?> <?php foreach ( $no_subscriptions as $filename => $data ) : ?> <tbody> <tr class="wp-list-table__row is-ext-header"> <td class="wp-list-table__ext-details color-bar autorenews"> <div class="wp-list-table__ext-title"> <a href="<?php echo esc_url( $data['_product_url'] ); ?>" target="_blank"><?php echo esc_html( $data['Name'] ); ?></a> </div> <div class="wp-list-table__ext-description"> </div> </td> <td class="wp-list-table__ext-actions"> <span class="form-toggle__wrapper"> <span class="form-toggle disabled is-compact" ><?php esc_html_e( 'Inactive', 'woocommerce' ); ?></span> <label class="form-toggle__label" for="activate-extension"> <span class="form-toggle__label-content"> <label for="activate-extension"><?php esc_html_e( 'Inactive', 'woocommerce' ); ?></label> </span> </label> </span> </td> </tr> <?php foreach ( $data['_actions'] as $subscription_action ) : ?> <tr class="wp-list-table__row wp-list-table__ext-updates"> <td class="wp-list-table__ext-status <?php echo sanitize_html_class( $subscription_action['status'] ); ?>"> <p><span class="dashicons <?php echo sanitize_html_class( $subscription_action['icon'] ); ?>"></span> <?php echo wp_kses( $subscription_action['message'], array( 'a' => array( 'href' => array(), 'title' => array(), ), 'br' => array(), 'em' => array(), 'strong' => array(), ) ); ?> </p> </td> <td class="wp-list-table__ext-actions"> <a class="button" href="<?php echo esc_url( $subscription_action['button_url'] ); ?>" target="_blank"><?php echo esc_html( $subscription_action['button_label'] ); ?></a> </td> </tr> <?php endforeach; ?> </tbody> <?php endforeach; ?> </table> <?php endif; ?> </div> PK ɥ3\�6� � views/html-section-nav.phpnu �[��� <?php /** * Helper admin navigation. * * @package WooCommerce\Helper * * @deprecated 5.7.0 */ defined( 'ABSPATH' ) || exit(); ?> <nav class="nav-tab-wrapper woo-nav-tab-wrapper"> <a href="<?php echo esc_url( admin_url( 'admin.php?page=wc-addons' ) ); ?>" class="nav-tab"><?php esc_html_e( 'Browse Extensions', 'woocommerce' ); ?></a> <?php $count_html = WC_Helper_Updater::get_updates_count_html(); /* translators: %s: WooCommerce.com Subscriptions tab count HTML. */ $menu_title = sprintf( __( 'WooCommerce.com Subscriptions %s', 'woocommerce' ), $count_html ); ?> <a href="<?php echo esc_url( admin_url( 'admin.php?page=wc-addons§ion=helper' ) ); ?>" class="nav-tab nav-tab-active"><?php echo wp_kses_post( $menu_title ); ?></a> </nav> PK ɥ3\$�J�� � views/html-helper-compat.phpnu �[��� <?php defined( 'ABSPATH' ) or exit(); ?> <div class="wrap"> <h1><?php _e( 'Looking for the WooCommerce Helper?', 'woocommerce' ); ?></h1> <p><?php printf( __( 'We\'ve made things simpler and easier to manage moving forward. From now on you can manage all your WooCommerce purchases directly from the Extensions menu within the WooCommerce plugin itself. <a href="%s">View and manage</a> your extensions now.', 'woocommerce' ), esc_url( $helper_url ) ); ?></p> </div> PK ɥ3\�A��� � views/html-section-notices.phpnu �[��� <?php defined( 'ABSPATH' ) or exit(); ?> <?php foreach ( $notices as $notice ) : ?> <div class="notice <?php echo sanitize_html_class( $notice['type'] ); ?>"> <?php echo wpautop( $notice['message'] ); ?> </div> <?php endforeach; ?> PK ɥ3\�SDZh h class-wc-helper-options.phpnu �[��� PK ɥ3\)�q$7 7 � class-wc-helper-api.phpnu �[��� PK ɥ3\�{ |� � 1 class-wc-helper-compat.phpnu �[��� PK ɥ3\��1qp p :/ class-wc-helper-plugin-info.phpnu �[��� PK ɥ3\:a�B� B� �6 class-wc-helper.phpnu �[��� PK ɥ3\YcS�: �: ~ class-wc-helper-updater.phpnu �[��� PK ɥ3\K�r� � r? views/html-section-account.phpnu �[��� PK ɥ3\Uݞ�� � wC views/html-oauth-start.phpnu �[��� PK ɥ3\���+ �+ qI views/html-main.phpnu �[��� PK ɥ3\�6� � �u views/html-section-nav.phpnu �[��� PK ɥ3\$�J�� � �x views/html-helper-compat.phpnu �[��� PK ɥ3\�A��� � �z views/html-section-notices.phpnu �[��� PK 8 +|
| ver. 1.4 |
Github
|
.
| PHP 8.2.29 | Генерация страницы: 0 |
proxy
|
phpinfo
|
Настройка