Skip to content

Commit

Permalink
OXDEV-8216 Prepared ModuleBlocklistService
Browse files Browse the repository at this point in the history
  • Loading branch information
RahatHameed committed Jul 11, 2024
1 parent d7d3efd commit ba6ff44
Show file tree
Hide file tree
Showing 9 changed files with 204 additions and 9 deletions.
3 changes: 3 additions & 0 deletions module_blocklist.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
modules:
- oe_graphql_base
- oe_graphql_configuration_access
22 changes: 22 additions & 0 deletions src/Module/Exception/ModuleBlockListException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

/**
* Copyright © OXID eSales AG. All rights reserved.
* See LICENSE file for license details.
*/

declare(strict_types=1);

namespace OxidEsales\GraphQL\ConfigurationAccess\Module\Exception;

use OxidEsales\GraphQL\Base\Exception\NotFound;

final class ModuleBlockListException extends NotFound
{
public const EXCEPTION_MESSAGE = "An error occurred while getting module blocklist.";

public function __construct()
{
parent::__construct(self::EXCEPTION_MESSAGE);
}
}
9 changes: 8 additions & 1 deletion src/Module/Infrastructure/ModuleSwitchInfrastructure.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@
use OxidEsales\EshopCommunity\Internal\Transition\Utility\ContextInterface;
use OxidEsales\GraphQL\ConfigurationAccess\Module\Exception\ModuleActivationException;
use OxidEsales\GraphQL\ConfigurationAccess\Module\Exception\ModuleDeactivationException;
use OxidEsales\GraphQL\ConfigurationAccess\Module\Service\ModuleBlocklistServiceInterface;

