args = $args; $this->product_id = sanitize_key( $args['name'] ); if ( isset( $args['bundled'] ) ) { $this->add_bundled_product( $args['bundled'] ); } $this->set_registration_data(); // Instantiate the updater. if ( null === $this->updater ) { $this->updater = new Fusion_Updater( $this ); } add_action( 'wp_ajax_avada_product_registration', [ $this, 'ajax_check_registration' ] ); } /** * Adds a product to the array of bundled products. * * @access private * @since 1.0.0 * @param array $bundled An array o bundled products. */ private function add_bundled_product( $bundled ) { $bundled = (array) $bundled; foreach ( $bundled as $product_slug => $product_name ) { $product = sanitize_key( $product_name ); if ( ! isset( self::$bundled[ $product ] ) ) { self::$bundled[ $product ] = $this->args['name']; } } } /** * Gets bundled products array. * * @access public * @since 1.0.0 * @return array */ public function get_bundled() { return self::$bundled; } /** * Gets the arguments. * * @access public * @since 1.0.0 * @return array */ public function get_args() { return $this->args; } /** * Checks if the product is part of the themes or plugins * purchased by the user belonging to the token. * * @access public * @since 1.0.0 */ public function ajax_check_registration() { if ( ! isset( $_POST['avada_product_reg'] ) || ! wp_verify_nonce( $_POST['avada_product_reg'], 'avada_product_reg_nonce' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput exit( 'Invalid request.' ); } $this->check_registration(); ob_start(); $this->the_form(); $response = ob_get_clean(); exit( $response ); // phpcs:ignore WordPress.Security.EscapeOutput } /** * Checks if the product is part of the themes or plugins * purchased by the user belonging to the token. * * @access public * @since 1.0.0 */ public function check_registration() { // Sanity check. No need to do anything if we're not saving the form. if ( ( isset( $_POST[ $this->option_name ] ) && isset( $_POST[ $this->option_name ][ $this->product_id ] ) || isset( $_POST['avada_unregister_product'] ) ) && isset( $_POST['_wpnonce'] ) ) { // Reset saved errors. $this->errors = null; // Revoking or registering. $revoke = isset( $_POST['avada_unregister_product'] ) && '1' === $_POST['avada_unregister_product']; // Security check. check_admin_referer( $this->option_name . '_' . $this->product_id ); // No purchase code passed and we are not revoking. if ( ! $revoke && ! isset( $_POST[ $this->option_name ][ $this->product_id ]['purchase_code'] ) ) { return; } if ( $revoke ) { $purchase_code = $this->get_purchase_code(); $revoked = $this->revoke_purchase_code( $purchase_code ); // Always revoke, regardless of response. $valid = false; $purchase_code = ''; $this->registration_data[ $this->product_id ]['token'] = ''; } else { $purchase_code = sanitize_text_field( wp_unslash( $_POST[ $this->option_name ][ $this->product_id ]['purchase_code'] ) ); $purchase_code = wp_strip_all_tags( trim( $purchase_code ) ); $valid = $this->check_purchase( $purchase_code ); } // Update saved product data. $this->registration_data[ $this->product_id ]['purchase_code'] = $purchase_code; $this->registration_data[ $this->product_id ]['is_valid'] = $valid; $this->registration_data[ $this->product_id ]['errors'] = null !== $this->errors ? $this->errors : ''; $this->update_data(); // Refresh data for grace period. delete_transient( 'avada_dashboard_data' ); } } /** * Update data to database. * * @access public * @since 3.3 * @return void */ public function update_data() { $save_data = $this->registration_data; // Filter out non-persistent error messages. if ( isset( $save_data[ $this->product_id ]['errors'] ) && is_wp_error( $save_data[ $this->product_id ]['errors'] ) ) { $error_code = $save_data[ $this->product_id ]['errors']->get_error_code(); if ( 400 === $error_code ) { $save_data[ $this->product_id ]['errors'] = ''; } } else { $save_data[ $this->product_id ]['errors'] = ''; } update_option( $this->option_name, $save_data ); } /** * Update data to database, CLI version. * * @access public * @since 3.4 * @param array $registration_data Registration data. * @return void */ public function cli_update_data( $registration_data ) { // Early exit. if ( empty( $registration_data ) || ! defined( 'WP_CLI' ) || ! WP_CLI ) { return; } $save_data = $registration_data; // Filter out non-persistent error messages. if ( isset( $save_data['avada']['errors'] ) && is_wp_error( $save_data['avada']['errors'] ) ) { $error_code = $save_data['avada']['errors']->get_error_code(); if ( 400 === $error_code ) { $save_data['avada']['errors'] = ''; } } else { $save_data['avada']['errors'] = ''; } update_option( $this->option_name, $save_data ); } /** * Get errors property. * * @access public * @since 3.4 * @return null|object */ public function get_errors() { return $this->errors; } /** * Check if purchase code is valid. * * @access public * @since 3.3 * @param string $purchase purchase code. * @return bool */ public function check_purchase( $purchase = '' ) { if ( '' === $purchase ) { $this->errors = $this->get_error( 400, 'auth' ); return false; } if ( false === strpos( $purchase, '-' ) && 32 === strlen( $purchase ) ) { $this->errors = $this->get_error( 401, 'token' ); return; } if ( 36 !== strlen( $purchase ) || 4 !== substr_count( $purchase, '-' ) ) { $this->errors = $this->get_error( 401, 'auth' ); return false; } $args = [ 'timeout' => 60, 'user-agent' => 'fusion-purchase-code', ]; $response = wp_remote_get( FUSION_UPDATES_URL . '/wp-json/avada-api/validate-code/' . $purchase, $args ); if ( is_wp_error( $response ) ) { $this->errors = $response; return false; } $code = wp_remote_retrieve_response_code( $response ); if ( 399 < $code && 501 > $code ) { $this->errors = $this->get_error( $code, 'auth' ); return false; } $response = isset( $response['body'] ) ? json_decode( $response['body'], true ) : false; if ( true === $response ) { return true; } $this->get_error( $code, 'auth' ); return false; } /** * Registration doesn't appear to be valid. * * @access public * @param object $error WordPress error object. * @return object * @since 3.3 */ public function invalidate( $error = '' ) { $this->registration_data[ $this->product_id ]['is_valid'] = false; $this->registration_data[ $this->product_id ]['errors'] = $error; $this->update_data(); return $error; } /** * Get error for code. * * @access public * @param int $code HTTP code. * @param string $request Request type. * @return object WP error * @since 3.3 */ public function get_error( $code = 403, $request = 'auth' ) { switch ( (int) $code ) { // No code. case 400: if ( 'revoke' === $request ) { return new WP_Error( $code, __( 'No purchase code was passed on to be revoked.', 'Avada' ) ); } if ( 'prebuilt' === $request ) { return new WP_Error( $code, __( 'In order to import a prebuilt website Avada must be registered. No purchase code was found.', 'Avada' ) ); } return new WP_Error( $code, __( 'No purchase code was provided.', 'Avada' ) ); // No domain. case 417: if ( 'revoke' === $request ) { return new WP_Error( $code, __( 'No domain was passed on and therefore revoke could not be confirmed.', 'Avada' ) ); } if ( 'prebuilt' === $request ) { return new WP_Error( $code, __( 'In order to import a prebuilt website Avada must be registered. No domain was passed on, therefore validation could not be confirmed.', 'Avada' ) ); } return new WP_Error( $code, __( 'No domain was passed on in the request, this is needed to confirm registration.', 'Avada' ) ); // Invalid purchase code. case 401: if ( 'token' === $request ) { return new WP_Error( $code, __( 'Invalid purchase code. Code provided appears to be a token instead.', 'Avada' ) ); } if ( 'download' === $request ) { return $this->invalidate( new WP_Error( $code, __( 'Invalid purchase code.', 'Avada' ) ) ); } if ( 'prebuilt' === $request ) { return $this->invalidate( new WP_Error( $code, __( 'In order to import a prebuilt website Avada must be registered. The purchase code being used does not seem to be valid.', 'Avada' ) ) ); } return new WP_Error( $code, __( 'Invalid purchase code.', 'Avada' ) ); // Envato forbidden. case 403: return new WP_Error( $code, __( 'Envato API did not respond. Either the purchase code is incorrect or the API is temporarily unavailable.', 'Avada' ) ); // Domain mismatch. case 409: if ( 'download' === $request ) { return $this->invalidate( new WP_Error( $code, __( 'The purchase code is already being used on another domain.', 'Avada' ) ) ); } if ( 'revoke' === $request ) { return new WP_Error( $code, __( 'The current domain does not match our records and therefore was not revoked.', 'Avada' ) ); } if ( 'prebuilt' === $request ) { return $this->invalidate( new WP_Error( $code, __( 'In order to import a prebuilt website Avada must be registered. The current domain does not match our records.', 'Avada' ) ) ); } return new WP_Error( $code, __( 'The purchase code is already being used on another domain.', 'Avada' ) ); // Staging mismatch. case 412: if ( 'download' === $request ) { return $this->invalidate( new WP_Error( $code, __( 'The purchase code is already being used on another staging domain.', 'Avada' ) ) ); } if ( 'prebuilt' === $request ) { return $this->invalidate( new WP_Error( $code, __( 'In order to import a prebuilt website Avada must be registered. The current staging domain does not match our records.', 'Avada' ) ) ); } return new WP_Error( $code, __( 'The purchase code is already being used on another staging domain.', 'Avada' ) ); // Purchase code locked. case 423: /* translators: "ThemeFusion" contact link. */ return $this->invalidate( new WP_Error( $code, sprintf( __( 'This purchase code has been locked, as it was used in a manner that violates Envato license terms. Please contact us via the %s page to resolve.', 'Avada' ), 'license unlock' ) ) ); // Envato API limited. case 429: return new WP_Error( $code, __( 'Sorry, the API is currently overloaded. Please try again later.', 'Avada' ) ); // Too many registrations. case 406: /* translators: "ThemeFusion" contact link. */ return new WP_Error( $code, sprintf( __( 'The purchase code has been registered too many times. Please contact %s to resolve.', 'Avada' ), 'Avada' ) ); } return new WP_Error( $code, __( 'Unknown error encountered. Please try again later.', 'Avada' ) ); } /** * Bypass active or not. * * @access public * @since 3.3 */ public function bypass_active() { $data = Avada::get_data(); if ( isset( $data['bypass_active'] ) && $data['bypass_active'] ) { return true; } return false; } /** * Whether user should see restricted UI or not. * * @access public * @param string $type section type. * @since 3.3 */ public function should_show( $type = 'plugins' ) { return $this->is_registered() || $this->legacy_support() || $this->bypass_active(); } /** * Reset token because its invalid. * * @access public * @since 3.3 */ public function reset_token() { $this->registration_data[ $this->product_id ]['token'] = ''; $this->update_data(); } /** * Revoke purchase code. * * @access public * @param string $purchase Purchase code to revoke. * @since 3.3 */ public function revoke_purchase_code( $purchase = '' ) { $args = [ 'timeout' => 60, 'user-agent' => 'fusion-purchase-code', ]; $response = wp_remote_get( FUSION_UPDATES_URL . '/wp-json/avada-api/revoke-code/' . $purchase, $args ); if ( is_wp_error( $response ) ) { $this->errors = $response; return false; } $code = wp_remote_retrieve_response_code( $response ); if ( 399 < $code && 501 > $code ) { $this->errors = $this->get_error( $code, 'revoke' ); return false; } $response = isset( $response['body'] ) ? json_decode( $response['body'], true ) : false; if ( true === $response ) { return true; } $this->get_error( $code, 'revoke' ); return false; } /** * Check if updates can be served in grace period. * * @access public * @since 1.9.2 * @param string $product_id The plugin/theme ID. * @return bool */ public function legacy_support( $product_id = '' ) { if ( ! $product_id ) { $product_id = $this->product_id; } if ( ! isset( $this->registration_data[ $product_id ] ) ) { return false; } // No token, need to register. if ( '' === $this->get_token() ) { return false; } $data = Avada::get_data(); // Token and no grace set, must be first plugin update. if ( ! isset( $data['legacy_end'] ) || '' === $data['legacy_end'] ) { return true; } // Current time is before end date, grace is valid. $current = new DateTime( gmdate( 'D, d M Y H:i' ) ); $legacy_end = new DateTime( gmdate( 'D, d M Y H:i', $data['legacy_end'] ) ); if ( $current < $legacy_end ) { return true; } // Grace has ended. return false; } /** * Set available registration data. * * @access public * @since 1.9.2 * @return void */ public function set_registration_data() { $registration_data = []; $registration_data_stored = get_option( $this->option_name, [] ); $registration_data_dummy = [ 'token' => '', 'purchase_code' => '', 'is_valid' => 'false', 'scopes' => [], 'errors' => '', ]; foreach ( $registration_data_stored as $product => $data ) { $registration_data[ $product ] = wp_parse_args( $data, $registration_data_dummy ); } // No data at all, set it to dummy data. if ( ! isset( $registration_data[ $this->product_id ] ) ) { $registration_data[ $this->product_id ] = $registration_data_dummy; } // if we have stored errors, set them to display. if ( isset( $registration_data[ $this->product_id ]['errors'] ) && '' !== $registration_data[ $this->product_id ]['errors'] ) { $this->errors = $registration_data[ $this->product_id ]['errors']; } $this->registration_data = $registration_data; } /** * Check if product is part of registration data and is also valid. * * @access public * @since 1.9.2 * @param string $product_id The plugin/theme ID. * @return bool */ public function is_registered( $product_id = '' ) { if ( ! $product_id ) { $product_id = $this->product_id; } if ( ! isset( $this->registration_data[ $product_id ] ) ) { return false; } if ( '' === $this->registration_data[ $product_id ]['purchase_code'] ) { return false; } // Is the product registered? if ( true === $this->registration_data[ $product_id ]['is_valid'] ) { return true; } return false; } /** * Legacy update and builder has not been updated yet. * * @access public * @since 1.0.0 * @return boolean */ public function is_legacy_update() { return '' !== $this->get_token() && defined( 'FUSION_BUILDER_VERSION' ) && version_compare( FUSION_BUILDER_VERSION, '3.3', '<' ); } /** * If it should appear as if registered. * * @access public * @since 1.0.0 * @return boolean */ public function appear_registered() { return $this->is_registered() || $this->is_legacy_update(); } /** * Returns the stored token for the product. * * @access public * @since 1.0.0 * @param string $product_id The product-ID. * @return string The current token. */ public function get_token( $product_id = '' ) { if ( '' === $product_id ) { $product_id = $this->product_id; } if ( isset( $this->registration_data[ $product_id ] ) ) { return $this->registration_data[ $product_id ]['token']; } return ''; } /** * Returns the purchase code * * @access public * @since 3.3 * @param string $product_id The product-ID. * @return string The current token. */ public function get_purchase_code( $product_id = '' ) { if ( '' === $product_id ) { $product_id = $this->product_id; } if ( isset( $this->registration_data[ $product_id ] ) ) { return $this->registration_data[ $product_id ]['purchase_code']; } return ''; } /** * Prints the registration form. * * @access public * @since 1.0.0 * @return void */ public function the_form() { /** * Check registration. Now done in the admin class. * $this->check_registration(); */ // Get the stored token. $token = $this->get_token(); $purchase_code = $this->get_purchase_code(); // Is the product registered? $is_registered = $this->appear_registered(); ?>

my.avada.com' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>

option_name}[{$this->product_id}][purchase_code]" ); ?>" value="" />
option_name . '_' . $this->product_id ); ?>
errors ) : ?>
errors->get_error_message(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>

  1. IMPORTANT: You must be signed into the same ThemeForest account that purchased Avada. If you are signed in already, look in the top menu bar to ensure it is the right account.', 'Avada' ), // phpcs:ignore WordPress.Security.EscapeOutput '' . esc_html__( 'ThemeForest account', 'Avada' ) . '' ); ?>
  2. ' . esc_html__( 'ThemeForest downloads page', 'Avada' ) . '' ); ?>