Skip to content

Commit

Permalink
Improved: store result from AJAX validation in transient, to speed up…
Browse files Browse the repository at this point in the history
… checkout process.
  • Loading branch information
Dan0sz committed Sep 22, 2023
1 parent 9c5089f commit 28b705b
Show file tree
Hide file tree
Showing 5 changed files with 163 additions and 142 deletions.
4 changes: 2 additions & 2 deletions assets/js/edd-truemail.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@ document.addEventListener('DOMContentLoaded', () => {
email: emailField.value
}
).done(function (response) {
if (response.status === 200 && response.success === true) {
if (response.code === 200 && response.success === true) {
// Valid email address.
emailField.classList.remove('edd-truemail-warning');
emailField.classList.add('edd-truemail-success');
}

remove_loader();
}).fail(function (response) {
if (response.status === 200 && response.success === false) {
if (response.code === 200 && response.success === false) {
// Email address is invalid.
emailField.classList.remove('edd-truemail-success');
emailField.classList.add('edd-truemail-warning');
Expand Down
2 changes: 1 addition & 1 deletion assets/js/edd-truemail.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

124 changes: 68 additions & 56 deletions src/Ajax.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,67 +7,79 @@
* https://daan.dev
* @copyright © 2023 Daan van den Bergh
*/

namespace EDD\Truemail;

use WpOrg\Requests\Exception\InvalidArgument;

defined( 'ABSPATH' ) || exit;

class Ajax {
/**
* Ajax constructor.
*
* @return void
*/
public function __construct() {
$this->init();
}

/**
* Initializes the class.
*
* @return void
*/
private function init() {
add_action( 'wp_ajax_edd_truemail_verify_email', [ $this, 'verify' ] );
add_action( 'wp_ajax_nopriv_edd_truemail_verify_email', [ $this, 'verify' ] );
}

/**
* Verifies an email address.
*
* @return void
*
* @throws InvalidArgument
*/
public function verify() {
$email = isset( $_POST['email'] ) ? sanitize_email( $_POST['email'] ) : false;
$client = new Client();
$result = $client->verify( $email );
$response = [
'status' => $result['code'],
'success' => false,
];

if ( ! $result['success'] && $result['code'] === 200 ) {
$response['message'] = __( 'We couldn\'t verify your email address. Are you sure it\'s spelled correctly?', 'edd-truemail' );
}

if ( ! $result['success'] && $result['code'] === 400 ) {
$response['message'] = __( 'Please enter a valid email address.', 'edd-truemail' );
}

if ( ! $result['success'] && $result['code'] === 408 ) {
$response['message'] = __( 'Request timed out.', 'edd-truemail' );
}

if ( ! $result['success'] ) {
wp_send_json_error( $response );
}

$response['message'] = __( 'Email address verified.', 'edd-truemail' );
$response['success'] = true;

wp_send_json_success( $response );
}
const TRANSIENT_LABEL = 'edd_truemail_valid_%s';

/**
* Ajax constructor.
*
* @return void
*/
public function __construct() {
$this->init();
}

/**
* Initializes the class.
*
* @return void
*/
private function init() {
add_action( 'wp_ajax_edd_truemail_verify_email', [ $this, 'verify' ] );
add_action( 'wp_ajax_nopriv_edd_truemail_verify_email', [ $this, 'verify' ] );
}

/**
* Verifies an email address.
*
* @return void
*
* @throws InvalidArgument
*/
public function verify() {
$email = isset( $_POST['email'] ) ? sanitize_email( $_POST['email'] ) : false;
$client = new Client();
$result = $client->verify( $email );
$response = [
'code' => $result['code'],
'success' => false,
];

if ( ! $result['success'] && $result['code'] === 200 ) {
$response['message'] = __( 'We couldn\'t verify your email address. Are you sure it\'s spelled correctly?', 'edd-truemail' );
}

if ( ! $result['success'] && $result['code'] === 400 ) {
$response['message'] = __( 'Please enter a valid email address.', 'edd-truemail' );
}

if ( ! $result['success'] && $result['code'] === 408 ) {
$response['message'] = __( 'Request timed out.', 'edd-truemail' );
}

if ( $result['success'] && $result['code'] === 200 ) {
$response['message'] = __( 'Email address verified.', 'edd-truemail' );
$response['success'] = true;
}

$transient_label = sprintf( self::TRANSIENT_LABEL, preg_replace( '/\W/', '_', $email ) );

/**
* Store result in a transient for 10 minutes, so it doesn't slow down the checkout process.
*/
set_transient( $transient_label, $response, 600 );

if ( ! $result['success'] ) {
wp_send_json_error( $response );
}

wp_send_json_success( $response );
}
}
136 changes: 68 additions & 68 deletions src/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,85 +7,85 @@
* https://daan.dev
* @copyright © 2023 Daan van den Bergh
*/

namespace EDD\Truemail;

use EDD\Truemail\Admin\Settings;

defined( 'ABSPATH' ) || exit;

class Client {
/**
* @var string Access Token
*/
private $token = '';

/**
* @var string API URL
*/
private $api_url = '';

/**
* Client constructor.
*
* @param string $token
*/
public function __construct() {
$this->token = edd_get_option( Settings::ACCESS_TOKEN );
$this->api_url = edd_get_option( Settings::APP_URL );
}

/**
* Verifies an email address.
*
* @param string $email
* @return array [ 'success' => bool, 'code' => int ]
*/
public function verify( $email ) {
if ( empty( $this->token ) || empty( $this->api_url ) ) {
// Not Acceptable
return [
'success' => false,
'code' => 406,
];
}

$email = sanitize_email( $email );

if ( ! $email ) {
// Bad Request
return [
/**
* @var string Access Token
*/
private $token = '';

/**
* @var string API URL
*/
private $api_url = '';

/**
* Client constructor.
*/
public function __construct() {
$this->token = edd_get_option( Settings::ACCESS_TOKEN );
$this->api_url = edd_get_option( Settings::APP_URL );
}

/**
* Verifies an email address.
*
* @param string $email
*
* @return array [ 'success' => bool, 'code' => int ]
*/
public function verify( $email ) {
if ( empty( $this->token ) || empty( $this->api_url ) ) {
// Not Acceptable
return [
'success' => false,
'code' => 406,
];
}

$email = sanitize_email( $email );

if ( ! $email ) {
// Bad Request
return [
'success' => false,
'code' => 400,
];
}

$url = $this->api_url . '?' . http_build_query( [ 'email' => $email ] );
$response = wp_remote_get(
$url,
[
'timeout' => 15,
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
'Authorization' => $this->token,
],
]
);

if ( is_wp_error( $response ) ) {
// Timeout
return [
];
}
$url = $this->api_url . '?' . http_build_query( [ 'email' => $email ] );
$response = wp_remote_get(
$url,
[
'timeout' => 15,
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
'Authorization' => $this->token,
],
]
);
if ( is_wp_error( $response ) ) {
// Timeout
return [
'success' => false,
'code' => 408,
];
}

$body = json_decode( wp_remote_retrieve_body( $response ) );

// Success
return [
];
}
$body = json_decode( wp_remote_retrieve_body( $response ) );
// Success
return [
'success' => $body->success,
'code' => 200,
];
}
];
}
}
39 changes: 24 additions & 15 deletions src/Plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
* https://daan.dev
* @copyright © 2023 Daan van den Bergh
*/

namespace EDD\Truemail;

use EDD\Truemail\Admin\Settings;
Expand All @@ -21,12 +22,12 @@ class Plugin {
* @return void
*/
public function __construct() {
new Admin\Settings();
new Admin\Settings();
new Ajax();

$this->init();
}

/**
* Initializes the class.
*
Expand All @@ -36,7 +37,7 @@ private function init() {
add_action( 'wp_enqueue_scripts', [ $this, 'enqueue_scripts' ] );
add_action( 'edd_checkout_error_checks', [ $this, 'validate_email' ], 10, 2 );
}

/**
* Enqueues scripts and styles. Loads minified versions if SCRIPT_DEBUG is true.
*
Expand All @@ -46,13 +47,16 @@ public function enqueue_scripts() {
if ( ! edd_is_checkout() ) {
return;
}

$ext = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG === true ? '.min' : '';

wp_enqueue_script( 'edd-truemail', plugin_dir_url( EDD_TM_PLUGIN_FILE ) . "assets/js/edd-truemail$ext.js", [ 'wp-util', 'edd-ajax' ], filemtime( plugin_dir_path( EDD_TM_PLUGIN_FILE ) . 'assets/js/edd-truemail.js' ), false );

wp_enqueue_script( 'edd-truemail', plugin_dir_url( EDD_TM_PLUGIN_FILE ) . "assets/js/edd-truemail$ext.js", [
'wp-util',
'edd-ajax',
], filemtime( plugin_dir_path( EDD_TM_PLUGIN_FILE ) . 'assets/js/edd-truemail.js' ), false );
wp_enqueue_style( 'edd-truemail', plugin_dir_url( EDD_TM_PLUGIN_FILE ) . "assets/css/edd-truemail$ext.css", [], filemtime( plugin_dir_path( EDD_TM_PLUGIN_FILE ) . 'assets/css/edd-truemail.css' ) );
}

/**
* Validates the email address.
*
Expand All @@ -69,20 +73,25 @@ public function validate_email( $valid_data, $data ) {
if ( empty( edd_get_option( Settings::BLOCK_PURCHASE ) ) ) {
return;
}

if ( ! isset( $data['edd_email'] ) ) {
return;
}

$email = sanitize_email( $data['edd_email'] );
$client = new Client();
$result = $client->verify( $email );


$email = sanitize_email( $data['edd_email'] );
$transient_label = sprintf( Ajax::TRANSIENT_LABEL, preg_replace( '/\W/', '_', $email ) );
$result = get_transient( $transient_label );

if ( empty( $result ) ) {
$client = new Client();
$result = $client->verify( $email );
}

// Fail silently on a timeout.
if ( $result['code'] === 408 ) {
return;
}

if ( ! $result['success'] ) {
edd_set_error( 'invalid_email', __( 'The email address you entered either contains a typo or it doesn\'t exist.', 'edd-truemail' ) );
}
Expand Down

0 comments on commit 28b705b

Please sign in to comment.