class ModuleSwitchInfrastructure implements ModuleSwitchInfrastructureInterface
{
public function __construct(
private readonly ContextInterface $context,
private readonly ModuleActivationBridgeInterface $moduleActivationBridge
private readonly ModuleActivationBridgeInterface $moduleActivationBridge,
private readonly ModuleBlocklistServiceInterface $moduleBlocklistService
) {
}

Expand All @@ -42,6 +44,11 @@ public function activateModule(string $moduleId): bool
*/
public function deactivateModule(string $moduleId): bool
{
$moduleBlocklist = $this->moduleBlocklistService->getModuleBlocklist();
if (in_array($moduleId, $moduleBlocklist, true)) {
throw new ModuleDeactivationException();
}

try {
$shopId = $this->context->getCurrentShopId();
$this->moduleActivationBridge->deactivate(moduleId: $moduleId, shopId: $shopId);
Expand Down
36 changes: 36 additions & 0 deletions src/Module/Service/ModuleBlocklistService.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

/**
* Copyright © OXID eSales AG. All rights reserved.
* See LICENSE file for license details.
*/

declare(strict_types=1);

namespace OxidEsales\GraphQL\ConfigurationAccess\Module\Service;

use OxidEsales\GraphQL\ConfigurationAccess\Module\Exception\ModuleBlockListException;
use Symfony\Component\Yaml\Yaml;

class ModuleBlocklistService implements ModuleBlocklistServiceInterface
{
public function __construct(
private readonly string $moduleBlocklist
) {
}

/**
* @inheritDoc
*/
public function getModuleBlocklist(): array
{
try {
$resolvedPath = dirname(__FILE__) . '/' . $this->moduleBlocklist;
$blocklistData = Yaml::parseFile($resolvedPath);
} catch (\Exception $e) {
throw new ModuleBlockListException();
}

return $blocklistData['modules'];
}
}
19 changes: 19 additions & 0 deletions src/Module/Service/ModuleBlocklistServiceInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

/**
* Copyright © OXID eSales AG. All rights reserved.
* See LICENSE file for license details.
*/

namespace OxidEsales\GraphQL\ConfigurationAccess\Module\Service;

use OxidEsales\GraphQL\ConfigurationAccess\Module\Exception\ModuleBlockListException;

interface ModuleBlocklistServiceInterface
{
/**
* @throws ModuleBlockListException
* @return array{int : string}
*/
public function getModuleBlocklist(): array;
}
9 changes: 9 additions & 0 deletions src/Module/services.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
parameters:
oxidesales.graphqlconfigurationaccess.modules_block_list: '../../../module_blocklist.yaml'

services:
_defaults:
public: false
Expand All @@ -15,3 +18,9 @@ services:

OxidEsales\GraphQL\ConfigurationAccess\Module\Service\ModuleSwitchServiceInterface:
class: OxidEsales\GraphQL\ConfigurationAccess\Module\Service\ModuleSwitchService


OxidEsales\GraphQL\ConfigurationAccess\Module\Service\ModuleBlocklistServiceInterface:
class: OxidEsales\GraphQL\ConfigurationAccess\Module\Service\ModuleBlocklistService
arguments:
$moduleBlocklist: '%oxidesales.graphqlconfigurationaccess.modules_block_list%'
27 changes: 27 additions & 0 deletions tests/Unit/Module/Exception/ModuleBlockListExceptionTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

/**
* Copyright © OXID eSales AG. All rights reserved.
* See LICENSE file for license details.
*/

declare(strict_types=1);

namespace OxidEsales\GraphQL\ConfigurationAccess\Tests\Unit\Module\Exception;

use OxidEsales\GraphQL\ConfigurationAccess\Module\Exception\ModuleBlockListException;
use PHPUnit\Framework\TestCase;

/**
* @covers \OxidEsales\GraphQL\ConfigurationAccess\Module\Exception\ModuleBlockListException
*/
final class ModuleBlockListExceptionTest extends TestCase
{
public function testException(): void
{
$exception = new ModuleBlockListException();

$this->assertInstanceOf(ModuleBlockListException::class, $exception);
$this->assertSame(ModuleBlockListException::EXCEPTION_MESSAGE, $exception->getMessage());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

use OxidEsales\EshopCommunity\Internal\Transition\Utility\ContextInterface;
use OxidEsales\GraphQL\ConfigurationAccess\Module\Infrastructure\ModuleSwitchInfrastructure;
use OxidEsales\GraphQL\ConfigurationAccess\Module\Service\ModuleBlocklistServiceInterface;
use OxidEsales\EshopCommunity\Internal\Framework\Module\Setup\Bridge\ModuleActivationBridgeInterface;
use OxidEsales\GraphQL\ConfigurationAccess\Module\Exception\ModuleActivationException;
use OxidEsales\GraphQL\ConfigurationAccess\Module\Exception\ModuleDeactivationException;
Expand All @@ -34,9 +35,15 @@ public function testModuleActivationAndDeactivation(
->method($method)
->with($moduleId, $shopId);

$moduleBlocklistServiceMock = $this->createMock(ModuleBlocklistServiceInterface::class);
$moduleBlocklistServiceMock
->method('getModuleBlocklist')
->willReturn(['randomModuleId']);

$sut = $this->getSut(
context: $this->getContextMock(),
moduleActivationBridge: $moduleActivationBridgeMock
moduleActivationBridge: $moduleActivationBridgeMock,
moduleBlocklistService: $moduleBlocklistServiceMock
);

$result = ($method == 'activate') ? $sut->activateModule($moduleId) : $sut->deactivateModule($moduleId);
Expand All @@ -50,6 +57,7 @@ public function testModuleActivationAndDeactivation(
public function testModuleActivationAndDeactivationExceptions(
string $method,
string $moduleId,
string $blockedModuleId,
mixed $exceptionClass
): void {

Expand All @@ -58,11 +66,17 @@ public function testModuleActivationAndDeactivationExceptions(
->method($method)
->willThrowException(new \Exception());

$moduleBlocklistServiceMock = $this->createMock(ModuleBlocklistServiceInterface::class);
$moduleBlocklistServiceMock
->method('getModuleBlocklist')
->willReturn(["$blockedModuleId"]);

$this->expectException($exceptionClass);
$this->expectExceptionMessage($exceptionClass::EXCEPTION_MESSAGE);

$sut = $this->getSut(
moduleActivationBridge: $moduleActivationBridgeMock
moduleActivationBridge: $moduleActivationBridgeMock,
moduleBlocklistService: $moduleBlocklistServiceMock
);

($method === 'activate') ? $sut->activateModule($moduleId) : $sut->deactivateModule($moduleId);
Expand All @@ -85,30 +99,41 @@ public static function activationDataProvider(): \Generator

public static function exceptionDataProvider(): \Generator
{
$moduleId = uniqid();
yield 'test activate module throws exception' => [
'method' => 'activate',
'moduleId' => uniqid(),
'moduleId' => $moduleId,
'blockedModuleId' => uniqid(),
'exceptionClass' => ModuleActivationException::class,

];

yield 'test deactivate module throws exception' => [
yield 'test deactivate module throws exception when module is not in blockList' => [
'method' => 'deactivate',
'moduleId' => uniqid(),
'moduleId' => $moduleId,
'blockedModuleId' => uniqid(),
'exceptionClass' => ModuleDeactivationException::class,
];

yield 'test deactivate module throws exception when module is present in blockList' => [
'method' => 'deactivate',
'moduleId' => $moduleId,
'blockedModuleId' => $moduleId,
'exceptionClass' => ModuleDeactivationException::class,
];
}

public function getSut(
ContextInterface $context = null,
ModuleActivationBridgeInterface $moduleActivationBridge = null
ModuleActivationBridgeInterface $moduleActivationBridge = null,
ModuleBlocklistServiceInterface $moduleBlocklistService = null
): ModuleSwitchInfrastructure {
return new ModuleSwitchInfrastructure(
context: $context
?? $this->createStub(ContextInterface::class),
moduleActivationBridge: $moduleActivationBridge
?? $this->createStub(ModuleActivationBridgeInterface::class)
?? $this->createStub(ModuleActivationBridgeInterface::class),
moduleBlocklistService: $moduleBlocklistService
?? $this->createStub(ModuleBlocklistServiceInterface::class)
);
}
}
47 changes: 47 additions & 0 deletions tests/Unit/Module/Service/ModuleBlocklistServiceTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

/**
* Copyright © OXID eSales AG. All rights reserved.
* See LICENSE file for license details.
*/

declare(strict_types=1);

namespace OxidEsales\GraphQL\ConfigurationAccess\Tests\Unit\Module\Service;

use org\bovigo\vfs\vfsStream;
use org\bovigo\vfs\vfsStreamDirectory;
use OxidEsales\GraphQL\ConfigurationAccess\Module\Service\ModuleBlocklistService;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Yaml\Yaml;

/**
* @covers \OxidEsales\GraphQL\ConfigurationAccess\Module\Service\ModuleBlocklistService
*/
class ModuleBlocklistServiceTest extends TestCase
{
private vfsStreamDirectory|string $moduleBlocklist;

protected function setUp(): void
{
vfsStream::setup('root');
$this->moduleBlocklist = vfsStream::url('root/moduleBlocklist.yaml');
}

public function testGetModuleBlocklist()
{
$expectedBlocklist = [
'modules' => [
'blockedModuleId1',
'blockedModuleId2',
]
];

file_put_contents($this->moduleBlocklist, Yaml::dump($expectedBlocklist));

$sut = new ModuleBlocklistService($this->moduleBlocklist);
$actualBlocklist = $sut->getModuleBlocklist();

$this->assertSame($expectedBlocklist['modules'], $actualBlocklist);
}
}

0 comments on commit ba6ff44

Please sign in to comment.