__( 'Theme License', 'ang' ), 'enter-key' => __( 'Enter your theme license key received upon purchase from AnalogWP.', 'ang' ), 'license-key' => __( 'License Key', 'ang' ), 'license-action' => __( 'License Action', 'ang' ), 'deactivate-license' => __( 'Deactivate License', 'ang' ), 'activate-license' => __( 'Activate License', 'ang' ), 'status-unknown' => __( 'License status is unknown.', 'ang' ), 'renew' => __( 'Renew?', 'ang' ), 'unlimited' => __( 'unlimited', 'ang' ), 'license-key-is-active' => __( 'License key is active.', 'ang' ), /* translators: %s: expiration date */ 'expires%s' => __( 'Expires %s.', 'ang' ), 'expires-never' => __( 'Lifetime License.', 'ang' ), /* translators: %1$s: active sites, %2$s: sites limit */ '%1$s/%2$-sites' => __( 'You have %1$s / %2$s sites activated.', 'ang' ), /* translators: %s: product name */ 'license-key-expired-%s' => __( 'License key expired %s.', 'ang' ), 'license-key-expired' => __( 'License key has expired.', 'ang' ), 'license-keys-do-not-match' => __( 'License keys do not match.

Enter your theme license key received upon purchase from AnalogWP.', 'ang' ), 'license-is-inactive' => __( 'License is inactive.', 'ang' ), 'license-key-is-disabled' => __( 'License key is disabled.', 'ang' ), 'site-is-inactive' => __( 'Site is inactive.', 'ang' ), 'license-status-unknown' => __( 'License status is unknown.', 'ang' ), 'update-notice' => __( "Updating this theme will lose any customizations you have made. 'Cancel' to stop, 'OK' to update.", 'ang' ), 'update-available' => __( // @codingStandardsIgnoreLine '%1$s %2$s is available. Check out what\'s new or update now.', 'ang' ), ]; $this->strings = $strings; add_action( 'rest_api_init', [ $this, 'register_endpoints' ] ); add_action( 'admin_init', [ $this, 'get_license_message' ], 10, 2 ); } /** * Register license management endpoints. * * @return void */ public function register_endpoints() { register_rest_route( 'agwp/v1', '/license', [ 'methods' => \WP_REST_Server::CREATABLE, 'callback' => [ $this, 'handle_license_request' ], 'permission_callback' => function() { return current_user_can( 'manage_options' ); }, ] ); register_rest_route( 'agwp/v1', '/license/status', [ 'methods' => \WP_REST_Server::READABLE, 'callback' => [ $this, 'get_license_message' ], 'permission_callback' => function() { return current_user_can( 'manage_options' ); }, ] ); } /** * Handles licenses requests: * - check_license * - activate_license * - deactivate_license * * @param \WP_REST_Request $request Request object. * @return \WP_REST_Response|\WP_Error */ public function handle_license_request( \WP_REST_Request $request ) { $action = $request->get_param( 'action' ); if ( ! $action ) { return new \WP_Error( 'license_error', 'No license action defined.' ); } $data = ''; if ( 'check' === $action ) { $data = $this->check_license(); } elseif ( 'activate' === $action ) { $data = $this->activate_license(); } elseif ( 'deactivate' === $action ) { $data = $this->deactivate_license(); } return new \WP_REST_Response( $data, 200 ); } /** * Makes a call to the API. * * @since 1.0.0 * * @param array $api_params to be used for wp_remote_get. * @return array $response decoded JSON response. */ public function get_api_response( $api_params ) { $response = wp_remote_post( $this->remote_api_url, array( 'timeout' => 15, 'sslverify' => false, 'body' => $api_params, ) ); // Make sure the response came back okay. if ( is_wp_error( $response ) ) { wp_die( $response->get_error_message(), __( 'Error' ) . $response->get_error_code() ); // @codingStandardsIgnoreLine } return $response; } /** * Constructs a renewal link */ public function get_renewal_link() { // If a renewal link was passed in the config, use that. if ( '' !== $this->renew_url ) { return $this->renew_url; } // If download_id was passed in the config, a renewal link can be constructed. $license_key = Options::get_instance()->get( $this->license_slug ); if ( '' !== $this->download_id && $license_key ) { $url = esc_url( $this->remote_api_url ); $url .= '/checkout/?edd_license_key=' . $license_key . '&download_id=' . $this->download_id; return $url; } // Otherwise return the remote_api_url. return $this->remote_api_url; } /** * Checks if license is valid and gets expire date. * * @return string $message License status message. */ public function check_license() { $license = trim( Options::get_instance()->get( $this->license_slug ) ); if ( ! $license ) { return; } $strings = $this->strings; $this->check_memory_limit(); $api_params = array( 'edd_action' => 'check_license', 'license' => $license, 'item_id' => $this->item_id, 'url' => home_url(), ); $response = $this->get_api_response( $api_params ); if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) { if ( is_wp_error( $response ) ) { $message = $response->get_error_message(); } else { $message = $strings['license-status-unknown']; } } else { $license_data = json_decode( wp_remote_retrieve_body( $response ) ); if ( ! isset( $license_data->license ) ) { $message = $strings['license-status-unknown']; return $message; } // We need to update the license status at the same time the message is updated. if ( $license_data && isset( $license_data->license ) ) { Options::get_instance()->set( 'ang_license_key_status', $license_data->license ); } // Get expire date. $expires = false; if ( isset( $license_data->expires ) && 'lifetime' !== $license_data->expires ) { $expires = date_i18n( get_option( 'date_format' ), strtotime( $license_data->expires, current_time( 'timestamp' ) ) ); $renew_link = '' . $strings['renew'] . ''; } elseif ( isset( $license_data->expires ) && 'lifetime' === $license_data->expires ) { $expires = 'lifetime'; } // Get site counts. $site_count = $license_data->site_count; $license_limit = $license_data->license_limit; // If unlimited. if ( 0 === $license_limit ) { $license_limit = $strings['unlimited']; } if ( 'valid' === $license_data->license ) { $message = $strings['license-key-is-active'] . ' '; if ( isset( $expires ) && 'lifetime' !== $expires ) { $message .= sprintf( $strings['expires%s'], $expires ) . ' '; } if ( isset( $expires ) && 'lifetime' === $expires ) { $message .= $strings['expires-never']; } if ( $site_count && $license_limit ) { $message .= sprintf( $strings['%1$s/%2$-sites'], $site_count, $license_limit ); } } elseif ( 'expired' === $license_data->license ) { if ( $expires ) { $message = sprintf( $strings['license-key-expired-%s'], $expires ); } else { $message = $strings['license-key-expired']; } if ( $renew_link ) { $message .= ' ' . $renew_link; } } elseif ( 'invalid' === $license_data->license ) { $message = $strings['license-keys-do-not-match']; } elseif ( 'inactive' === $license_data->license ) { $message = $strings['license-is-inactive']; } elseif ( 'disabled' === $license_data->license ) { $message = $strings['license-key-is-disabled']; } elseif ( 'site_inactive' === $license_data->license ) { // Site is inactive. $message = $strings['site-is-inactive']; } else { $message = $strings['license-status-unknown']; } } return $message; } /** * Activates the license key. * * @return array|\WP_Error */ public function activate_license() { $license = trim( Options::get_instance()->get( $this->license_slug ) ); $message = ''; $this->check_memory_limit(); // Data to send in our API request. $api_params = array( 'edd_action' => 'activate_license', 'license' => $license, 'item_id' => $this->item_id, 'url' => home_url(), ); $response = $this->get_api_response( $api_params ); $license_data = ''; // make sure the response came back okay. if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) { if ( is_wp_error( $response ) ) { $message = $response->get_error_message(); } else { $message = __( 'An error occurred, please try again.', 'ang' ); } } else { $license_data = json_decode( wp_remote_retrieve_body( $response ) ); if ( false === $license_data->success ) { switch ( $license_data->error ) { case 'expired': $message = sprintf( /* translators: %s: expiration date */ __( 'Your license key expired on %s.', 'ang' ), date_i18n( get_option( 'date_format' ), strtotime( $license_data->expires, current_time( 'timestamp' ) ) ) ); break; case 'revoked': $message = __( 'Your license key has been disabled.', 'ang' ); break; case 'missing': $message = __( 'Invalid license.', 'ang' ); break; case 'invalid': case 'site_inactive': $message = __( 'Your license is not active for this URL.', 'ang' ); break; case 'item_name_mismatch': /* translators: %s: site name/email */ $message = sprintf( __( 'This appears to be an invalid license key for %s.', 'ang' ), $args['name'] ); break; case 'no_activations_left': $message = __( 'Your license key has reached its activation limit.', 'ang' ); break; default: $message = __( 'An error occurred, please try again.', 'ang' ); break; } if ( ! empty( $message ) ) { return new \WP_Error( 'activation_error', $message ); } } } // $response->license will be either "active" or "inactive". if ( $license_data && isset( $license_data->license ) ) { Options::get_instance()->set( 'ang_license_key_status', $license_data->license ); delete_transient( 'ang_license_message' ); } return [ 'status' => Options::get_instance()->get( 'ang_license_key_status' ), 'message' => $this->get_license_message(), 'action' => 'activate', ]; } /** * Get displayable license status message. * * @return string|mixed */ public function get_license_message() { if ( ! get_transient( 'ang_license_message' ) ) { set_transient( 'ang_license_message', $this->check_license(), DAY_IN_SECONDS ); } return get_transient( 'ang_license_message' ); } /** * Deactivates the license key. */ public function deactivate_license() { $license = trim( Options::get_instance()->get( $this->license_slug ) ); $this->check_memory_limit(); // Data to send in our API request. $api_params = array( 'edd_action' => 'deactivate_license', 'license' => $license, 'item_id' => $this->item_id, 'url' => home_url(), ); $response = $this->get_api_response( $api_params ); // Make sure the response came back okay. if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) { if ( is_wp_error( $response ) ) { $message = $response->get_error_message(); } else { $message = __( 'An error occurred, please try again.', 'ang' ); } } else { $license_data = json_decode( wp_remote_retrieve_body( $response ) ); // $license_data->license will be either "deactivated" or "failed". if ( $license_data && ( 'deactivated' === $license_data->license ) ) { Options::get_instance()->set( 'ang_license_key_status', false ); delete_transient( 'ang_license_message' ); } } if ( ! empty( $message ) ) { return new \WP_Error( 'deactivation_error', $message ); } return [ 'status' => Options::get_instance()->get( 'ang_license_key_status' ), 'message' => $this->get_license_message(), 'action' => 'deactivate', ]; } } new LicenseManager();