Add Premium installation/activation UI [PREMIUM-9]
This commit is contained in:
@ -3,6 +3,7 @@ namespace MailPoet\API\JSON\v1;
|
|||||||
|
|
||||||
use MailPoet\API\JSON\Endpoint as APIEndpoint;
|
use MailPoet\API\JSON\Endpoint as APIEndpoint;
|
||||||
use MailPoet\API\JSON\Error as APIError;
|
use MailPoet\API\JSON\Error as APIError;
|
||||||
|
use MailPoet\Config\Installer;
|
||||||
use MailPoet\Services\Bridge;
|
use MailPoet\Services\Bridge;
|
||||||
use MailPoet\Util\License\License;
|
use MailPoet\Util\License\License;
|
||||||
use MailPoet\WP\DateTime;
|
use MailPoet\WP\DateTime;
|
||||||
@ -97,10 +98,9 @@ class Services extends APIEndpoint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if($success_message) {
|
if($success_message) {
|
||||||
$premium_plugin_active = License::getLicense();
|
|
||||||
return $this->successResponse(
|
return $this->successResponse(
|
||||||
array('message' => $success_message),
|
array('message' => $success_message),
|
||||||
array('premium_plugin_active' => $premium_plugin_active)
|
Installer::getPremiumStatus()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,6 +75,7 @@ class Initializer {
|
|||||||
try {
|
try {
|
||||||
$this->maybeDbUpdate();
|
$this->maybeDbUpdate();
|
||||||
$this->setupRenderer();
|
$this->setupRenderer();
|
||||||
|
$this->setupInstaller();
|
||||||
$this->setupLocalizer();
|
$this->setupLocalizer();
|
||||||
$this->setupMenu();
|
$this->setupMenu();
|
||||||
$this->setupAnalytics();
|
$this->setupAnalytics();
|
||||||
@ -136,6 +137,13 @@ class Initializer {
|
|||||||
$this->renderer = new Renderer($caching, $debugging);
|
$this->renderer = new Renderer($caching, $debugging);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setupInstaller() {
|
||||||
|
$installer = new Installer(
|
||||||
|
Installer::PREMIUM_PLUGIN_SLUG
|
||||||
|
);
|
||||||
|
$installer->init();
|
||||||
|
}
|
||||||
|
|
||||||
function setupLocalizer() {
|
function setupLocalizer() {
|
||||||
$localizer = new Localizer($this->renderer);
|
$localizer = new Localizer($this->renderer);
|
||||||
$localizer->init();
|
$localizer->init();
|
||||||
|
116
lib/Config/Installer.php
Normal file
116
lib/Config/Installer.php
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
<?php
|
||||||
|
namespace MailPoet\Config;
|
||||||
|
|
||||||
|
use MailPoet\Util\License\License;
|
||||||
|
|
||||||
|
if(!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
|
class Installer {
|
||||||
|
const PREMIUM_PLUGIN_SLUG = 'mailpoet-premium';
|
||||||
|
|
||||||
|
private $slug;
|
||||||
|
|
||||||
|
function __construct($slug) {
|
||||||
|
$this->slug = $slug;
|
||||||
|
}
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
add_filter('plugins_api', array($this, 'getPluginInfo'), 10, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPluginInfo($data, $action = '', $args = null) {
|
||||||
|
if($action === 'plugin_information'
|
||||||
|
&& isset($args->slug)
|
||||||
|
&& $args->slug === $this->slug
|
||||||
|
) {
|
||||||
|
$data = $this->retrievePluginInformation();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static function getPremiumStatus() {
|
||||||
|
$slug = self::PREMIUM_PLUGIN_SLUG;
|
||||||
|
|
||||||
|
$premium_plugin_active = License::getLicense();
|
||||||
|
$premium_plugin_installed = $premium_plugin_active || self::isPluginInstalled($slug);
|
||||||
|
$premium_install_url = $premium_plugin_installed ? '' : self::getPluginInstallUrl($slug);
|
||||||
|
$premium_activate_url = $premium_plugin_active ? '' : self::getPluginActivateUrl($slug);
|
||||||
|
|
||||||
|
return compact(
|
||||||
|
'premium_plugin_active',
|
||||||
|
'premium_plugin_installed',
|
||||||
|
'premium_install_url',
|
||||||
|
'premium_activate_url'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static function isPluginInstalled($slug) {
|
||||||
|
$installed_plugin = self::getInstalledPlugin($slug);
|
||||||
|
return !empty($installed_plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
static function getPluginInstallUrl($slug) {
|
||||||
|
$install_url = add_query_arg(
|
||||||
|
array(
|
||||||
|
'action' => 'install-plugin',
|
||||||
|
'plugin' => $slug,
|
||||||
|
'_wpnonce' => wp_create_nonce('install-plugin_' . $slug),
|
||||||
|
),
|
||||||
|
self_admin_url('update.php')
|
||||||
|
);
|
||||||
|
return $install_url;
|
||||||
|
}
|
||||||
|
|
||||||
|
static function getPluginActivateUrl($slug) {
|
||||||
|
$plugin_file = self::getPluginFile($slug);
|
||||||
|
if(empty($plugin_file)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$activate_url = add_query_arg(
|
||||||
|
array(
|
||||||
|
'action' => 'activate',
|
||||||
|
'plugin' => $plugin_file,
|
||||||
|
'_wpnonce' => wp_create_nonce('activate-plugin_' . $plugin_file),
|
||||||
|
),
|
||||||
|
self_admin_url('plugins.php')
|
||||||
|
);
|
||||||
|
return $activate_url;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function getInstalledPlugin($slug) {
|
||||||
|
$installed_plugin = array();
|
||||||
|
if(is_dir(WP_PLUGIN_DIR . '/' . $slug)) {
|
||||||
|
$installed_plugin = get_plugins('/' . $slug);
|
||||||
|
}
|
||||||
|
return $installed_plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function getPluginFile($slug) {
|
||||||
|
$plugin_file = false;
|
||||||
|
$installed_plugin = self::getInstalledPlugin($slug);
|
||||||
|
if(!empty($installed_plugin)) {
|
||||||
|
$plugin_file = $slug . '/' . key($installed_plugin);
|
||||||
|
}
|
||||||
|
return $plugin_file;
|
||||||
|
}
|
||||||
|
|
||||||
|
function retrievePluginInformation() {
|
||||||
|
$obj = new \stdClass();
|
||||||
|
$obj->slug = $this->slug;
|
||||||
|
$obj->plugin_name = 'MailPoet Premium';
|
||||||
|
$obj->new_version = '3.0.0-alpha.0.0.3.1';
|
||||||
|
$obj->requires = '4.6';
|
||||||
|
$obj->tested = '4.7.4';
|
||||||
|
$obj->downloaded = 12540;
|
||||||
|
$obj->last_updated = date('Y-m-d');
|
||||||
|
$obj->sections = array(
|
||||||
|
'description' => 'The new version of the Premium plugin',
|
||||||
|
'another_section' => 'This is another section',
|
||||||
|
'changelog' => 'Some new features'
|
||||||
|
);
|
||||||
|
$obj->download_link = home_url() . '/wp-content/uploads/mailpoet-premium.zip';
|
||||||
|
$obj->package = $obj->download_link;
|
||||||
|
return $obj;
|
||||||
|
}
|
||||||
|
}
|
@ -350,6 +350,8 @@ class Menu {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$data = array_merge($data, Installer::getPremiumStatus());
|
||||||
|
|
||||||
$this->displayPage('settings.html', $data);
|
$this->displayPage('settings.html', $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
use Codeception\Util\Stub;
|
use Codeception\Util\Stub;
|
||||||
use MailPoet\API\JSON\v1\Services;
|
use MailPoet\API\JSON\v1\Services;
|
||||||
use MailPoet\API\JSON\Response as APIResponse;
|
use MailPoet\API\JSON\Response as APIResponse;
|
||||||
|
use MailPoet\Config\Installer;
|
||||||
use MailPoet\Services\Bridge;
|
use MailPoet\Services\Bridge;
|
||||||
|
|
||||||
class ServicesTest extends MailPoetTest {
|
class ServicesTest extends MailPoetTest {
|
||||||
@ -89,6 +90,9 @@ class ServicesTest extends MailPoetTest {
|
|||||||
);
|
);
|
||||||
$response = $this->services_endpoint->checkPremiumKey($this->data);
|
$response = $this->services_endpoint->checkPremiumKey($this->data);
|
||||||
expect($response->status)->equals(APIResponse::STATUS_OK);
|
expect($response->status)->equals(APIResponse::STATUS_OK);
|
||||||
|
foreach (array_keys(Installer::getPremiumStatus()) as $key) {
|
||||||
|
expect(isset($response->meta[$key]))->true();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function testItRespondsWithErrorIfPremiumKeyIsInvalid() {
|
function testItRespondsWithErrorIfPremiumKeyIsInvalid() {
|
||||||
|
70
tests/unit/Config/InstallerTest.php
Normal file
70
tests/unit/Config/InstallerTest.php
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Codeception\Util\Stub;
|
||||||
|
use MailPoet\Config\Env;
|
||||||
|
use MailPoet\Config\Installer;
|
||||||
|
|
||||||
|
class InstallerTest extends MailPoetTest {
|
||||||
|
function _before() {
|
||||||
|
$this->slug = 'some-plugin';
|
||||||
|
|
||||||
|
$this->installer = new Installer(
|
||||||
|
$this->slug
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItInitializes() {
|
||||||
|
$installer = Stub::make(
|
||||||
|
$this->installer,
|
||||||
|
array(
|
||||||
|
'getPluginInfo' => Stub::once()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$installer->init();
|
||||||
|
apply_filters('plugins_api', null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItGetsPluginInfo() {
|
||||||
|
$args = new \StdClass;
|
||||||
|
$args->slug = $this->slug;
|
||||||
|
$result = $this->installer->getPluginInfo(false, 'plugin_information', $args);
|
||||||
|
expect($result->slug)->equals($this->slug);
|
||||||
|
expect($result->new_version)->notEmpty();
|
||||||
|
expect($result->download_link)->notEmpty();
|
||||||
|
expect($result->package)->notEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItIgnoresNonMatchingRequestsWhenGettingPluginInfo() {
|
||||||
|
$data = new \StdClass;
|
||||||
|
$data->some_property = '123';
|
||||||
|
$result = $this->installer->getPluginInfo($data, 'some_action', null);
|
||||||
|
expect($result)->equals($data);
|
||||||
|
$args = new \StdClass;
|
||||||
|
$args->slug = 'different-slug';
|
||||||
|
$result = $this->installer->getPluginInfo($data, 'plugin_information', $args);
|
||||||
|
expect($result)->equals($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItGetsPremiumStatus() {
|
||||||
|
$status = Installer::getPremiumStatus();
|
||||||
|
expect(isset($status['premium_plugin_active']))->true();
|
||||||
|
expect(isset($status['premium_plugin_installed']))->true();
|
||||||
|
expect(isset($status['premium_install_url']))->true();
|
||||||
|
expect(isset($status['premium_activate_url']))->true();
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItChecksIfAPluginIsInstalled() {
|
||||||
|
expect(Installer::isPluginInstalled(Env::$plugin_name))->true();
|
||||||
|
expect(Installer::isPluginInstalled('some-non-existent-plugin-123'))->false();
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItGetsPluginInstallUrl() {
|
||||||
|
expect(Installer::getPluginInstallUrl(Env::$plugin_name))
|
||||||
|
->startsWith(home_url() . '/wp-admin/update.php?action=install-plugin&plugin=mailpoet&_wpnonce=');
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItGetsPluginActivateUrl() {
|
||||||
|
expect(Installer::getPluginActivateUrl(Env::$plugin_name))
|
||||||
|
->startsWith(home_url() . '/wp-admin/plugins.php?action=activate&plugin=mailpoet/mailpoet.php&_wpnonce=');
|
||||||
|
}
|
||||||
|
}
|
@ -77,23 +77,33 @@ class BridgeTest extends MailPoetTest {
|
|||||||
expect($this->getMSSKey())->notEquals($this->valid_key);
|
expect($this->getMSSKey())->notEquals($this->valid_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testItChecksPremiumKey() {
|
function testItChecksValidPremiumKey() {
|
||||||
$result = $this->bridge->checkPremiumKey($this->valid_key);
|
$result = $this->bridge->checkPremiumKey($this->valid_key);
|
||||||
expect($result)->notEmpty();
|
expect($result)->notEmpty();
|
||||||
expect($result['state'])->equals(Bridge::PREMIUM_KEY_VALID);
|
expect($result['state'])->equals(Bridge::PREMIUM_KEY_VALID);
|
||||||
|
expect($this->getPremiumKey())->equals($this->valid_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItChecksInvalidPremiumKey() {
|
||||||
$result = $this->bridge->checkPremiumKey($this->invalid_key);
|
$result = $this->bridge->checkPremiumKey($this->invalid_key);
|
||||||
expect($result)->notEmpty();
|
expect($result)->notEmpty();
|
||||||
expect($result['state'])->equals(Bridge::PREMIUM_KEY_INVALID);
|
expect($result['state'])->equals(Bridge::PREMIUM_KEY_INVALID);
|
||||||
|
expect($this->getPremiumKey())->equals($this->invalid_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItChecksAlreadyUsedPremiumKey() {
|
||||||
$result = $this->bridge->checkPremiumKey($this->used_premium_key);
|
$result = $this->bridge->checkPremiumKey($this->used_premium_key);
|
||||||
expect($result)->notEmpty();
|
expect($result)->notEmpty();
|
||||||
expect($result['state'])->equals(Bridge::PREMIUM_KEY_ALREADY_USED);
|
expect($result['state'])->equals(Bridge::PREMIUM_KEY_ALREADY_USED);
|
||||||
|
expect($this->getPremiumKey())->equals($this->used_premium_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItChecksExpiringPremiumKey() {
|
||||||
$result = $this->bridge->checkPremiumKey($this->expiring_premium_key);
|
$result = $this->bridge->checkPremiumKey($this->expiring_premium_key);
|
||||||
expect($result)->notEmpty();
|
expect($result)->notEmpty();
|
||||||
expect($result['state'])->equals(Bridge::PREMIUM_KEY_EXPIRING);
|
expect($result['state'])->equals(Bridge::PREMIUM_KEY_EXPIRING);
|
||||||
expect($result['data']['expire_at'])->notEmpty();
|
expect($result['data']['expire_at'])->notEmpty();
|
||||||
|
expect($this->getPremiumKey())->equals($this->expiring_premium_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testItReturnsErrorStateOnEmptyAPIResponseCodeDuringPremiumCheck() {
|
function testItReturnsErrorStateOnEmptyAPIResponseCodeDuringPremiumCheck() {
|
||||||
@ -102,6 +112,7 @@ class BridgeTest extends MailPoetTest {
|
|||||||
$result = $this->bridge->checkPremiumKey($this->valid_key);
|
$result = $this->bridge->checkPremiumKey($this->valid_key);
|
||||||
expect($result)->notEmpty();
|
expect($result)->notEmpty();
|
||||||
expect($result['state'])->equals(Bridge::PREMIUM_KEY_CHECK_ERROR);
|
expect($result['state'])->equals(Bridge::PREMIUM_KEY_CHECK_ERROR);
|
||||||
|
expect($this->getPremiumKey())->notEquals($this->valid_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testItUpdatesSubscriberCount() {
|
function testItUpdatesSubscriberCount() {
|
||||||
@ -169,6 +180,10 @@ class BridgeTest extends MailPoetTest {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function getPremiumKey() {
|
||||||
|
return Setting::getValue(Bridge::PREMIUM_KEY_SETTING_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
function _after() {
|
function _after() {
|
||||||
ORM::raw_execute('TRUNCATE ' . Setting::$_table);
|
ORM::raw_execute('TRUNCATE ' . Setting::$_table);
|
||||||
}
|
}
|
||||||
|
@ -47,11 +47,15 @@
|
|||||||
<br/>
|
<br/>
|
||||||
<div
|
<div
|
||||||
class="mailpoet_premium_download"
|
class="mailpoet_premium_download"
|
||||||
<% if premium_plugin_active or not(premium_key_valid) %>
|
<% if premium_plugin_installed or not(premium_key_valid) %>
|
||||||
style="display: none;"
|
style="display: none;"
|
||||||
<% endif %>
|
<% endif %>
|
||||||
>
|
>
|
||||||
<a class="button-primary" href="#"><%= __('Download Premium now.') %></a>
|
<a
|
||||||
|
class="mailpoet_premium_install_link button-primary"
|
||||||
|
href="<%= premium_install_url | default('#') %>"
|
||||||
|
><%= __('Install Premium now.') %>
|
||||||
|
</a>
|
||||||
<span>
|
<span>
|
||||||
<%= __("[link]Read guide[/link] on how to install Premium.")
|
<%= __("[link]Read guide[/link] on how to install Premium.")
|
||||||
|replace({
|
|replace({
|
||||||
@ -62,6 +66,18 @@
|
|||||||
%>
|
%>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
class="mailpoet_premium_activate"
|
||||||
|
<% if not(premium_plugin_installed) or premium_plugin_active or not(premium_key_valid) %>
|
||||||
|
style="display: none;"
|
||||||
|
<% endif %>
|
||||||
|
>
|
||||||
|
<span><%= __('You need to activate the MailPoet Premium plugin.') %></span>
|
||||||
|
<a
|
||||||
|
class="mailpoet_premium_activate_link button-primary"
|
||||||
|
href="<%= premium_activate_url | default('#') %>"
|
||||||
|
><%= __('Activate Premium.') %></a>
|
||||||
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
@ -98,7 +114,7 @@
|
|||||||
|
|
||||||
function verifyMailPoetPremiumKey(key) {
|
function verifyMailPoetPremiumKey(key) {
|
||||||
$('.mailpoet_premium_key_valid, .mailpoet_premium_key_invalid').addClass('mailpoet_hidden');
|
$('.mailpoet_premium_key_valid, .mailpoet_premium_key_invalid').addClass('mailpoet_hidden');
|
||||||
$('.mailpoet_premium_download').hide();
|
$('.mailpoet_premium_download, .mailpoet_premium_activate').hide();
|
||||||
|
|
||||||
return MailPoet.Ajax.post({
|
return MailPoet.Ajax.post({
|
||||||
api_version: window.mailpoet_api_version,
|
api_version: window.mailpoet_api_version,
|
||||||
@ -112,8 +128,14 @@
|
|||||||
$('.mailpoet_notice_server').hide();
|
$('.mailpoet_notice_server').hide();
|
||||||
$('.mailpoet_premium_key_valid').text(response.data.message);
|
$('.mailpoet_premium_key_valid').text(response.data.message);
|
||||||
$('.mailpoet_premium_key_valid').removeClass('mailpoet_hidden');
|
$('.mailpoet_premium_key_valid').removeClass('mailpoet_hidden');
|
||||||
if (!response.meta.premium_plugin_active) {
|
if (!response.meta.premium_plugin_installed) {
|
||||||
|
$('.mailpoet_premium_install_link')
|
||||||
|
.attr('href', response.meta.premium_install_url || '#');
|
||||||
$('.mailpoet_premium_download').show();
|
$('.mailpoet_premium_download').show();
|
||||||
|
} else if (!response.meta.premium_plugin_active) {
|
||||||
|
$('.mailpoet_premium_activate_link')
|
||||||
|
.attr('href', response.meta.premium_activate_url || '#');
|
||||||
|
$('.mailpoet_premium_activate').show();
|
||||||
}
|
}
|
||||||
}).fail(function(response) {
|
}).fail(function(response) {
|
||||||
if (response.errors.length > 0) {
|
if (response.errors.length > 0) {
|
||||||
|
Reference in New Issue
Block a user