Skip to content

Commit

Permalink
OXDEV-7456: Throw exception if no setting was changes and add value e…
Browse files Browse the repository at this point in the history
…ncoding
  • Loading branch information
MarcelOxid committed Nov 14, 2023
1 parent 41bc986 commit 39687c2
Show file tree
Hide file tree
Showing 9 changed files with 136 additions and 40 deletions.
19 changes: 14 additions & 5 deletions src/Setting/Infrastructure/AbstractDatabaseSettingRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace OxidEsales\GraphQL\ConfigurationAccess\Setting\Infrastructure;

use Doctrine\DBAL\Query\QueryBuilder;
use OxidEsales\EshopCommunity\Internal\Framework\Config\Utility\ShopSettingEncoderInterface;
use OxidEsales\EshopCommunity\Internal\Framework\Database\QueryBuilderFactoryInterface;
use OxidEsales\EshopCommunity\Internal\Framework\Theme\Event\ThemeSettingChangedEvent;
use OxidEsales\EshopCommunity\Internal\Transition\Utility\BasicContextInterface;
Expand All @@ -18,16 +18,22 @@ abstract class AbstractDatabaseSettingRepository
public function __construct(
private BasicContextInterface $basicContext,
private EventDispatcherInterface $eventDispatcher,
private QueryBuilderFactoryInterface $queryBuilderFactory
private QueryBuilderFactoryInterface $queryBuilderFactory,
protected ShopSettingEncoderInterface $shopSettingEncoder
) {
}

protected function throwNotFoundException(string $typeString)
protected function throwGetterNotFoundException(string $typeString)
{
$aOrAn = (preg_match('/^[aeiou]/i', $typeString)) ? 'an' : 'a';
throw new NotFound("The queried name couldn't be found as $aOrAn $typeString configuration");
}

protected function throwSetterNotFoundException(string $typeString, string $name)
{
throw new NotFound('The ' . $typeString . ' setting "' . $name . '" doesn\'t exist');
}

protected function isFloatString(string $number): bool
{
return is_numeric($number) && str_contains($number, '.') !== false;
Expand Down Expand Up @@ -88,7 +94,7 @@ protected function getSettingTypes(string $theme = ''): array
return $value;
}

protected function saveSettingValue(ID $name, string $themeId, mixed $value): void
protected function saveSettingValue(ID $name, string $themeId, string $value): void
{
$shopId = $this->basicContext->getCurrentShopId();

Expand All @@ -106,7 +112,10 @@ protected function saveSettingValue(ID $name, string $themeId, mixed $value): vo
'value' => $value
]);

$queryBuilder->execute();
$affectedRows = $queryBuilder->execute();
if ($affectedRows === 0) {
throw new NotFound('No configurations found for ' . $themeId);
}

