123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597 |
- <?php
- if ( ! defined( 'ABSPATH' ) ) {
- exit; // Exit if accessed directly
- }
- if ( ! class_exists( 'acf_pro_updates' ) ) :
- class acf_pro_updates {
- /**
- * __construct
- *
- * Initialize filters, action, variables and includes
- *
- * @type function
- * @date 23/06/12
- * @since 5.0.0
- */
- function __construct() {
- // actions
- add_action( 'init', array( $this, 'init' ), 20 );
- }
- /**
- * init
- *
- * description
- *
- * @type function
- * @date 10/4/17
- * @since 5.5.10
- */
- function init() {
- // bail early if no show_updates.
- if ( ! acf_get_setting( 'show_updates' ) ) {
- return;
- }
- // bail early if not a plugin (included in theme).
- if ( ! acf_is_plugin_active() ) {
- return;
- }
- // register update
- acf_register_plugin_update(
- array(
- 'id' => 'pro',
- 'key' => acf_pro_get_license_key(),
- 'slug' => acf_get_setting( 'slug' ),
- 'basename' => acf_get_setting( 'basename' ),
- 'version' => acf_get_setting( 'version' ),
- )
- );
- add_action( 'admin_init', 'acf_pro_check_defined_license', 20 );
- add_action( 'current_screen', 'acf_pro_display_activation_error', 30 );
- // admin
- if ( is_admin() ) {
- add_action( 'in_plugin_update_message-' . acf_get_setting( 'basename' ), array( $this, 'modify_plugin_update_message' ), 10, 2 );
- }
- }
- /*
- * modify_plugin_update_message
- *
- * Displays an update message for plugin list screens.
- *
- * @type function
- * @date 14/06/2016
- * @since 5.3.8
- *
- * @param $message (string)
- * @param $plugin_data (array)
- * @param $r (object)
- * @return $message
- */
- function modify_plugin_update_message( $plugin_data, $response ) {
- // bail early if has key
- if ( acf_pro_get_license_key() ) {
- return;
- }
- // display message
- echo '<br />' . sprintf( __( 'To enable updates, please enter your license key on the <a href="%1$s">Updates</a> page. If you don\'t have a licence key, please see <a href="%2$s" target="_blank">details & pricing</a>.', 'acf' ), admin_url( 'edit.php?post_type=acf-field-group&page=acf-settings-updates' ), acf_add_url_utm_tags( 'https://www.advancedcustomfields.com/pro/', 'ACF upgrade', 'updates' ) );
- }
- }
- // initialize
- new acf_pro_updates();
- endif; // class_exists check
- /**
- * Check if a license is defined in wp-config.php and requires activation.
- * Also checks if the license key has been changed and reactivates.
- *
- * @date 29/09/2021
- * @since 5.11.0
- */
- function acf_pro_check_defined_license() {
- // Bail early if the license is not defined in wp-config.
- if ( ! defined( 'ACF_PRO_LICENSE' ) || empty( ACF_PRO_LICENSE ) || ! is_string( ACF_PRO_LICENSE ) ) {
- return;
- }
- // Bail early if no show_admin.
- if ( ! acf_get_setting( 'show_admin' ) ) {
- return;
- }
- // Check if we've been asked to clear the transient to retry activation.
- if ( acf_verify_nonce( 'acf_delete_activation_transient' ) || ( isset( $_REQUEST['acf_retry_nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_REQUEST['acf_retry_nonce'] ) ), 'acf_retry_activation' ) ) ) {
- delete_transient( 'acf_activation_error' );
- } else {
- // If we've failed activation recently, check if the key has been changed, otherwise return.
- $activation_data = acf_pro_get_activation_failure_transient();
- if ( $activation_data && $activation_data['license'] === ACF_PRO_LICENSE ) {
- return;
- }
- }
- // If we're already activated, check if the defined license key has changed.
- $license = acf_pro_get_license();
- if ( $license ) {
- // Check the saved license key against the defined key.
- if ( acf_pro_get_license_key() !== ACF_PRO_LICENSE ) {
- // Deactivate if the key has changed.
- $deactivation_response = acf_pro_deactivate_license( true );
- // A connection error occurred while trying to deactivate.
- if ( is_wp_error( $deactivation_response ) ) {
- return acf_pro_set_activation_failure_transient( __( '<b>ACF Activation Error</b>. Your defined license key has changed, but an error occurred when connecting to activation server', 'acf' ) . ' <span class="description">(' . esc_html( $deactivation_response->get_error_message() ) . ').</span>', ACF_PRO_LICENSE );
- // A deactivation error occurred. Display the message returned by our API.
- } elseif ( ! $deactivation_response['success'] ) {
- return acf_pro_set_activation_failure_transient( __( '<b>ACF Activation Error</b>. Your defined license key has changed, but an error occurred when deactivating your old licence', 'acf' ) . ' <span class="description">(' . $deactivation_response['message'] . ').</span>', ACF_PRO_LICENSE );
- }
- } else {
- // Check if the licence has been marked as invalid during the update check.
- $basename = acf_get_setting( 'basename' );
- $update = acf_updates()->get_plugin_update( $basename );
- if ( isset( $update['license_valid'] ) && ! $update['license_valid'] ) {
- // Our site is not activated, so remove the license.
- acf_pro_update_license( '' );
- } else {
- // License key hasn't changed, we are activated and licence is still valid, return.
- return;
- }
- }
- }
- // Activate the defined key license.
- $activation_response = acf_pro_activate_license( ACF_PRO_LICENSE, true );
- $error_text = false;
- // A connection error occurred during activation
- if ( is_wp_error( $activation_response ) ) {
- $error_text = __( '<b>ACF Activation Error</b>. An error occurred when connecting to activation server', 'acf' ) . ' <span class="description">(' . esc_html( $activation_response->get_error_message() ) . ').</span>';
- // A deactivation error occurred. Display the message returned by our API.
- } elseif ( ! $activation_response['success'] ) {
- $error_text = __( '<b>ACF Activation Error</b>', 'acf' ) . ': <span class="description">' . $activation_response['message'] . '.</span>';
- } else {
- // Delete any previously saved activation error transient.
- delete_transient( 'acf_activation_error' );
- // Prefix connect API success message with ACF as we could be outside of the ACF admin and display message.
- acf_add_admin_notice( '<b>ACF </b>' . acf_esc_html( $activation_response['message'] ), 'success' );
- return;
- }
- return acf_pro_set_activation_failure_transient( $error_text, ACF_PRO_LICENSE );
- }
- /**
- * Set the automatic activation failure transient
- *
- * @date 11/10/2021
- * @since 5.11.0
- *
- * @param string $error_text string containing the error text message.
- * @param string $license_key the license key that was used during the failed activation.
- *
- * @return void
- */
- function acf_pro_set_activation_failure_transient( $error_text, $license_key ) {
- set_transient(
- 'acf_activation_error',
- array(
- 'error' => $error_text,
- 'license' => $license_key,
- ),
- HOUR_IN_SECONDS
- );
- }
- /**
- * Get the automatic activation failure transient
- *
- * @date 11/10/2021
- * @since 5.11.0
- *
- * @return array|false Activation failure transient array, or false if it's not set.
- */
- function acf_pro_get_activation_failure_transient() {
- return get_transient( 'acf_activation_error' );
- }
- /**
- * Display the stored activation error
- *
- * @date 11/10/2021
- * @since 5.11.0
- */
- function acf_pro_display_activation_error() {
- // Return if we're not in admin.
- if ( ! is_admin() ) {
- return;
- }
- // Return if the current user cannot view ACF settings.
- if ( ! acf_current_user_can_admin() ) {
- return;
- }
- // Check if the transient exists.
- $activation_data = acf_pro_get_activation_failure_transient();
- // Return if the transient does not exist.
- if ( ! $activation_data ) {
- return;
- }
- // Check if the license key is defined. If not, delete the transient.
- if ( ! defined( 'ACF_PRO_LICENSE' ) || empty( ACF_PRO_LICENSE ) || ! is_string( ACF_PRO_LICENSE ) ) {
- delete_transient( 'acf_activation_error' );
- return;
- }
- // Append a retry link if we're not already on the settings page.
- global $plugin_page;
- if ( ! $plugin_page || 'acf-settings-updates' !== $plugin_page ) {
- $nonce = wp_create_nonce( 'acf_retry_activation' );
- $check_again_url = admin_url( 'edit.php?post_type=acf-field-group&page=acf-settings-updates&acf_retry_nonce=' . $nonce );
- $activation_data['error'] = $activation_data['error'] . ' <a href="' . $check_again_url . '">' . __( 'Check Again', 'acf' ) . '</a>';
- }
- // Add a non-dismissible error message with the activation error.
- acf_add_admin_notice( acf_esc_html( $activation_data['error'] ), 'error', false );
- }
- /**
- * This function will return the license
- *
- * @type function
- * @date 20/09/2016
- * @since 5.4.0
- *
- * @return $license Activated license array
- */
- function acf_pro_get_license() {
- // get option
- $license = get_option( 'acf_pro_license' );
- // bail early if no value
- if ( ! $license ) {
- return false;
- }
- // decode
- $license = maybe_unserialize( base64_decode( $license ) );
- // bail early if corrupt
- if ( ! is_array( $license ) ) {
- return false;
- }
- // return
- return $license;
- }
- /**
- * An ACF specific getter to replace `home_url` in our licence checks to ensure we can avoid third party filters.
- *
- * @since 6.0.1
- *
- * @return string $home_url The output from home_url, sans known third party filters which cause licence activation issues.
- */
- function acf_get_home_url() {
- // Disable WPML's home url overrides for our license check.
- add_filter( 'wpml_get_home_url', 'acf_licence_wpml_intercept', 99, 2 );
- $home_url = home_url();
- // Re-enable WPML's home url overrides.
- remove_filter( 'wpml_get_home_url', 'acf_licence_wpml_intercept', 99 );
- return $home_url;
- }
- /**
- * Return the original home url inside ACF's home url getter.
- *
- * @since 6.0.1
- *
- * @param string $home_url the WPML converted home URL.
- * @param string $url the original home URL.
- *
- * @return string $url
- */
- function acf_licence_wpml_intercept( $home_url, $url ) {
- return $url;
- }
- /**
- * This function will return the license key
- *
- * @type function
- * @date 20/09/2016
- * @since 5.4.0
- *
- * @param boolean $skip_url_check Skip the check of the current site url.
- * @return string $license_key
- */
- function acf_pro_get_license_key( $skip_url_check = false ) {
- $license = acf_pro_get_license();
- $home_url = acf_get_home_url();
- // bail early if empty
- if ( ! $license || ! $license['key'] ) {
- return false;
- }
- // bail early if url has changed
- if ( ! $skip_url_check && acf_strip_protocol( $license['url'] ) !== acf_strip_protocol( $home_url ) ) {
- return false;
- }
- // return
- return $license['key'];
- }
- /**
- * This function will update the DB license
- *
- * @type function
- * @date 20/09/2016
- * @since 5.4.0
- *
- * @param string $key The license key
- * @return bool The result of the update_option call
- */
- function acf_pro_update_license( $key = '' ) {
- // vars
- $value = '';
- // key
- if ( $key ) {
- // vars
- $data = array(
- 'key' => $key,
- 'url' => acf_get_home_url(),
- );
- // encode
- $value = base64_encode( maybe_serialize( $data ) );
- }
- // re-register update (key has changed)
- acf_register_plugin_update(
- array(
- 'id' => 'pro',
- 'key' => $key,
- 'slug' => acf_get_setting( 'slug' ),
- 'basename' => acf_get_setting( 'basename' ),
- 'version' => acf_get_setting( 'version' ),
- )
- );
- // update
- return update_option( 'acf_pro_license', $value );
- }
- /**
- * Get count of registered ACF Blocks
- *
- * @return int
- */
- function acf_pro_get_registered_block_count() {
- return acf_get_store( 'block-types' )->count();
- }
- /**
- * Activates the submitted license key
- * Formally ACF_Admin_Updates::activate_pro_licence since 5.0.0
- *
- * @date 30/09/2021
- * @since 5.11.0
- *
- * @param string $license_key License key to activate
- * @param boolean $silent Return errors rather than displaying them
- * @return mixed $response A wp-error instance, or an array with a boolean success key, and string message key
- */
- function acf_pro_activate_license( $license_key, $silent = false ) {
- // Connect to API.
- $post = array(
- 'acf_license' => trim( $license_key ),
- 'acf_version' => acf_get_setting( 'version' ),
- 'wp_name' => get_bloginfo( 'name' ),
- 'wp_url' => acf_get_home_url(),
- 'wp_version' => get_bloginfo( 'version' ),
- 'wp_language' => get_bloginfo( 'language' ),
- 'wp_timezone' => get_option( 'timezone_string' ),
- 'php_version' => PHP_VERSION,
- 'block_count' => acf_pro_get_registered_block_count(),
- );
- $response = acf_updates()->request( 'v2/plugins/activate?p=pro', $post );
- // Check response is expected JSON array (not string).
- if ( is_string( $response ) ) {
- $response = new WP_Error( 'server_error', esc_html( $response ) );
- }
- // Display error.
- if ( is_wp_error( $response ) ) {
- if ( ! $silent ) {
- display_wp_activation_error( $response );
- }
- return $response;
- }
- $success = false;
- // On success.
- if ( $response['status'] == 1 ) {
- // Update license.
- acf_pro_update_license( $response['license'] );
- // Refresh plugins transient to fetch new update data.
- acf_updates()->refresh_plugins_transient();
- // Show notice.
- if ( ! $silent ) {
- acf_add_admin_notice( acf_esc_html( $response['message'] ), 'success' );
- }
- $success = true;
- // On failure.
- } else {
- // Show notice.
- if ( ! $silent ) {
- acf_add_admin_notice( acf_esc_html( $response['message'] ), 'warning' );
- }
- }
- // Return status array for automated activation error notices
- return array(
- 'success' => $success,
- 'message' => $response['message'],
- );
- }
- /**
- * Deactivates the registered license key.
- * Formally ACF_Admin_Updates::deactivate_pro_licence since 5.0.0
- *
- * @date 30/09/2021
- * @since 5.11.0
- *
- * @param bool $silent Return errors rather than displaying them
- * @return mixed $response A wp-error instance, or an array with a boolean success key, and string message key
- */
- function acf_pro_deactivate_license( $silent = false ) {
- // Get license key.
- $license = acf_pro_get_license_key( true );
- // Bail early if no key.
- if ( ! $license ) {
- return false;
- }
- // Connect to API.
- $post = array(
- 'acf_license' => $license,
- 'wp_url' => acf_get_home_url(),
- );
- $response = acf_updates()->request( 'v2/plugins/deactivate?p=pro', $post );
- // Check response is expected JSON array (not string).
- if ( is_string( $response ) ) {
- $response = new WP_Error( 'server_error', esc_html( $response ) );
- }
- // Display error.
- if ( is_wp_error( $response ) ) {
- if ( ! $silent ) {
- display_wp_activation_error( $response );
- }
- return $response;
- }
- // Remove license key from DB.
- acf_pro_update_license( '' );
- // Refresh plugins transient to fetch new update data.
- acf_updates()->refresh_plugins_transient();
- $success = $response['status'] == 1;
- if ( ! $silent ) {
- $notice_class = $success ? 'info' : 'warning';
- acf_add_admin_notice( acf_esc_html( $response['message'] ), $notice_class );
- }
- // Return status array for automated activation error notices
- return array(
- 'success' => $success,
- 'message' => $response['message'],
- );
- }
- /**
- * Adds an admin notice using the provided WP_Error.
- *
- * @date 14/1/19
- * @since 5.7.10
- *
- * @param WP_Error $wp_error The error to display.
- */
- function display_wp_activation_error( $wp_error ) {
- // Only show one error on page.
- if ( acf_has_done( 'display_wp_error' ) ) {
- return;
- }
- // Create new notice.
- acf_new_admin_notice(
- array(
- 'text' => __( '<b>ACF Activation Error</b>. Could not connect to activation server', 'acf' ) . ' <span class="description">(' . esc_html( $wp_error->get_error_message() ) . ').</span>',
- 'type' => 'error',
- )
- );
- }
|