diff --git a/lib/API/JSON/v1/Services.php b/lib/API/JSON/v1/Services.php
index 555bae77a9..d2078c0ba1 100644
--- a/lib/API/JSON/v1/Services.php
+++ b/lib/API/JSON/v1/Services.php
@@ -3,6 +3,7 @@ namespace MailPoet\API\JSON\v1;
use MailPoet\API\JSON\Endpoint as APIEndpoint;
use MailPoet\API\JSON\Error as APIError;
+use MailPoet\Config\Installer;
use MailPoet\Services\Bridge;
use MailPoet\Util\License\License;
use MailPoet\WP\DateTime;
@@ -97,10 +98,9 @@ class Services extends APIEndpoint {
}
if($success_message) {
- $premium_plugin_active = License::getLicense();
return $this->successResponse(
array('message' => $success_message),
- array('premium_plugin_active' => $premium_plugin_active)
+ Installer::getPremiumStatus()
);
}
@@ -122,4 +122,4 @@ class Services extends APIEndpoint {
return $this->errorResponse(array(APIError::BAD_REQUEST => $error));
}
-}
\ No newline at end of file
+}
diff --git a/lib/Config/Initializer.php b/lib/Config/Initializer.php
index f9b8abfa8c..743d010dbe 100644
--- a/lib/Config/Initializer.php
+++ b/lib/Config/Initializer.php
@@ -75,6 +75,7 @@ class Initializer {
try {
$this->maybeDbUpdate();
$this->setupRenderer();
+ $this->setupInstaller();
$this->setupLocalizer();
$this->setupMenu();
$this->setupAnalytics();
@@ -136,6 +137,13 @@ class Initializer {
$this->renderer = new Renderer($caching, $debugging);
}
+ function setupInstaller() {
+ $installer = new Installer(
+ Installer::PREMIUM_PLUGIN_SLUG
+ );
+ $installer->init();
+ }
+
function setupLocalizer() {
$localizer = new Localizer($this->renderer);
$localizer->init();
diff --git a/lib/Config/Installer.php b/lib/Config/Installer.php
new file mode 100644
index 0000000000..696a56b3ad
--- /dev/null
+++ b/lib/Config/Installer.php
@@ -0,0 +1,116 @@
+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;
+ }
+}
diff --git a/lib/Config/Menu.php b/lib/Config/Menu.php
index 0072f29d73..42bcdb86ad 100644
--- a/lib/Config/Menu.php
+++ b/lib/Config/Menu.php
@@ -350,6 +350,8 @@ class Menu {
)
);
+ $data = array_merge($data, Installer::getPremiumStatus());
+
$this->displayPage('settings.html', $data);
}
diff --git a/tests/unit/API/JSON/v1/ServicesTest.php b/tests/unit/API/JSON/v1/ServicesTest.php
index 568181a75c..f0ee1a580f 100644
--- a/tests/unit/API/JSON/v1/ServicesTest.php
+++ b/tests/unit/API/JSON/v1/ServicesTest.php
@@ -3,6 +3,7 @@
use Codeception\Util\Stub;
use MailPoet\API\JSON\v1\Services;
use MailPoet\API\JSON\Response as APIResponse;
+use MailPoet\Config\Installer;
use MailPoet\Services\Bridge;
class ServicesTest extends MailPoetTest {
@@ -89,6 +90,9 @@ class ServicesTest extends MailPoetTest {
);
$response = $this->services_endpoint->checkPremiumKey($this->data);
expect($response->status)->equals(APIResponse::STATUS_OK);
+ foreach (array_keys(Installer::getPremiumStatus()) as $key) {
+ expect(isset($response->meta[$key]))->true();
+ }
}
function testItRespondsWithErrorIfPremiumKeyIsInvalid() {
diff --git a/tests/unit/Config/InstallerTest.php b/tests/unit/Config/InstallerTest.php
new file mode 100644
index 0000000000..edae3b0cd7
--- /dev/null
+++ b/tests/unit/Config/InstallerTest.php
@@ -0,0 +1,70 @@
+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=');
+ }
+}
diff --git a/tests/unit/Services/BridgeTest.php b/tests/unit/Services/BridgeTest.php
index 3090d1f348..18fdeb4098 100644
--- a/tests/unit/Services/BridgeTest.php
+++ b/tests/unit/Services/BridgeTest.php
@@ -77,23 +77,33 @@ class BridgeTest extends MailPoetTest {
expect($this->getMSSKey())->notEquals($this->valid_key);
}
- function testItChecksPremiumKey() {
+ function testItChecksValidPremiumKey() {
$result = $this->bridge->checkPremiumKey($this->valid_key);
expect($result)->notEmpty();
expect($result['state'])->equals(Bridge::PREMIUM_KEY_VALID);
+ expect($this->getPremiumKey())->equals($this->valid_key);
+ }
+ function testItChecksInvalidPremiumKey() {
$result = $this->bridge->checkPremiumKey($this->invalid_key);
expect($result)->notEmpty();
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);
expect($result)->notEmpty();
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);
expect($result)->notEmpty();
expect($result['state'])->equals(Bridge::PREMIUM_KEY_EXPIRING);
expect($result['data']['expire_at'])->notEmpty();
+ expect($this->getPremiumKey())->equals($this->expiring_premium_key);
}
function testItReturnsErrorStateOnEmptyAPIResponseCodeDuringPremiumCheck() {
@@ -102,6 +112,7 @@ class BridgeTest extends MailPoetTest {
$result = $this->bridge->checkPremiumKey($this->valid_key);
expect($result)->notEmpty();
expect($result['state'])->equals(Bridge::PREMIUM_KEY_CHECK_ERROR);
+ expect($this->getPremiumKey())->notEquals($this->valid_key);
}
function testItUpdatesSubscriberCount() {
@@ -169,6 +180,10 @@ class BridgeTest extends MailPoetTest {
);
}
+ private function getPremiumKey() {
+ return Setting::getValue(Bridge::PREMIUM_KEY_SETTING_NAME);
+ }
+
function _after() {
ORM::raw_execute('TRUNCATE ' . Setting::$_table);
}
diff --git a/views/settings/premium.html b/views/settings/premium.html
index 3eaea8b595..53dae30961 100644
--- a/views/settings/premium.html
+++ b/views/settings/premium.html
@@ -47,11 +47,15 @@