Last active
August 10, 2018 22:26
-
-
Save indikatordesign/ea2abc30acd1e1478db1244c91738e91 to your computer and use it in GitHub Desktop.
EMP EDD Plugin Updater - Another Approach
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function($){$(function(){ | |
class prefixUpdater | |
{ | |
setProperties() | |
{ | |
this.red = '#fff0f0'; | |
this.green = '#f1fff0'; | |
this.localize = yourPrefixPHP; | |
} // end setProperties | |
constructor() | |
{ | |
this.setProperties(); | |
this.bindEvents(); | |
} // end constructor | |
// This colors the input field according to the response | |
// and inserts the corresponding feedback as placeholder | |
resp( color, message ) | |
{ | |
return this.field | |
.css( 'background', color ) | |
.attr( 'value', '' ) | |
.attr( 'placeholder', message ); | |
} | |
// The handler for Ajax requests | |
ajax( action, key, self, that = this ) | |
{ | |
let data = | |
{ | |
nonce : self.localize.nonce, | |
action : action, | |
license : key, | |
} | |
data[action] = true; | |
$.ajax( | |
{ | |
data : data, | |
type : 'post', | |
dataType : 'json', | |
url : self.localize.url, | |
success: function( data ) | |
{ | |
if ( self.localize.prefix + '_activate' == action ) | |
{ | |
if ( 'success' in data ) | |
{ | |
self.resp.apply( that, [ self.green, data.success ] ); | |
setTimeout( () => | |
{ | |
$(that).closest( 'div.update-message' ).slideUp( 800, function() | |
{ | |
$(this).closest( 'tr' ).remove(); | |
location.reload(); | |
}); | |
}, 3000 ); | |
} | |
else | |
self.resp.apply( that, [ self.red, data.failed ] ); | |
} | |
else | |
{ | |
if ( 'delete' in data ) | |
{ | |
alert( data.delete ); | |
location.reload(); | |
} | |
else | |
alert( data.failed ); | |
} | |
}, | |
error: function( data ) | |
{ | |
alert( self.localize.error ); | |
location.reload(); | |
} | |
}); | |
} // end ajax | |
bindEvents( self = this ) | |
{ | |
// The Event Handler for license activation (Submit button) | |
$( '#' + self.localize.prefix + '-license-submit' ).on( 'click', function( e ) | |
{ | |
e.preventDefault(); | |
e.stopImmediatePropagation(); | |
this.field = $( '#' + self.localize.prefix + '-license-field' ); | |
this.val = this.field.val(); | |
// The EMP license keys are all 32 characters long | |
if ( this.val && 32 == this.val.length ) | |
{ | |
// Valid request | |
self.ajax.apply( this, [ self.localize.prefix + '_activate', this.val, self ] ); | |
} | |
else // Invalid request | |
self.resp.apply( this, [ self.red, self.localize.valid, self ] ); | |
}); | |
// The Event Handler for license deactivation (Remove link) | |
$( '#' + self.localize.prefix + '-remove-license' ).on( 'click', function( e ) | |
{ | |
e.preventDefault(); | |
self.ajax.apply( this, [ self.localize.prefix + '_deactivate', self.localize.key, self ] ); | |
}); | |
} // end bindEvents | |
} // end class prefixUpdater | |
new prefixUpdater; | |
});}(jQuery)); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* EMP EDD Updater class for smooth Ajax handling | |
* Author: Bruno Bouyajdad | Indikator Design | |
* Author URI: https://indikator-design.com | |
* License: GPLv2 or later | |
* License URI: http://www.gnu.org/licenses/gpl-2.0.html | |
* | |
* @since 1.0.0 | |
*/ | |
if ( ! class_exists( 'prefixUpdateInitialize' ) ) | |
{ | |
class prefixUpdateInitialize | |
{ | |
/** | |
* Define properties | |
* | |
* @since 1.0.0 | |
*/ | |
private $args; | |
private $domain; | |
private $prefix; | |
private $licenseKey; | |
/** | |
* Constructor | |
* | |
* @since 1.0.0 | |
*/ | |
public function __construct() | |
{ | |
/** | |
* Set the properties | |
* | |
* @since 1.0.0 | |
*/ | |
$this->domain = 'yourDomain'; | |
$this->prefix = 'yourPrefix'; | |
$this->args = (object) | |
[ | |
'url' => 'https://elegantmarketplace.com', | |
'file' => MyPluginMainFileClass::FILE, // Constant defined in the plugin main file with __FILE__ | |
'args' => | |
[ | |
'license' => '', | |
'beta' => false, | |
'item_id' => 1234567, // Your EMP Download ID | |
'item_name' => 'My Awesome Plugin', // Your EMP Download Title | |
'version' => '1.0.0', | |
'author' => 'Bruno Bouyajdad', | |
] | |
]; | |
/** | |
* Initialize | |
* | |
* @since 1.0.0 | |
*/ | |
if ( is_admin() ) | |
$this->initialize(); | |
} // end constructor | |
/** | |
* Initialize | |
* | |
* @since 1.0.0 | |
*/ | |
public function initialize() | |
{ | |
$this->licenseKey = get_option( esc_attr( $this->prefix . '_license_key' ) ); | |
if ( $this->licenseKey ) : | |
$this->args->args['license'] = $this->licenseKey; | |
add_action( 'wp_ajax_' . $this->prefix . '_deactivate', [ $this, 'deactivateLicense' ] ); | |
else : | |
add_action( 'wp_ajax_' . $this->prefix . '_activate', [ $this, 'activateLicense' ] ); | |
endif; | |
add_action( 'admin_init', [ $this, 'updater' ], 0 ); | |
add_action( 'current_screen', function( $screen ) | |
{ | |
if ( 'plugins' == $screen->base ) : | |
$slug = $this->prefix . '-plugins'; | |
if ( ! $this->licenseKey ) | |
add_action( 'after_plugin_row', [ $this, 'licenseField' ] ); | |
else | |
add_filter( 'plugin_action_links_' . plugin_basename( $this->args->file ), [ $this, 'removeLink' ] ); | |
$this->enqueueScript( $slug, [ 'jquery' ] ); | |
wp_localize_script( $slug, $this->prefix . 'PHP', $this->localize() ); | |
endif; | |
}); // end add_action | |
} // end initialize | |
/** | |
* Data for Localization | |
* | |
* @since 1.0.0 | |
*/ | |
public function localize() | |
{ | |
return | |
[ | |
'prefix' => $this->prefix, | |
'error' => $this->getMessage()->error, | |
'url' => admin_url( 'admin-ajax.php' ), | |
'key' => $this->licenseKey ? $this->licenseKey : '', | |
'nonce' => wp_create_nonce( $this->prefix . "-nonce-value" ) , | |
'valid' => esc_html__( "Insert a valid key.", $this->domain ), | |
]; | |
} // end localize | |
/** | |
* Instantiate the updater class | |
* | |
* @since 1.0.0 | |
*/ | |
public function updater() | |
{ | |
if ( ! class_exists( 'EDD_SL_Plugin_Updater' ) ) | |
include( dirname( __FILE__ ) . '/EDD_SL_Plugin_Updater.php' ); | |
new EDD_SL_Plugin_Updater( $this->args->url, $this->args->file, $this->args->args ); | |
} // end updater | |
/** | |
* Add the license field | |
* | |
* @since 1.0.0 | |
*/ | |
public function licenseField( $plugin ) | |
{ | |
if ( false !== strpos( $plugin, $this->domain ) ) : | |
$prefix = $this->prefix; | |
$text01 = esc_html__( 'Enter Your License Key for future updates', $this->domain ); | |
$text02 = esc_html__( 'Submit', $this->domain ); | |
$text03 = esc_html__( 'You can get it ', $this->domain ); | |
$text04 = esc_html__( 'here.', $this->domain ); | |
echo <<<FORM | |
</tr><tr class="plugin-update-tr"> | |
<td colspan="3" class="plugin-update" style="border-left: 4px solid #00a0d2"> | |
<div class="update-message" style="margin-top:5px;margin-bottom:5px;"> | |
<form action="" method="POST"> | |
<input type="hidden" name="{$prefix}_license" value="license_key"> | |
<div class="about-text" style="display:inline-block"> | |
<div> | |
<input id="{$prefix}-license-field" type="text" class="regular-text" id="license_key" value="" name="license_key" placeholder="{$text01}" style="min-height:30px;"> | |
</div> | |
</div> | |
<div style="display:inline-block"> | |
<button id="{$prefix}-license-submit" class="button button-primary" type="submit" value="Submit" name="_submit" style="margin-top:-6px;border-radius:0">{$text02}</button> | |
</div> | |
</form> | |
<div style="display:inline-block;margin-left:5px"> | |
<span style="margin-right:5px">-</span><span>{$text03}</span><a href="https://elegantmarketplace.com/checkout/purchase-history/" target="_blank">{$text04}</a> | |
</div> | |
</div> | |
</td> | |
FORM; | |
endif; | |
} // end licenseField | |
/** | |
* Link to remove the license | |
* | |
* @since 1.0.0 | |
*/ | |
public function removeLink( $items ) | |
{ | |
$items[] = '<a id="' . $this->prefix . '-remove-license' . '" href="#">' . esc_html__( 'Remove License', $this->domain ) . '</a>'; | |
return $items; | |
} // end removeLink | |
/** | |
* Verify request | |
* | |
* @since 1.0.0 | |
*/ | |
private function verifyRequest( $opt ) | |
{ | |
$r = $_REQUEST; | |
$nonce = isset( $r['nonce'] ) ? esc_attr( $r['nonce'] ) : false; | |
if ( $nonce && wp_verify_nonce( $nonce, $this->prefix . '-nonce-value' ) ) : | |
if ( isset( $r[$opt], $r['license'] ) && 'true' == $r[$opt] ) | |
return true; | |
endif; | |
wp_send_json( (object) [ 'failed' => $this->getMessage()->error ] ); | |
wp_die(); | |
} // end verifyRequest | |
/** | |
* Get error message | |
* | |
* @since 1.0.0 | |
*/ | |
private function getMessage() | |
{ | |
$message = 'The license has been successfully '; | |
return (object) | |
[ | |
'error' => esc_html__( 'That fails. Please reload the page and try it again.', $this->domain ), | |
'success' => esc_html__( $message . 'activated.', $this->domain ), | |
'delete' => esc_html__( $message . 'deactivated.', $this->domain ), | |
]; | |
} // end getMessage | |
/** | |
* Activate the license | |
* | |
* @since 1.0.0 | |
*/ | |
public function activateLicense() | |
{ | |
if ( $this->verifyRequest( $this->prefix . '_activate' ) ) : | |
$licenseKey = trim( esc_attr( $_REQUEST['license'] ) ); | |
$response = $this->apiRemoteRequest( 'activate_license', $licenseKey ); | |
if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) : | |
if ( is_wp_error( $response ) ) | |
$message = $response->get_error_message(); | |
else | |
$message = esc_html__( 'An error occurred, please try again.', $this->domain ); | |
else : | |
$license = json_decode( wp_remote_retrieve_body( $response ) ); | |
if ( false === $license->success ) : | |
switch( $license->error ) : | |
case 'expired' : | |
$message = sprintf( | |
esc_html__( 'Your license key expired on %s.', $this->domain ), | |
date_i18n( get_option( 'date_format' ), strtotime( $license->expires, current_time( 'timestamp' ) ) ) | |
); | |
break; | |
case 'revoked' : | |
$message = esc_html__( 'Your license key has been disabled.', $this->domain ); | |
break; | |
case 'missing' : | |
$message = esc_html__( 'Invalid license.', $this->domain ); | |
break; | |
case 'invalid' : | |
case 'site_inactive' : | |
$message = esc_html__( 'Your license is not active for this URL.', $this->domain ); | |
break; | |
case 'item_name_mismatch' : | |
$message = sprintf( | |
esc_html__( 'This appears to be an invalid license key for %s.', $this->domain ), | |
$this->args->args['item_name'] | |
); | |
break; | |
case 'no_activations_left': | |
$message = esc_html__( 'Your license key has reached its activation limit.', $this->domain ); | |
break; | |
default : | |
$message = esc_html__( 'An error occurred, please try again.', $this->domain ); | |
break; | |
endswitch; | |
endif; | |
endif; | |
if ( isset( $message ) ) : | |
wp_send_json( (object) [ 'failed' => $message ] ); | |
wp_die(); | |
endif; | |
update_option( esc_attr( $this->prefix . '_license_status' ), $license->license ); | |
update_option( esc_attr( $this->prefix . '_license_key' ), $licenseKey ); | |
$this->clearCaches(); | |
endif; | |
wp_send_json( (object) [ 'success' => $this->getMessage()->success ] ); | |
wp_die(); | |
} // end activateLicense | |
/** | |
* Deactivate the license | |
* | |
* @since 1.0.0 | |
*/ | |
public function deactivateLicense() | |
{ | |
if ( $this->verifyRequest( $this->prefix . '_deactivate' ) ) : | |
$response = $this->apiRemoteRequest( 'deactivate_license', $this->licenseKey ); | |
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.' ); | |
if ( isset( $message ) ) : | |
wp_send_json( (object) [ 'failed' => $message ] ); | |
wp_die(); | |
endif; | |
endif; | |
$licenseData = json_decode( wp_remote_retrieve_body( $response ) ); | |
if( $licenseData->license == 'deactivated' ) : | |
delete_option( esc_attr( $this->prefix . '_license_status' ) ); | |
delete_option( esc_attr( $this->prefix . '_license_key' ) ); | |
$this->clearCaches(); | |
endif; | |
endif; | |
wp_send_json( (object) [ 'delete' => $this->getMessage()->delete ] ); | |
wp_die(); | |
} // end deactivateLicense | |
/** | |
* Clear EDD and plugin caches | |
* | |
* @since 1.0.0 | |
*/ | |
public function clearCaches() | |
{ | |
$slug = basename( $this->args->file, '.php' ); | |
$beta = empty( $this->args->args['beta'] ) ? false : true; | |
$key = md5( serialize( $slug . $this->args->args['license'] . $beta ) ); | |
$key2 = md5( serialize( $slug . $beta ) ); | |
delete_option( esc_attr( '_site_transient_update_plugins' ) ); | |
delete_option( esc_attr( 'edd_api_request_' . $key2 ) ); | |
delete_option( esc_attr( 'edd_api_request_' . $key ) ); | |
delete_option( esc_attr( $key2 ) ); | |
delete_option( esc_attr( $key ) ); | |
} // end clearCaches | |
/** | |
* Api remote request | |
* | |
* @since 1.0.0 | |
*/ | |
public function apiRemoteRequest( $request, $license ) | |
{ | |
$args = | |
[ | |
'url' => home_url(), | |
'license' => $license, | |
'edd_action' => $request, | |
'item_name' => urlencode( $this->args->args['item_name'] ), | |
]; | |
return wp_remote_post( $this->args->url, array( 'timeout' => 15, 'sslverify' => false, 'body' => $args ) ); | |
} // end apiRemoteRequest | |
/** | |
* Enqueue scripts | |
* | |
* @since 1.0.0 | |
*/ | |
public function enqueueScript( $slug, $dep, $footer = true ) | |
{ | |
$assets = plugin_dir_path( $this->args->file ) . 'assets/'; | |
wp_enqueue_script( $slug, $assets . 'js/' . $slug . 'min' . '.js', $dep, $this->args->args['version'], $footer ); | |
} // end enqueueScript | |
} // end class | |
} // end if |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment