Skip to content

Instantly share code, notes, and snippets.

@indikatordesign
Last active August 10, 2018 22:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save indikatordesign/ea2abc30acd1e1478db1244c91738e91 to your computer and use it in GitHub Desktop.
Save indikatordesign/ea2abc30acd1e1478db1244c91738e91 to your computer and use it in GitHub Desktop.
EMP EDD Plugin Updater - Another Approach
(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));
<?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