Introduce ContainerWrapper
Container wrapper wraps both premium and free containers and adds ability for free plugin to use premium plugin services directly. [PREMIUM-99]
This commit is contained in:
@@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
namespace MailPoet\API;
|
namespace MailPoet\API;
|
||||||
|
|
||||||
|
use MailPoet\DI\ContainerWrapper;
|
||||||
use MailPoetVendor\Psr\Container\ContainerInterface;
|
use MailPoetVendor\Psr\Container\ContainerInterface;
|
||||||
use MailPoetVendor\Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
|
use MailPoetVendor\Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
|
||||||
use MailPoet\DI\ContainerFactory;
|
|
||||||
|
|
||||||
if(!defined('ABSPATH')) exit;
|
if(!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
@@ -37,8 +37,7 @@ class API {
|
|||||||
*/
|
*/
|
||||||
private static function ensureContainerIsLoaded() {
|
private static function ensureContainerIsLoaded() {
|
||||||
if(!self::$container) {
|
if(!self::$container) {
|
||||||
$factory = new ContainerFactory();
|
self::$container = ContainerWrapper::getInstance();
|
||||||
self::$container = $factory->getContainer();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -3,7 +3,6 @@ namespace MailPoet\API\JSON;
|
|||||||
|
|
||||||
use MailPoet\Config\AccessControl;
|
use MailPoet\Config\AccessControl;
|
||||||
use MailPoetVendor\Psr\Container\ContainerInterface;
|
use MailPoetVendor\Psr\Container\ContainerInterface;
|
||||||
use MailPoetVendor\Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
|
|
||||||
use MailPoet\Models\Setting;
|
use MailPoet\Models\Setting;
|
||||||
use MailPoet\Util\Helpers;
|
use MailPoet\Util\Helpers;
|
||||||
use MailPoet\Util\Security;
|
use MailPoet\Util\Security;
|
||||||
@@ -143,13 +142,7 @@ class API {
|
|||||||
throw new \Exception(__('Invalid API endpoint.', 'mailpoet'));
|
throw new \Exception(__('Invalid API endpoint.', 'mailpoet'));
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
$endpoint = $this->container->get($this->_request_endpoint_class);
|
||||||
$endpoint = $this->container->get($this->_request_endpoint_class);
|
|
||||||
} catch (ServiceNotFoundException $e) {
|
|
||||||
// Hotfix for Premium plugin which adds endpoints which are not registered in DI container
|
|
||||||
$endpoint = new $this->_request_endpoint_class();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!method_exists($endpoint, $this->_request_method)) {
|
if(!method_exists($endpoint, $this->_request_method)) {
|
||||||
throw new \Exception(__('Invalid API endpoint method.', 'mailpoet'));
|
throw new \Exception(__('Invalid API endpoint method.', 'mailpoet'));
|
||||||
}
|
}
|
||||||
|
@@ -4,7 +4,7 @@ namespace MailPoet\Config;
|
|||||||
|
|
||||||
use MailPoet\API;
|
use MailPoet\API;
|
||||||
use MailPoet\Cron\CronTrigger;
|
use MailPoet\Cron\CronTrigger;
|
||||||
use MailPoet\DI\ContainerFactory;
|
use MailPoet\DI\ContainerWrapper;
|
||||||
use MailPoet\Models\Setting;
|
use MailPoet\Models\Setting;
|
||||||
use MailPoet\Router;
|
use MailPoet\Router;
|
||||||
use MailPoet\Util\ConflictResolver;
|
use MailPoet\Util\ConflictResolver;
|
||||||
@@ -97,8 +97,7 @@ class Initializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function loadContainer() {
|
function loadContainer() {
|
||||||
$container_factory = new ContainerFactory(WP_DEBUG);
|
$this->container = ContainerWrapper::getInstance(WP_DEBUG);
|
||||||
$this->container = $container_factory->getContainer();
|
|
||||||
API\API::injectContainer($this->container);
|
API\API::injectContainer($this->container);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
62
lib/DI/ContainerWrapper.php
Normal file
62
lib/DI/ContainerWrapper.php
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace MailPoet\DI;
|
||||||
|
|
||||||
|
use MailPoetVendor\Psr\Container\ContainerInterface;
|
||||||
|
use MailPoetVendor\Psr\Container\NotFoundExceptionInterface;
|
||||||
|
|
||||||
|
class ContainerWrapper implements ContainerInterface {
|
||||||
|
|
||||||
|
/** @var ContainerInterface */
|
||||||
|
private $free_container;
|
||||||
|
|
||||||
|
/** @var ContainerInterface|null */
|
||||||
|
private $premium_container;
|
||||||
|
|
||||||
|
/** @var ContainerWrapper */
|
||||||
|
private static $instance;
|
||||||
|
|
||||||
|
public function __construct(ContainerInterface $free_container, ContainerInterface $premium_container = null) {
|
||||||
|
$this->free_container = $free_container;
|
||||||
|
$this->premium_container = $premium_container;
|
||||||
|
}
|
||||||
|
|
||||||
|
function get($id) {
|
||||||
|
try {
|
||||||
|
return $this->free_container->get($id);
|
||||||
|
} catch (NotFoundExceptionInterface $e) {
|
||||||
|
if(!$this->premium_container) {
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
return $this->premium_container->get($id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function has($id) {
|
||||||
|
return $this->free_container->has($id) || ($this->premium_container && $this->premium_container->has($id));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return ContainerInterface|null
|
||||||
|
*/
|
||||||
|
function getPremiumContainer() {
|
||||||
|
return $this->premium_container;
|
||||||
|
}
|
||||||
|
|
||||||
|
static function getInstance($debug = false) {
|
||||||
|
if(self::$instance) {
|
||||||
|
return self::$instance;
|
||||||
|
}
|
||||||
|
$free_container_factory = new ContainerFactory(new ContainerConfigurator(), $debug);
|
||||||
|
$free_container = $free_container_factory->getContainer();
|
||||||
|
$premium_container = null;
|
||||||
|
if(class_exists(\MailPoet\Premium\DI\ContainerConfigurator::class)) {
|
||||||
|
$premium_container_factory = new ContainerFactory(new \MailPoet\Premium\DI\ContainerConfigurator($free_container), $debug);
|
||||||
|
$premium_container = $premium_container_factory->getContainer();
|
||||||
|
$premium_container->set(IContainerConfigurator::FREE_CONTAINER_SERVICE_SLUG, $free_container);
|
||||||
|
$free_container->set(IContainerConfigurator::PREMIUM_CONTAINER_SERVICE_SLUG, $premium_container);
|
||||||
|
}
|
||||||
|
self::$instance = new ContainerWrapper($free_container, $premium_container);
|
||||||
|
return self::$instance;
|
||||||
|
}
|
||||||
|
}
|
87
tests/unit/DI/ContainerWrapperTest.php
Normal file
87
tests/unit/DI/ContainerWrapperTest.php
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
<?php
|
||||||
|
namespace MailPoet\Test\DI;
|
||||||
|
|
||||||
|
use Codeception\Stub;
|
||||||
|
use MailPoet\DI\ContainerWrapper;
|
||||||
|
use MailPoetVendor\Symfony\Component\DependencyInjection\Container;
|
||||||
|
use MailPoetVendor\Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
|
use MailPoetVendor\Psr\Container\ContainerInterface;
|
||||||
|
use MailPoetVendor\Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
|
||||||
|
|
||||||
|
class ContainerWrapperTest extends \MailPoetUnitTest {
|
||||||
|
function testItCanConstruct() {
|
||||||
|
$instance = new ContainerWrapper(new ContainerBuilder());
|
||||||
|
expect($instance)->isInstanceOf(ContainerWrapper::class);
|
||||||
|
expect($instance)->isInstanceOf(ContainerInterface::class);
|
||||||
|
|
||||||
|
$instance = new ContainerWrapper(new ContainerBuilder(), new ContainerBuilder());
|
||||||
|
expect($instance)->isInstanceOf(ContainerWrapper::class);
|
||||||
|
expect($instance)->isInstanceOf(ContainerInterface::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItProvidesPremiumContainerIfAvailable() {
|
||||||
|
$instance = new ContainerWrapper(new ContainerBuilder());
|
||||||
|
expect($instance->getPremiumContainer())->null();
|
||||||
|
|
||||||
|
$instance = new ContainerWrapper(new ContainerBuilder(), new ContainerBuilder());
|
||||||
|
expect($instance->getPremiumContainer())->isInstanceOf(ContainerBuilder::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItProvidesFreePluginServices() {
|
||||||
|
$free_container_stub = Stub::make(Container::class, [
|
||||||
|
'get' => function () {
|
||||||
|
return 'service';
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
$instance = new ContainerWrapper($free_container_stub);
|
||||||
|
$service = $instance->get('service_id');
|
||||||
|
expect($service)->equals('service');
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItThrowsFreePluginServices() {
|
||||||
|
$free_container_stub = Stub::make(Container::class, [
|
||||||
|
'get' => function ($id) {
|
||||||
|
throw new ServiceNotFoundException($id);
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
$instance = new ContainerWrapper($free_container_stub);
|
||||||
|
$exception = null;
|
||||||
|
try {
|
||||||
|
$instance->get('service');
|
||||||
|
} catch (ServiceNotFoundException $e) {
|
||||||
|
$exception = $e;
|
||||||
|
}
|
||||||
|
expect($exception)->isInstanceOf(ServiceNotFoundException::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItReturnServiceFromPremium() {
|
||||||
|
$free_container_stub = Stub::make(Container::class, [
|
||||||
|
'get' => function ($id) {
|
||||||
|
throw new ServiceNotFoundException($id);
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
$premium_container_stub = Stub::make(Container::class, [
|
||||||
|
'get' => function () {
|
||||||
|
return 'service_1';
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
$instance = new ContainerWrapper($free_container_stub, $premium_container_stub);
|
||||||
|
expect($instance->get('service'))->equals('service_1');
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItThrowsIfServiceNotFoundInBothContainers() {
|
||||||
|
$container_stub = Stub::make(Container::class, [
|
||||||
|
'get' => function ($id) {
|
||||||
|
throw new ServiceNotFoundException($id);
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
$instance = new ContainerWrapper($container_stub, $container_stub);
|
||||||
|
$exception = null;
|
||||||
|
try {
|
||||||
|
$instance->get('service');
|
||||||
|
} catch (ServiceNotFoundException $e) {
|
||||||
|
$exception = $e;
|
||||||
|
}
|
||||||
|
expect($exception)->isInstanceOf(ServiceNotFoundException::class);
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user