$this->eventDispatcher->dispatch(
new ThemeSettingChangedEvent(
Expand Down
14 changes: 7 additions & 7 deletions src/Setting/Infrastructure/ShopSettingRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public function getInteger(ID $name): int
try {
$value = $this->getSettingValue($name, FieldType::NUMBER);
} catch (NotFound $e) {
$this->throwNotFoundException('integer');
$this->throwGetterNotFoundException('integer');
}

if ($this->isFloatString($value)) {
Expand All @@ -36,7 +36,7 @@ public function getFloat(ID $name): float
try {
$value = $this->getSettingValue($name, FieldType::NUMBER);
} catch (NotFound $e) {
$this->throwNotFoundException('float');
$this->throwGetterNotFoundException('float');
}

if (!$this->isFloatString($value)) {
Expand All @@ -51,7 +51,7 @@ public function getBoolean(ID $name): bool
try {
$value = $this->getSettingValue($name, FieldType::BOOLEAN);
} catch (NotFound $e) {
$this->throwNotFoundException('boolean');
$this->throwGetterNotFoundException('boolean');
}

return (bool)$value;
Expand All @@ -62,7 +62,7 @@ public function getString(ID $name): string
try {
$value = $this->getSettingValue($name, FieldType::STRING);
} catch (NotFound $e) {
$this->throwNotFoundException('string');
$this->throwGetterNotFoundException('string');
}

return $value;
Expand All @@ -73,7 +73,7 @@ public function getSelect(ID $name): string
try {
$value = $this->getSettingValue($name, FieldType::SELECT);
} catch (NotFound $e) {
$this->throwNotFoundException('select');
$this->throwGetterNotFoundException('select');
}

return $value;
Expand All @@ -84,7 +84,7 @@ public function getCollection(ID $name): array
try {
$value = $this->getSettingValue($name, FieldType::ARRAY);
} catch (NotFound $e) {
$this->throwNotFoundException('collection');
$this->throwGetterNotFoundException('collection');
}

return unserialize($value);
Expand All @@ -95,7 +95,7 @@ public function getAssocCollection(ID $name): array
try {
$value = $this->getSettingValue($name, FieldType::ASSOCIATIVE_ARRAY);
} catch (NotFound $e) {
$this->throwNotFoundException('associative collection');
$this->throwGetterNotFoundException('associative collection');
}

return unserialize($value);
Expand Down
58 changes: 39 additions & 19 deletions src/Setting/Infrastructure/ThemeSettingRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,87 +18,101 @@ final class ThemeSettingRepository extends AbstractDatabaseSettingRepository imp
{
public function getInteger(ID $name, string $themeId): int
{
$fieldType = FieldType::NUMBER;
try {
$value = $this->getSettingValue($name, FieldType::NUMBER, $themeId);
$encodedValue = $this->getSettingValue($name, $fieldType, $themeId);
} catch (NotFound $e) {
$this->throwNotFoundException('integer');
$this->throwGetterNotFoundException('integer');
}

if ($this->isFloatString($value)) {
if ($this->isFloatString($encodedValue)) {
throw new UnexpectedValueException('The queried configuration was found as a float, not an integer');
}
$value = $this->shopSettingEncoder->decode($fieldType, $encodedValue);

return (int)$value;
}

public function getFloat(ID $name, string $themeId): float
{
$fieldType = FieldType::NUMBER;
try {
$value = $this->getSettingValue($name, FieldType::NUMBER, $themeId);
$encodedValue = $this->getSettingValue($name, $fieldType, $themeId);
} catch (NotFound $e) {
$this->throwNotFoundException('float');
$this->throwGetterNotFoundException('float');
}

if (!$this->isFloatString($value)) {
if (!$this->isFloatString($encodedValue)) {
throw new UnexpectedValueException('The queried configuration was found as an integer, not a float');
}
$value = $this->shopSettingEncoder->decode($fieldType, $encodedValue);

return (float)$value;
}

public function getBoolean(ID $name, string $themeId): bool
{
$fieldType = FieldType::BOOLEAN;
try {
$value = $this->getSettingValue($name, FieldType::BOOLEAN, $themeId);
$encodedValue = $this->getSettingValue($name, $fieldType, $themeId);
} catch (NotFound $e) {
$this->throwNotFoundException('boolean');
$this->throwGetterNotFoundException('boolean');
}
$value = $this->shopSettingEncoder->decode($fieldType, $encodedValue);

return (bool)$value;
}

public function getString(ID $name, string $themeId): string
{
$fieldType = FieldType::STRING;
try {
$value = $this->getSettingValue($name, FieldType::STRING, $themeId);
$encodedValue = $this->getSettingValue($name, $fieldType, $themeId);
} catch (NotFound $e) {
$this->throwNotFoundException('string');
$this->throwGetterNotFoundException('string');
}
$value = $this->shopSettingEncoder->decode($fieldType, $encodedValue);

return $value;
}

public function getSelect(ID $name, string $themeId): string
{
$fieldType = FieldType::SELECT;
try {
$value = $this->getSettingValue($name, FieldType::SELECT, $themeId);
$encodedValue = $this->getSettingValue($name, $fieldType, $themeId);
} catch (NotFound $e) {
$this->throwNotFoundException('select');
$this->throwGetterNotFoundException('select');
}
$value = $this->shopSettingEncoder->decode($fieldType, $encodedValue);

return $value;
}

public function getCollection(ID $name, string $themeId): array
{
$fieldType = FieldType::ARRAY;
try {
$value = $this->getSettingValue($name, FieldType::ARRAY, $themeId);
$encodedValue = $this->getSettingValue($name, $fieldType, $themeId);
} catch (NotFound $e) {
$this->throwNotFoundException('collection');
$this->throwGetterNotFoundException('collection');
}
$value = $this->shopSettingEncoder->decode($fieldType, $encodedValue);

return unserialize($value);
return $value;
}

public function getAssocCollection(ID $name, string $themeId): array
{
$fieldType = FieldType::ASSOCIATIVE_ARRAY;
try {
$value = $this->getSettingValue($name, FieldType::ASSOCIATIVE_ARRAY, $themeId);
$encodedValue = $this->getSettingValue($name, $fieldType, $themeId);
} catch (NotFound $e) {
$this->throwNotFoundException('associative collection');
$this->throwGetterNotFoundException('associative collection');
}
$value = $this->shopSettingEncoder->decode($fieldType, $encodedValue);

return unserialize($value);
return $value;
}

public function getSettingsList(string $themeId): array
Expand All @@ -108,7 +122,13 @@ public function getSettingsList(string $themeId): array

public function saveIntegerSetting(ID $name, int $value, string $themeId): void
{
$this->saveSettingValue($name, $themeId, $value);
$value = $this->shopSettingEncoder->encode(FieldType::NUMBER, $value);

try {
$this->saveSettingValue($name, $themeId, (string)$value);
} catch (NotFound $e) {
$this->throwSetterNotFoundException('integer', $name->val());
}
}

public function saveFloatSetting(ID $name, float $value, string $themeId): void
Expand Down
3 changes: 2 additions & 1 deletion src/Setting/Service/ThemeSettingService.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,9 @@ public function getSettingsList(string $themeId): array
public function changeIntegerSetting(ID $name, int $value, string $themeId): IntegerSetting
{
$this->themeSettingRepository->saveIntegerSetting($name, $value, $themeId);
$integer = $this->themeSettingRepository->getInteger($name, $themeId);

return new IntegerSetting($name, $value);
return new IntegerSetting($name, $integer);
}

public function changeFloatSetting(ID $name, float $value, string $themeId): FloatSetting
Expand Down
36 changes: 36 additions & 0 deletions tests/Integration/Infrastructure/DecoratedShopSettingEncoder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

namespace OxidEsales\GraphQL\ConfigurationAccess\Tests\Integration\Infrastructure;

use OxidEsales\EshopCommunity\Internal\Framework\Config\Utility\ShopSettingEncoder;

/**
* This method is needed to execute en/de-coding and also notice if en/de-coder was executed
*/
class DecoratedShopSettingEncoder extends ShopSettingEncoder
{
private int $encodeCounter = 0;
private int $decodeCounter = 0;

public function encode(string $encodingType, $value)
{
$this->encodeCounter += 1;
return parent::encode($encodingType, $value);
}

public function decode(string $encodingType, $value)
{
$this->decodeCounter += 1;
return parent::decode($encodingType, $value);
}

public function getEncodeCounter(): int
{
return $this->encodeCounter;
}

public function getDecodeCounter(): int
{
return $this->decodeCounter;
}
}
32 changes: 27 additions & 5 deletions tests/Integration/Infrastructure/ThemeSettingRepositoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@

namespace OxidEsales\GraphQL\ConfigurationAccess\Tests\Integration\Infrastructure;

use OxidEsales\EshopCommunity\Internal\Container\ContainerFactory;
use OxidEsales\EshopCommunity\Internal\Framework\Config\Utility\ShopSettingEncoderInterface;
use OxidEsales\EshopCommunity\Internal\Framework\Database\QueryBuilderFactoryInterface;
use OxidEsales\EshopCommunity\Internal\Framework\Theme\Event\ThemeSettingChangedEvent;
use OxidEsales\EshopCommunity\Internal\Transition\Utility\BasicContextInterface;
use OxidEsales\EshopCommunity\Tests\Integration\IntegrationTestCase;
use OxidEsales\GraphQL\Base\Exception\NotFound;
use OxidEsales\GraphQL\ConfigurationAccess\Setting\Enum\FieldType;
use OxidEsales\GraphQL\ConfigurationAccess\Setting\Infrastructure\ThemeSettingRepository;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
Expand All @@ -23,7 +24,6 @@ class ThemeSettingRepositoryTest extends IntegrationTestCase
{
public function testSaveAndGetIntegerSetting(): void
{
$container = ContainerFactory::getInstance()->getContainer();
$configurationChangedEvent = new ThemeSettingChangedEvent(
"coolIntSetting",
1,
Expand All @@ -33,14 +33,16 @@ public function testSaveAndGetIntegerSetting(): void
$eventDispatcher->expects($this->once())
->method('dispatch')
->with($configurationChangedEvent);
$basicContext = $container->get(BasicContextInterface::class);
$basicContext = $this->get(BasicContextInterface::class);
/** @var QueryBuilderFactoryInterface $queryBuilderFactory */
$queryBuilderFactory = $container->get(QueryBuilderFactoryInterface::class);
$queryBuilderFactory = $this->get(QueryBuilderFactoryInterface::class);
$shopSettingEncoder = new DecoratedShopSettingEncoder();

$repository = new ThemeSettingRepository(
$basicContext,
$eventDispatcher,
$queryBuilderFactory
$queryBuilderFactory,
$shopSettingEncoder
);

$uniqueId = uniqid();
Expand All @@ -67,5 +69,25 @@ public function testSaveAndGetIntegerSetting(): void
$integerResult = $repository->getInteger(new ID('coolIntSetting'), 'awesomeTheme');

$this->assertSame(124, $integerResult);
$this->assertSame(1, $shopSettingEncoder->getEncodeCounter());
}

public function testSaveNotExistingSetting(): void
{
$basicContext = $this->get(BasicContextInterface::class);
$eventDispatcher = $this->get(EventDispatcherInterface::class);
$queryBuilderFactory = $this->get(QueryBuilderFactoryInterface::class);
$shopSettingEncoder = $this->get(ShopSettingEncoderInterface::class);

$repository = new ThemeSettingRepository(
$basicContext,
$eventDispatcher,
$queryBuilderFactory,
$shopSettingEncoder
);

$this->expectException(NotFound::class);
$this->expectExceptionMessage('The integer setting "notExistingSetting" doesn\'t exist');
$repository->saveIntegerSetting(new ID('notExistingSetting'), 1234, 'awesomeTheme');
}
}
4 changes: 3 additions & 1 deletion tests/Unit/Infrastructure/ShopSettingRepositoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Doctrine\DBAL\ForwardCompatibility\Result;
use Doctrine\DBAL\Query\QueryBuilder;
use OxidEsales\EshopCommunity\Internal\Framework\Config\Utility\ShopSettingEncoder;
use OxidEsales\EshopCommunity\Internal\Framework\Database\QueryBuilderFactoryInterface;
use OxidEsales\GraphQL\Base\Exception\NotFound;
use OxidEsales\GraphQL\ConfigurationAccess\Setting\Infrastructure\ShopSettingRepository;
Expand Down Expand Up @@ -270,6 +271,7 @@ private function getShopSettingRepository(MockObject|QueryBuilderFactoryInterfac
): ShopSettingRepository {
$basicContextMock = $this->getBasicContextMock(1);
$eventDispatcher = $this->createMock(EventDispatcherInterface::class);
return new ShopSettingRepository($basicContextMock, $eventDispatcher, $queryBuilderFactory);
$shopSettingEncoder = new ShopSettingEncoder();
return new ShopSettingRepository($basicContextMock, $eventDispatcher, $queryBuilderFactory, $shopSettingEncoder);
}
}
Loading

0 comments on commit 39687c2

Please sign in to comment.