From 1f4843b92d2abf517ca218a6b64a2bc83d77a2ed Mon Sep 17 00:00:00 2001 From: Mikel Madariaga Date: Fri, 11 Dec 2020 11:38:57 +0100 Subject: [PATCH 01/76] updated for php 7.4 and symfony 5 compatibility --- Domain/Model/TempFileContainnerTrait.php | 10 ++-------- Domain/Service/FileContainerInterface.php | 7 +------ .../Domain/Service/DoctrineEntityPersister.php | 2 +- .../Persistence/Doctrine/LoggableMigration.php | 8 ++++---- .../Symfony/EventListener/DomainExceptionListener.php | 8 ++++---- composer.json | 10 +++++----- 6 files changed, 17 insertions(+), 28 deletions(-) diff --git a/Domain/Model/TempFileContainnerTrait.php b/Domain/Model/TempFileContainnerTrait.php index 4f6d3df..1a8a29d 100755 --- a/Domain/Model/TempFileContainnerTrait.php +++ b/Domain/Model/TempFileContainnerTrait.php @@ -7,26 +7,20 @@ trait TempFileContainnerTrait { /** - * @var TempFile[] + * @var \Ivoz\Core\Domain\Service\TempFile[] */ protected $tmpFiles = []; /** - * @param string $fldName - * @param \Ivoz\Core\Domain\Service\TempFile $file - * * @return void */ - public function addTmpFile($fldName, TempFile $file) + public function addTmpFile(string $fldName, TempFile $file) { $this->tmpFiles[$fldName] = $file; } /** - * @param \Ivoz\Core\Domain\Service\TempFile $file - * * @throws \Exception - * * @return void */ public function removeTmpFile(TempFile $file) diff --git a/Domain/Service/FileContainerInterface.php b/Domain/Service/FileContainerInterface.php index 093dffb..f34ff36 100755 --- a/Domain/Service/FileContainerInterface.php +++ b/Domain/Service/FileContainerInterface.php @@ -12,14 +12,9 @@ interface FileContainerInterface self::UPDALOADABLE_FILE ]; - /** - * @param string $fldName - * @param \Ivoz\Core\Domain\Service\TempFile $file - */ - public function addTmpFile($fldName, TempFile $file); + public function addTmpFile(string $fldName, TempFile $file); /** - * @param \Ivoz\Core\Domain\Service\TempFile $file * @throws \Exception */ public function removeTmpFile(TempFile $file); diff --git a/Infrastructure/Domain/Service/DoctrineEntityPersister.php b/Infrastructure/Domain/Service/DoctrineEntityPersister.php index b839206..9e29710 100755 --- a/Infrastructure/Domain/Service/DoctrineEntityPersister.php +++ b/Infrastructure/Domain/Service/DoctrineEntityPersister.php @@ -330,7 +330,7 @@ private function getDependantEntities(EntityInterface $entity): array foreach ($associations as $field => $association) { $isDeleteCascade = isset($association['joinColumns']) - && $association['joinColumns'][0]['onDelete'] === 'cascade'; + && strtolower($association['joinColumns'][0]['onDelete']) === 'cascade'; if (!$isDeleteCascade) { continue; diff --git a/Infrastructure/Persistence/Doctrine/LoggableMigration.php b/Infrastructure/Persistence/Doctrine/LoggableMigration.php index ae7006f..6999d73 100644 --- a/Infrastructure/Persistence/Doctrine/LoggableMigration.php +++ b/Infrastructure/Persistence/Doctrine/LoggableMigration.php @@ -2,7 +2,7 @@ namespace Ivoz\Core\Infrastructure\Persistence\Doctrine; -use Doctrine\DBAL\Migrations\AbstractMigration; +use Doctrine\Migrations\AbstractMigration;; use Doctrine\DBAL\Schema\Schema; use Ivoz\Core\Application\Event\CommandWasExecuted; use Ivoz\Core\Domain\Event\EntityWasUpdated; @@ -13,13 +13,13 @@ abstract class LoggableMigration extends AbstractMigration { private $queries = []; - public function postUp(Schema $schema) + public function postUp(Schema $schema): void { $this->logChanges('up'); parent::postUp(...func_get_args()); } - public function postDown(Schema $schema) + public function postDown(Schema $schema): void { $this->logChanges('down'); parent::postDown(...func_get_args()); @@ -111,7 +111,7 @@ function ($value) { return $commandQuery; } - protected function addSql($sql, array $params = [], array $types = []) + protected function addSql($sql, array $params = [], array $types = []): void { $this->queries[] = $sql; parent::addSql(...func_get_args()); diff --git a/Infrastructure/Symfony/EventListener/DomainExceptionListener.php b/Infrastructure/Symfony/EventListener/DomainExceptionListener.php index 9501ffc..5d34509 100644 --- a/Infrastructure/Symfony/EventListener/DomainExceptionListener.php +++ b/Infrastructure/Symfony/EventListener/DomainExceptionListener.php @@ -4,17 +4,17 @@ use Assert\InvalidArgumentException; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; +use Symfony\Component\HttpKernel\Event\ExceptionEvent; class DomainExceptionListener { /** - * @param GetResponseForExceptionEvent $event + * @param ExceptionEvent $event * @return void */ - public function onKernelException(GetResponseForExceptionEvent $event) + public function onKernelException(ExceptionEvent $event) { - $exception = $event->getException(); + $exception = $event->getThrowable(); $exceptionClass = get_class($exception); $publicExceptions = [ \DomainException::class, diff --git a/composer.json b/composer.json index e01175d..66b1c68 100644 --- a/composer.json +++ b/composer.json @@ -24,17 +24,17 @@ } }, "require": { - "php": ">=7.0.19", + "php": ">=7.4", "beberlei/assert": "2.9.*", "doctrine/orm": "^2.5", "graze/guzzle-jsonrpc": "3.2.*", "guzzlehttp/guzzle": "^6.3", "lexik/jwt-authentication-bundle": "^2.5", "ramsey/uuid": "^3.7", - "symfony/expression-language": "3.4.*", - "symfony/finder": "3.4.*", - "symfony/http-foundation": "3.4.*", - "symfony/serializer": "3.4.*" + "symfony/expression-language": "^5.1", + "symfony/finder": "^5.1", + "symfony/http-foundation": "^5.1", + "symfony/serializer": "^5.1" }, "require-dev": { } From 06588e3857776284cbbe7826c5406cb58638801f Mon Sep 17 00:00:00 2001 From: Mikel Madariaga Date: Thu, 24 Dec 2020 12:21:36 +0100 Subject: [PATCH 02/76] updated DataTransferObjectInterface --- Application/DataTransferObjectInterface.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Application/DataTransferObjectInterface.php b/Application/DataTransferObjectInterface.php index 434856f..a1dc46e 100755 --- a/Application/DataTransferObjectInterface.php +++ b/Application/DataTransferObjectInterface.php @@ -16,7 +16,7 @@ interface DataTransferObjectInterface self::CONTEXT_DETAILED_COLLECTION ]; - public function setId($id = null); + public function setId(?int $id = null); public function getId(); /** From fbb1d5bb30f2de2c02d444cba2fb966fbd9800b2 Mon Sep 17 00:00:00 2001 From: Mikel Madariaga Date: Thu, 24 Dec 2020 12:22:15 +0100 Subject: [PATCH 03/76] fixed DtoNormalizer --- Application/Model/DtoNormalizer.php | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/Application/Model/DtoNormalizer.php b/Application/Model/DtoNormalizer.php index 3c8f857..b667fdb 100644 --- a/Application/Model/DtoNormalizer.php +++ b/Application/Model/DtoNormalizer.php @@ -32,16 +32,12 @@ public function normalize(string $context, string $role = '') return array_filter( $response, - function ($value, $key) use ($contextProperties) { - - $isEmbedded = is_array($value) || is_object($value); - + function ($key) use ($contextProperties) { return in_array($key, $contextProperties, true) - || (!$isEmbedded && in_array($value, $contextProperties, true)) - || ($isEmbedded && array_key_exists($key, $contextProperties)); + || array_key_exists($key, $contextProperties); }, - ARRAY_FILTER_USE_BOTH + ARRAY_FILTER_USE_KEY ); } From 17126385d3e5dfd467497970f47eec83eec9ec44 Mon Sep 17 00:00:00 2001 From: Mikel Madariaga Date: Tue, 9 Mar 2021 15:34:59 +0100 Subject: [PATCH 04/76] updated Gearman/FakeManager method signature --- Infrastructure/Domain/Service/Gearman/FakeManager.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Infrastructure/Domain/Service/Gearman/FakeManager.php b/Infrastructure/Domain/Service/Gearman/FakeManager.php index 04cb9a7..7c28375 100644 --- a/Infrastructure/Domain/Service/Gearman/FakeManager.php +++ b/Infrastructure/Domain/Service/Gearman/FakeManager.php @@ -8,8 +8,9 @@ public static function getClient() { return new class extends \GearmanClient { - public function doBackground($function_name, $workload, $unique = null) + public function doBackground(string $function, string $workload, ?string $unique = NULL): string { + return ''; } }; } From 98479f80c9071ea2259732cfe4d5edd105b2cd24 Mon Sep 17 00:00:00 2001 From: Mikel Madariaga Date: Fri, 12 Mar 2021 11:52:56 +0100 Subject: [PATCH 05/76] updated doctrine versions --- Application/DataTransferObjectInterface.php | 2 +- Application/Helper/EntityClassHelper.php | 2 +- Application/Helper/LifecycleServiceHelper.php | 2 +- Domain/Service/CommonLifecycleServiceCollection.php | 7 +++---- .../Domain/Service/Lifecycle/DoctrineEventSubscriber.php | 2 +- .../Persistence/Doctrine/Hydration/ObjectHydrator.php | 2 +- .../Doctrine/Hydration/SimpleObjectHydrator.php | 2 +- .../Persistence/Doctrine/ORM/Mapping/QuoteStrategy.php | 2 +- composer.json | 2 +- 9 files changed, 11 insertions(+), 12 deletions(-) diff --git a/Application/DataTransferObjectInterface.php b/Application/DataTransferObjectInterface.php index a1dc46e..73d57fc 100755 --- a/Application/DataTransferObjectInterface.php +++ b/Application/DataTransferObjectInterface.php @@ -16,7 +16,7 @@ interface DataTransferObjectInterface self::CONTEXT_DETAILED_COLLECTION ]; - public function setId(?int $id = null); + public function setId($id); public function getId(); /** diff --git a/Application/Helper/EntityClassHelper.php b/Application/Helper/EntityClassHelper.php index c4c2952..c8abd3d 100755 --- a/Application/Helper/EntityClassHelper.php +++ b/Application/Helper/EntityClassHelper.php @@ -2,7 +2,7 @@ namespace Ivoz\Core\Application\Helper; -use Doctrine\Common\Persistence\Proxy; +use Doctrine\Persistence\Proxy; use Ivoz\Core\Application\DataTransferObjectInterface; use Ivoz\Core\Domain\Model\EntityInterface; diff --git a/Application/Helper/LifecycleServiceHelper.php b/Application/Helper/LifecycleServiceHelper.php index 28de9e6..75eb9d9 100755 --- a/Application/Helper/LifecycleServiceHelper.php +++ b/Application/Helper/LifecycleServiceHelper.php @@ -24,7 +24,7 @@ public static function getServiceNameByEntityFqdn(string $entityClass, string $e $prefix = $classSegments[1]; $entityName = end($classSegments); - $snakeCaseEntity = Inflector::tableize($entityName); + $snakeCaseEntity = strtolower(preg_replace('~(?<=\\w)([A-Z])~', '_$1', $entityName)); $serviceName = $prefix . '.lifecycle.' . $snakeCaseEntity . '.' . $event; return strtolower($serviceName); diff --git a/Domain/Service/CommonLifecycleServiceCollection.php b/Domain/Service/CommonLifecycleServiceCollection.php index 32b352d..31a71ff 100755 --- a/Domain/Service/CommonLifecycleServiceCollection.php +++ b/Domain/Service/CommonLifecycleServiceCollection.php @@ -2,6 +2,7 @@ namespace Ivoz\Core\Domain\Service; +use Ivoz\Core\Domain\Assert\Assertion; use Ivoz\Core\Domain\Model\EntityInterface; class CommonLifecycleServiceCollection implements LifecycleServiceCollectionInterface @@ -27,11 +28,9 @@ public function setServices(string $event, array $services) } } - /** - * @return void - */ - protected function addService(string $event, CommonLifecycleEventHandlerInterface $service) + protected function addService(string $event, $service): void { + Assertion::isInstanceOf($service, CommonLifecycleEventHandlerInterface::class); $this->services[$event][] = $service; } diff --git a/Infrastructure/Domain/Service/Lifecycle/DoctrineEventSubscriber.php b/Infrastructure/Domain/Service/Lifecycle/DoctrineEventSubscriber.php index e20213d..62df694 100755 --- a/Infrastructure/Domain/Service/Lifecycle/DoctrineEventSubscriber.php +++ b/Infrastructure/Domain/Service/Lifecycle/DoctrineEventSubscriber.php @@ -3,7 +3,7 @@ namespace Ivoz\Core\Infrastructure\Domain\Service\Lifecycle; use Doctrine\Common\EventSubscriber; -use Doctrine\Common\Persistence\Event\LifecycleEventArgs; +use Doctrine\Persistence\Event\LifecycleEventArgs; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\Event\OnFlushEventArgs; use Doctrine\ORM\Event\PreUpdateEventArgs; diff --git a/Infrastructure/Persistence/Doctrine/Hydration/ObjectHydrator.php b/Infrastructure/Persistence/Doctrine/Hydration/ObjectHydrator.php index 6a0afa1..b8681b3 100644 --- a/Infrastructure/Persistence/Doctrine/Hydration/ObjectHydrator.php +++ b/Infrastructure/Persistence/Doctrine/Hydration/ObjectHydrator.php @@ -4,7 +4,7 @@ use Doctrine\ORM\Internal\Hydration\ObjectHydrator as DoctrineObjectHydrator; use Ivoz\Core\Infrastructure\Persistence\Doctrine\Events as IvozEvents; -use Doctrine\Common\Persistence\Event\LifecycleEventArgs; +use Doctrine\Persistence\Event\LifecycleEventArgs; use Doctrine\ORM\Events; class ObjectHydrator extends DoctrineObjectHydrator diff --git a/Infrastructure/Persistence/Doctrine/Hydration/SimpleObjectHydrator.php b/Infrastructure/Persistence/Doctrine/Hydration/SimpleObjectHydrator.php index e6206a6..a9ccc11 100644 --- a/Infrastructure/Persistence/Doctrine/Hydration/SimpleObjectHydrator.php +++ b/Infrastructure/Persistence/Doctrine/Hydration/SimpleObjectHydrator.php @@ -4,7 +4,7 @@ use Doctrine\ORM\Internal\Hydration\SimpleObjectHydrator as DoctrineSimpleObjectHydrator; use Ivoz\Core\Infrastructure\Persistence\Doctrine\Events as IvozEvents; -use Doctrine\Common\Persistence\Event\LifecycleEventArgs; +use Doctrine\Persistence\Event\LifecycleEventArgs; class SimpleObjectHydrator extends DoctrineSimpleObjectHydrator { diff --git a/Infrastructure/Persistence/Doctrine/ORM/Mapping/QuoteStrategy.php b/Infrastructure/Persistence/Doctrine/ORM/Mapping/QuoteStrategy.php index 4bc5808..6c77c24 100644 --- a/Infrastructure/Persistence/Doctrine/ORM/Mapping/QuoteStrategy.php +++ b/Infrastructure/Persistence/Doctrine/ORM/Mapping/QuoteStrategy.php @@ -14,7 +14,7 @@ class QuoteStrategy extends DefaultQuoteStrategy public function getColumnAlias($columnName, $counter, AbstractPlatform $platform, ClassMetadata $class = null) { $columnName = parent::getColumnAlias(...func_get_args()); - $columnName = is_numeric($columnName{0}) ? '_' . $columnName : $columnName; + $columnName = is_numeric($columnName[0]) ? '_' . $columnName : $columnName; return $platform->getSQLResultCasing($columnName); } diff --git a/composer.json b/composer.json index 66b1c68..0525820 100644 --- a/composer.json +++ b/composer.json @@ -26,7 +26,7 @@ "require": { "php": ">=7.4", "beberlei/assert": "2.9.*", - "doctrine/orm": "^2.5", + "doctrine/orm": "^2.8", "graze/guzzle-jsonrpc": "3.2.*", "guzzlehttp/guzzle": "^6.3", "lexik/jwt-authentication-bundle": "^2.5", From 34dff6621a3ee950b37110fe86a0cd38eb67363d Mon Sep 17 00:00:00 2001 From: Mikel Madariaga Date: Tue, 23 Mar 2021 10:06:47 +0100 Subject: [PATCH 06/76] fixed DBAL/Types/UtcDateTimeType issues --- .../Persistence/Doctrine/Model/DBAL/Types/UtcDateTimeType.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Infrastructure/Persistence/Doctrine/Model/DBAL/Types/UtcDateTimeType.php b/Infrastructure/Persistence/Doctrine/Model/DBAL/Types/UtcDateTimeType.php index cc3045d..38b97f6 100755 --- a/Infrastructure/Persistence/Doctrine/Model/DBAL/Types/UtcDateTimeType.php +++ b/Infrastructure/Persistence/Doctrine/Model/DBAL/Types/UtcDateTimeType.php @@ -12,6 +12,10 @@ class UtcDateTimeType extends DateTimeType public function convertToDatabaseValue($value, AbstractPlatform $platform) { + if (is_string($value)) { + return $value; + } + if ($value instanceof \DateTime) { $value->setTimezone( new \DateTimeZone('UTC') From 11bf568f6d00d9734e6ae54000a4ffb02b05f3e3 Mon Sep 17 00:00:00 2001 From: Mikel Madariaga Date: Wed, 14 Apr 2021 13:36:04 +0200 Subject: [PATCH 07/76] avoid duplicated ON_COMMIT service calls --- Domain/Model/ChangelogTrait.php | 15 ++------------- .../Domain/Service/Gearman/Jobs/AbstractJob.php | 2 +- .../Service/Lifecycle/DoctrineEventSubscriber.php | 2 ++ 3 files changed, 5 insertions(+), 14 deletions(-) diff --git a/Domain/Model/ChangelogTrait.php b/Domain/Model/ChangelogTrait.php index ba59729..7a4b805 100644 --- a/Domain/Model/ChangelogTrait.php +++ b/Domain/Model/ChangelogTrait.php @@ -27,40 +27,29 @@ abstract protected function __toArray(); abstract public static function createDto($id = null); /** - * @return bool + * TRUE on new entities until transaction is closed + * always false for ON_COMMIT lifecycle services */ public function isNew(): bool { return !$this->isPersisted(); } - /** - * @return bool - */ public function isInitialized(): bool { return !empty($this->_initialValues); } - /** - * @return bool - */ public function isPersisted(): bool { return $this->isPersisted; } - /** - * @return void - */ public function markAsPersisted() { $this->isPersisted = true; } - /** - * @return bool - */ public function hasBeenDeleted(): bool { $id = $this->getId(); diff --git a/Infrastructure/Domain/Service/Gearman/Jobs/AbstractJob.php b/Infrastructure/Domain/Service/Gearman/Jobs/AbstractJob.php index 11570a7..f10b60a 100644 --- a/Infrastructure/Domain/Service/Gearman/Jobs/AbstractJob.php +++ b/Infrastructure/Domain/Service/Gearman/Jobs/AbstractJob.php @@ -79,7 +79,7 @@ public function __sleep() * * @return void */ - public function send() + public function send(): void { $this->manager::setOptions($this->settings); diff --git a/Infrastructure/Domain/Service/Lifecycle/DoctrineEventSubscriber.php b/Infrastructure/Domain/Service/Lifecycle/DoctrineEventSubscriber.php index 62df694..d8ecb9a 100755 --- a/Infrastructure/Domain/Service/Lifecycle/DoctrineEventSubscriber.php +++ b/Infrastructure/Domain/Service/Lifecycle/DoctrineEventSubscriber.php @@ -167,6 +167,8 @@ public function onFlush(OnFlushEventArgs $eventArgs) $this->flushedEntities[] = $entity; } } + + $this->flushedEntities = array_unique($this->flushedEntities); } /** From cb2149969030577c6834ca395265e0213e86c165 Mon Sep 17 00:00:00 2001 From: Mikel Date: Thu, 15 Apr 2021 09:56:39 +0200 Subject: [PATCH 08/76] fixed regression --- .../Service/Lifecycle/DoctrineEventSubscriber.php | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Infrastructure/Domain/Service/Lifecycle/DoctrineEventSubscriber.php b/Infrastructure/Domain/Service/Lifecycle/DoctrineEventSubscriber.php index d8ecb9a..1011c94 100755 --- a/Infrastructure/Domain/Service/Lifecycle/DoctrineEventSubscriber.php +++ b/Infrastructure/Domain/Service/Lifecycle/DoctrineEventSubscriber.php @@ -168,7 +168,17 @@ public function onFlush(OnFlushEventArgs $eventArgs) } } - $this->flushedEntities = array_unique($this->flushedEntities); + $uniqueObjectIds = array_unique( + array_map('spl_object_id', $this->flushedEntities) + ); + + foreach ($this->flushedEntities as $key => $entity) { + if (array_key_exists($key, $uniqueObjectIds)) { + continue; + } + + unset($this->flushedEntities[$key]); + } } /** From 9ababeda7c25b9d886030f8ebedd9fe4dc9916d2 Mon Sep 17 00:00:00 2001 From: Mikel Date: Fri, 16 Apr 2021 09:47:15 +0200 Subject: [PATCH 09/76] added RedisMasterFactory service --- .../Persistence/Redis/RedisMasterFactory.php | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 Infrastructure/Persistence/Redis/RedisMasterFactory.php diff --git a/Infrastructure/Persistence/Redis/RedisMasterFactory.php b/Infrastructure/Persistence/Redis/RedisMasterFactory.php new file mode 100644 index 0000000..58bc667 --- /dev/null +++ b/Infrastructure/Persistence/Redis/RedisMasterFactory.php @@ -0,0 +1,28 @@ +sentinel = $sentinel; + } + + public function create(int $dbIndex = 1): \Redis + { + $redisConf = $this->sentinel->resolveMaster(); + $redisClient = new \Redis(); + $redisClient->connect( + $redisConf->getHost(), + $redisConf->getPort() + ); + + $redisClient->select($dbIndex); + + return $redisClient; + } +} From b414eae75161a45ca658612ab1515e9189daa46a Mon Sep 17 00:00:00 2001 From: Mikel Date: Mon, 19 Apr 2021 12:08:01 +0200 Subject: [PATCH 10/76] added FakeRedisMasterFactory --- .../Redis/FakeRedisMasterFactory.php | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 Infrastructure/Persistence/Redis/FakeRedisMasterFactory.php diff --git a/Infrastructure/Persistence/Redis/FakeRedisMasterFactory.php b/Infrastructure/Persistence/Redis/FakeRedisMasterFactory.php new file mode 100644 index 0000000..6efac19 --- /dev/null +++ b/Infrastructure/Persistence/Redis/FakeRedisMasterFactory.php @@ -0,0 +1,22 @@ + Date: Wed, 21 Apr 2021 10:40:40 +0200 Subject: [PATCH 11/76] removed gearmn services --- .../Gearman/Client/AbstractXmlRpcRequest.php | 48 -------- .../Client/FakeXmlRpcTrunksRequest.php | 10 -- .../Gearman/Client/FakeXmlRpcUsersRequest.php | 10 -- .../Client/XmlRpcTrunksRequestInterface.php | 13 --- .../Client/XmlRpcUsersRequestInterface.php | 11 -- .../Domain/Service/Gearman/FakeManager.php | 17 --- .../Service/Gearman/Jobs/AbstractJob.php | 106 ------------------ .../Domain/Service/Gearman/Jobs/Xmlrpc.php | 105 ----------------- .../Domain/Service/Gearman/Manager.php | 96 ---------------- 9 files changed, 416 deletions(-) delete mode 100755 Infrastructure/Domain/Service/Gearman/Client/AbstractXmlRpcRequest.php delete mode 100644 Infrastructure/Domain/Service/Gearman/Client/FakeXmlRpcTrunksRequest.php delete mode 100644 Infrastructure/Domain/Service/Gearman/Client/FakeXmlRpcUsersRequest.php delete mode 100644 Infrastructure/Domain/Service/Gearman/Client/XmlRpcTrunksRequestInterface.php delete mode 100644 Infrastructure/Domain/Service/Gearman/Client/XmlRpcUsersRequestInterface.php delete mode 100644 Infrastructure/Domain/Service/Gearman/FakeManager.php delete mode 100644 Infrastructure/Domain/Service/Gearman/Jobs/AbstractJob.php delete mode 100644 Infrastructure/Domain/Service/Gearman/Jobs/Xmlrpc.php delete mode 100644 Infrastructure/Domain/Service/Gearman/Manager.php diff --git a/Infrastructure/Domain/Service/Gearman/Client/AbstractXmlRpcRequest.php b/Infrastructure/Domain/Service/Gearman/Client/AbstractXmlRpcRequest.php deleted file mode 100755 index c350888..0000000 --- a/Infrastructure/Domain/Service/Gearman/Client/AbstractXmlRpcRequest.php +++ /dev/null @@ -1,48 +0,0 @@ -xmlrpc = $xmlrpc; - $this->xmlrpc->setRpcEntity($rpcEntity); - $this->xmlrpc->setRpcPort($rpcPort); - - $this->enabled = $enabled; - } - - /** - * @return void - */ - public function send(string $rpcMethod) - { - if (!$this->enabled) { - return; - } - - $this->xmlrpc->setRpcMethod($rpcMethod); - $this->xmlrpc->send(); - } -} diff --git a/Infrastructure/Domain/Service/Gearman/Client/FakeXmlRpcTrunksRequest.php b/Infrastructure/Domain/Service/Gearman/Client/FakeXmlRpcTrunksRequest.php deleted file mode 100644 index 9ec1b92..0000000 --- a/Infrastructure/Domain/Service/Gearman/Client/FakeXmlRpcTrunksRequest.php +++ /dev/null @@ -1,10 +0,0 @@ -manager = $manager; - $this->logger = $logger; - $this->settings = $settings; - } - - /** - * @param string $methodName - * - * @return void - */ - public function setMethod($methodName) - { - $this->method = $methodName; - } - - /** - * @return array - */ - public function __sleep() - { - return $this->mainVariables; - } - - /** - * Send Gearman Job request to server - * - * @return void - */ - public function send(): void - { - $this->manager::setOptions($this->settings); - - try { - $gearmandClient = $this->manager::getClient(); - $gearmandClient->doBackground( - $this->method, - igbinary_serialize($this) - ); - - if ($gearmandClient->returnCode() != GEARMAN_SUCCESS) { - throw new \Exception('Gearmand return code error'); - } - } catch (\DomainException $e) { - $this->logger->error($e->getMessage()); - - throw new \Exception( - 'Gearmand: Unable to add background job to the queue', - 0, - $e - ); - } - } -} diff --git a/Infrastructure/Domain/Service/Gearman/Jobs/Xmlrpc.php b/Infrastructure/Domain/Service/Gearman/Jobs/Xmlrpc.php deleted file mode 100644 index 8b29f2b..0000000 --- a/Infrastructure/Domain/Service/Gearman/Jobs/Xmlrpc.php +++ /dev/null @@ -1,105 +0,0 @@ -method = $method; - parent::__construct($manager, $logger, $settings); - } - - /** - * @param string $rpcEntity - * @return $this - */ - public function setRpcEntity($rpcEntity) - { - $this->rpcEntity = $rpcEntity; - return $this; - } - - /** - * @return string - */ - public function getRpcEntity() - { - return $this->rpcEntity; - } - - /** - * @param string $rpcPort - * @return $this - */ - public function setRpcPort($rpcPort) - { - $this->rpcPort = $rpcPort; - return $this; - } - - /** - * @return string - */ - public function getRpcPort() - { - return $this->rpcPort; - } - - /** - * @param string $rpcMethod - * @return $this - */ - public function setRpcMethod($rpcMethod) - { - $this->rpcMethod = $rpcMethod; - return $this; - } - - /** - * @return string - */ - public function getRpcMethod() - { - return $this->rpcMethod; - } -} diff --git a/Infrastructure/Domain/Service/Gearman/Manager.php b/Infrastructure/Domain/Service/Gearman/Manager.php deleted file mode 100644 index 12493a1..0000000 --- a/Infrastructure/Domain/Service/Gearman/Manager.php +++ /dev/null @@ -1,96 +0,0 @@ -addServers($servers); - if (isset(self::$_options['client']) && - isset(self::$_options['client']['timeout'])) { - $gmclient->setTimeout(self::$_options['client']['timeout']); - } - - return $gmclient; - } - - /** - * Creates a GearmanWorker instance - * - * @return \GearmanWorker - */ - public static function getWorker() - { - $worker = new \GearmanWorker(); - $servers = self::getServers(); - - $worker->addServers($servers); - - return $worker; - } - - /** - * Given a worker name, it checks if it can be loaded. If it's possible, - * it creates and returns a new instance. - * - * @param string $workerName - * @param string $logFile - * @return \GearmanWorker - */ - public static function runWorker($workerName, $logFile = null) - { - $workerName .= 'Worker'; - $workerFile = self::WORKER_PATH . '/' . $workerName . '.php'; - - if (!file_exists($workerFile)) { - throw new \InvalidArgumentException( - "Worker not found: {$workerFile}" - ); - } - - require $workerFile; - - if (!class_exists($workerName)) { - throw new \InvalidArgumentException( - "class {$workerName} not found in {$workerFile}" - ); - } - - return new $workerName($logFile); - } -} From 2f04a3ab6448b3c2f95efc2ce98b49030c747664 Mon Sep 17 00:00:00 2001 From: Mikel Date: Wed, 21 Apr 2021 11:11:18 +0200 Subject: [PATCH 12/76] improved FakeRedisMasterFactory service --- Infrastructure/Persistence/Redis/FakeRedisMasterFactory.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Infrastructure/Persistence/Redis/FakeRedisMasterFactory.php b/Infrastructure/Persistence/Redis/FakeRedisMasterFactory.php index 6efac19..430a16b 100644 --- a/Infrastructure/Persistence/Redis/FakeRedisMasterFactory.php +++ b/Infrastructure/Persistence/Redis/FakeRedisMasterFactory.php @@ -15,6 +15,12 @@ public function connect( $retryInterval = 0, $readTimeout = 0.0 ) {} + + public function lPush($key, ...$value1) {} + + public function rPush($key, ...$value1) {} + + public function blPop($key, $timeout_or_key, ...$extra_args) {} }; return new $fakeRedis; From 6be69f6c9ef0ccfc04c2ceb1c0c17c6ed4fcf493 Mon Sep 17 00:00:00 2001 From: Mikel Madariaga Date: Wed, 14 Jul 2021 16:29:53 +0200 Subject: [PATCH 13/76] allow dto embedded property filter --- Application/Model/DtoNormalizer.php | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/Application/Model/DtoNormalizer.php b/Application/Model/DtoNormalizer.php index b667fdb..206d849 100644 --- a/Application/Model/DtoNormalizer.php +++ b/Application/Model/DtoNormalizer.php @@ -30,7 +30,7 @@ public function normalize(string $context, string $role = '') $response = $this->toArray(true); $contextProperties = static::getPropertyMap($context, $role); - return array_filter( + $response = array_filter( $response, function ($key) use ($contextProperties) { return @@ -39,6 +39,29 @@ function ($key) use ($contextProperties) { }, ARRAY_FILTER_USE_KEY ); + + foreach ($response as $key => $val) { + + $isEmbedded = is_array($val)/* || is_object($val)*/; + if (!$isEmbedded) { + continue; + } + + if (!isset($contextProperties[$key])) { + continue; + } + + $validSubKeys = $contextProperties[$key]; + $response[$key] = array_filter( + $val, + function ($key) use ($validSubKeys) { + return in_array($key, $validSubKeys); + }, + ARRAY_FILTER_USE_KEY + ); + } + + return $response; } /** From c682f466e48d161a19afebf46c9d331318d53200 Mon Sep 17 00:00:00 2001 From: Mikel Madariaga Date: Wed, 15 Sep 2021 10:05:17 +0200 Subject: [PATCH 14/76] added DataTransferObjectInterface::CONTEXT_EMPTY --- Application/DataTransferObjectInterface.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Application/DataTransferObjectInterface.php b/Application/DataTransferObjectInterface.php index 73d57fc..b3b7f5b 100755 --- a/Application/DataTransferObjectInterface.php +++ b/Application/DataTransferObjectInterface.php @@ -5,11 +5,13 @@ interface DataTransferObjectInterface { const CONTEXT_COLLECTION = 'collection'; - const CONTEXT_SIMPLE = ''; + const CONTEXT_SIMPLE = 'item'; const CONTEXT_DETAILED = 'detailed'; const CONTEXT_DETAILED_COLLECTION = 'detailedCollection'; + const CONTEXT_EMPTY = ''; const CONTEXT_TYPES = [ + self::CONTEXT_EMPTY, self::CONTEXT_COLLECTION, self::CONTEXT_SIMPLE, self::CONTEXT_DETAILED, From 74d7af3a039b7f33985c6fb52a11314384ca3fb2 Mon Sep 17 00:00:00 2001 From: Mikel Madariaga Date: Thu, 16 Sep 2021 11:06:37 +0200 Subject: [PATCH 15/76] error prevention in DtoNormalizer --- Application/Model/DtoNormalizer.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Application/Model/DtoNormalizer.php b/Application/Model/DtoNormalizer.php index 206d849..ab32113 100644 --- a/Application/Model/DtoNormalizer.php +++ b/Application/Model/DtoNormalizer.php @@ -85,6 +85,10 @@ protected function setByContext(array $contextProperties, array $data) foreach ($contextProperties as $key => $value) { if (is_array($value)) { foreach ($value as $property) { + if (!isset($data[$key]) || !array_key_exists($property, $data[$key])) { + continue; + } + $setter = 'set' . ucfirst($key) . ucfirst($property); $dataPath = [ $key, From e121acb330636f19d1310f97485e726f7ead709a Mon Sep 17 00:00:00 2001 From: Mikel Date: Wed, 29 Sep 2021 15:51:24 +0200 Subject: [PATCH 16/76] allow collection property filter in DtoNormalizer --- Application/Model/DtoNormalizer.php | 40 ++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/Application/Model/DtoNormalizer.php b/Application/Model/DtoNormalizer.php index ab32113..fecf691 100644 --- a/Application/Model/DtoNormalizer.php +++ b/Application/Model/DtoNormalizer.php @@ -52,18 +52,44 @@ function ($key) use ($contextProperties) { } $validSubKeys = $contextProperties[$key]; - $response[$key] = array_filter( - $val, - function ($key) use ($validSubKeys) { - return in_array($key, $validSubKeys); - }, - ARRAY_FILTER_USE_KEY - ); + $response[$key] = $this->filterResponseValues($val, $validSubKeys); } return $response; } + private function filterResponseValues($value, $validSubKeys) + { + $filterCollectionItems = + is_array($value) + && is_array($validSubKeys) + && array_key_exists(0, $validSubKeys) + && is_array($validSubKeys[0]); + + if ($filterCollectionItems) { + foreach ($value as $k => $itemValue) { + $value[$k] = $this->filterResponseValues( + $value[$k], + $validSubKeys[0] + ); + + if (empty($value[$k])) { + unset($value[$k]); + } + } + + return $value; + } + + return array_filter( + $value, + function ($subkey) use ($validSubKeys) { + return in_array($subkey, $validSubKeys); + }, + ARRAY_FILTER_USE_KEY + ); + } + /** * @inheritdoc */ From 11ff64abfef5843d9c482c15f78b412c628b3579 Mon Sep 17 00:00:00 2001 From: Mikel Date: Thu, 14 Oct 2021 12:08:14 +0200 Subject: [PATCH 17/76] require php 8 --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 0525820..6a28f54 100644 --- a/composer.json +++ b/composer.json @@ -24,8 +24,8 @@ } }, "require": { - "php": ">=7.4", - "beberlei/assert": "2.9.*", + "php": ">=8.0", + "beberlei/assert": "^3.0", "doctrine/orm": "^2.8", "graze/guzzle-jsonrpc": "3.2.*", "guzzlehttp/guzzle": "^6.3", From 1e5507dd015421ec6b6fcd2887ec444101ca1501 Mon Sep 17 00:00:00 2001 From: Mikel Date: Thu, 14 Oct 2021 14:30:12 +0200 Subject: [PATCH 18/76] upgraded ramsey/uuid to ^4.2 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 6a28f54..c763bf7 100644 --- a/composer.json +++ b/composer.json @@ -30,7 +30,7 @@ "graze/guzzle-jsonrpc": "3.2.*", "guzzlehttp/guzzle": "^6.3", "lexik/jwt-authentication-bundle": "^2.5", - "ramsey/uuid": "^3.7", + "ramsey/uuid": "^4.2", "symfony/expression-language": "^5.1", "symfony/finder": "^5.1", "symfony/http-foundation": "^5.1", From 569544ae295d1135d71a988db76fce7ccaeb6ab4 Mon Sep 17 00:00:00 2001 From: Mikel Date: Wed, 10 Nov 2021 17:25:24 +0100 Subject: [PATCH 19/76] updated Entity and DTO hints --- Application/DataTransferObjectInterface.php | 25 ++------ Application/Model/DtoNormalizer.php | 8 +-- Domain/Model/ChangelogTrait.php | 20 ++---- Domain/Model/EntityInterface.php | 67 +++++---------------- 4 files changed, 29 insertions(+), 91 deletions(-) diff --git a/Application/DataTransferObjectInterface.php b/Application/DataTransferObjectInterface.php index b3b7f5b..d156828 100755 --- a/Application/DataTransferObjectInterface.php +++ b/Application/DataTransferObjectInterface.php @@ -20,26 +20,9 @@ interface DataTransferObjectInterface public function setId($id); public function getId(); - - /** - * @return array - */ - public function normalize(string $context, string $role = ''); - - /** - * @return void - */ - public function denormalize(array $data, string $context, string $role = ''); - - /** - * @return array - */ - public static function getPropertyMap(string $context = '', string $role = null); - + public function normalize(string $context, string $role = ''): array; + public function denormalize(array $data, string $context, string $role = ''): void; + public static function getPropertyMap(string $context = '', string $role = null): array; public function getSensitiveFields(): array; - - /** - * @return array - */ - public function toArray($hideSensitiveData = false); + public function toArray(bool $hideSensitiveData = false): array; } diff --git a/Application/Model/DtoNormalizer.php b/Application/Model/DtoNormalizer.php index fecf691..258b249 100644 --- a/Application/Model/DtoNormalizer.php +++ b/Application/Model/DtoNormalizer.php @@ -10,12 +10,12 @@ trait DtoNormalizer /** * @return array */ - abstract public function toArray($hideSensitiveData = false); + abstract public function toArray(bool $hideSensitiveData = false): array; /** * @return array */ - abstract public static function getPropertyMap(string $context = ''); + abstract public static function getPropertyMap(string $context = ''): array; public function getSensitiveFields(): array { @@ -25,7 +25,7 @@ public function getSensitiveFields(): array /** * @inheritdoc */ - public function normalize(string $context, string $role = '') + public function normalize(string $context, string $role = ''): array { $response = $this->toArray(true); $contextProperties = static::getPropertyMap($context, $role); @@ -93,7 +93,7 @@ function ($subkey) use ($validSubKeys) { /** * @inheritdoc */ - public function denormalize(array $data, string $context, string $role = '') + public function denormalize(array $data, string $context, string $role = ''): void { $contextProperties = static::getPropertyMap($context, $role); diff --git a/Domain/Model/ChangelogTrait.php b/Domain/Model/ChangelogTrait.php index 7a4b805..c7a1ae4 100644 --- a/Domain/Model/ChangelogTrait.php +++ b/Domain/Model/ChangelogTrait.php @@ -24,7 +24,7 @@ trait ChangelogTrait abstract public function getId(); abstract protected function __toArray(); - abstract public static function createDto($id = null); + abstract public static function createDto(string|int $id = null); /** * TRUE on new entities until transaction is closed @@ -45,7 +45,7 @@ public function isPersisted(): bool return $this->isPersisted; } - public function markAsPersisted() + public function markAsPersisted(): void { $this->isPersisted = true; } @@ -63,11 +63,7 @@ public function hasBeenDeleted(): bool return $hasInitialValue; } - /** - * @return void - * @throws \Exception - */ - public function initChangelog() + public function initChangelog(): void { $values = $this->__toArray(); if (!$this->getId()) { @@ -83,11 +79,9 @@ public function initChangelog() } /** - * @param string $dbFieldName - * @return bool * @throws \Exception */ - public function hasChanged($dbFieldName): bool + public function hasChanged(string $dbFieldName): bool { if (!array_key_exists($dbFieldName, $this->_initialValues)) { throw new \Exception($dbFieldName . ' field was not found'); @@ -98,11 +92,9 @@ public function hasChanged($dbFieldName): bool } /** - * @param string $dbFieldName - * @return mixed * @throws \Exception */ - public function getInitialValue($dbFieldName) + public function getInitialValue(string $dbFieldName): mixed { if (!array_key_exists($dbFieldName, $this->_initialValues)) { throw new \Exception($dbFieldName . ' field was not found'); @@ -114,7 +106,7 @@ public function getInitialValue($dbFieldName) /** * @return array */ - protected function getChangeSet() + protected function getChangeSet(): array { $changes = []; $currentValues = $this->__toArray(); diff --git a/Domain/Model/EntityInterface.php b/Domain/Model/EntityInterface.php index a1cfa50..4289ffd 100755 --- a/Domain/Model/EntityInterface.php +++ b/Domain/Model/EntityInterface.php @@ -13,100 +13,63 @@ interface EntityInterface { /** - * @return mixed + * @return string|int|null */ public function getId(); - /** - * @return bool - */ - public function isNew(); + public function isNew(): bool; - /** - * @return bool - */ - public function isPersisted(); + public function isPersisted(): bool; - /** - * @return void - */ - public function markAsPersisted(); + public function markAsPersisted(): void; - /** - * @return bool - */ - public function hasBeenDeleted(); + public function hasBeenDeleted(): bool; - /** - * @return string - */ - public function __toString(); + public function __toString(): string; - /** - * @return void - * @throws \Exception - */ - public function initChangelog(); + public function initChangelog(): void; /** - * @param string $fieldName - * @return boolean * @throws \Exception */ - public function hasChanged($fieldName); + public function hasChanged(string $fieldName): bool; /** * @return string[] */ - public function getChangedFields(); + public function getChangedFields(): array; /** - * @param string $fieldName - * @return mixed * @throws \Exception */ - public function getInitialValue($fieldName); + public function getInitialValue(string $fieldName): mixed; - /** - * @param mixed|null $id - * @return EntityInterface - */ - public static function createDto($id = null); + public static function createDto(int|string $id = null): DataTransferObjectInterface; /** - * @param int $depth - * @param EntityInterface|null $entity - * @return DataTransferObjectInterface|null * @todo move this into dto::fromEntity */ - public static function entityToDto(EntityInterface $entity = null, $depth = 0); + public static function entityToDto(?EntityInterface $entity, int $depth = 0): ?DataTransferObjectInterface; /** * Factory method - * @param DataTransferObjectInterface $dto - * @param \Ivoz\Core\Application\ForeignKeyTransformerInterface $fkTransformer */ public static function fromDto( DataTransferObjectInterface $dto, ForeignKeyTransformerInterface $fkTransformer - ); + ): EntityInterface; /** * @internal use EntityTools instead - * @param DataTransferObjectInterface $dto - * @param \Ivoz\Core\Application\ForeignKeyTransformerInterface $fkTransformer - * @return self */ public function updateFromDto( DataTransferObjectInterface $dto, ForeignKeyTransformerInterface $fkTransformer - ); + ): static; /** * DTO casting - * @param int $depth - * @return DataTransferObjectInterface * @todo move this into dto::fromEntity */ - public function toDto($depth = 0); + public function toDto(int $depth = 0): DataTransferObjectInterface; } From cefd07f5214a3d79e47366f0bae62da574d1d5f2 Mon Sep 17 00:00:00 2001 From: Mikel Date: Fri, 12 Nov 2021 11:36:09 +0100 Subject: [PATCH 20/76] fixed hydration issues Recursive EAGER loadings was causing onHydratorComplete event to be fired before time --- .../Persistence/Doctrine/Hydration/ObjectHydrator.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Infrastructure/Persistence/Doctrine/Hydration/ObjectHydrator.php b/Infrastructure/Persistence/Doctrine/Hydration/ObjectHydrator.php index b8681b3..ffdf57c 100644 --- a/Infrastructure/Persistence/Doctrine/Hydration/ObjectHydrator.php +++ b/Infrastructure/Persistence/Doctrine/Hydration/ObjectHydrator.php @@ -11,6 +11,8 @@ class ObjectHydrator extends DoctrineObjectHydrator { protected $loadedEntities = []; + private static int $recursionLevel = 0; + /** * {@inheritdoc} */ @@ -22,6 +24,7 @@ public function hydrateAll($stmt, $resultSetMapping, array $hints = array()) $this ); + self::$recursionLevel++; $response = parent::hydrateAll(...func_get_args()); $evm->removeEventListener( @@ -54,6 +57,14 @@ function ($entity) use ($reponseClass) { return $response; } + protected function cleanup() + { + self::$recursionLevel--; + if (self::$recursionLevel === 0) { + parent::cleanup(); + } + } + public function hydrateRow() { $response = parent::hydrateRow(); From 0faa5ef438984fab99c790147824d2de78c2b53c Mon Sep 17 00:00:00 2001 From: Mikel Date: Tue, 16 Nov 2021 14:10:07 +0100 Subject: [PATCH 21/76] enhanced hints --- Application/DataTransferObjectInterface.php | 2 +- Application/Event/CommandEventInterface.php | 18 ++++++++++++++++++ Application/ForeignKeyTransformerInterface.php | 10 +++++----- Domain/Event/EntityEventInterface.php | 12 ++++++++++++ Domain/Model/ChangelogTrait.php | 3 ++- Domain/Model/EntityInterface.php | 2 +- .../DoctrineForeignKeyTransformer.php | 12 +++++------- 7 files changed, 44 insertions(+), 15 deletions(-) diff --git a/Application/DataTransferObjectInterface.php b/Application/DataTransferObjectInterface.php index d156828..c15d340 100755 --- a/Application/DataTransferObjectInterface.php +++ b/Application/DataTransferObjectInterface.php @@ -18,7 +18,7 @@ interface DataTransferObjectInterface self::CONTEXT_DETAILED_COLLECTION ]; - public function setId($id); + public function setId(int|string $id); public function getId(); public function normalize(string $context, string $role = ''): array; public function denormalize(array $data, string $context, string $role = ''): void; diff --git a/Application/Event/CommandEventInterface.php b/Application/Event/CommandEventInterface.php index c4ad62e..0e574e8 100644 --- a/Application/Event/CommandEventInterface.php +++ b/Application/Event/CommandEventInterface.php @@ -14,15 +14,33 @@ public function __construct( array $agent ); + /** + * @return string + */ public function getId(); + /** + * @return string + */ public function getRequestId(); + /** + * @return string + */ public function getService(); + /** + * @return string + */ public function getMethod(); + /** + * @return array + */ public function getArguments(); + /** + * @return array + */ public function getAgent(); } diff --git a/Application/ForeignKeyTransformerInterface.php b/Application/ForeignKeyTransformerInterface.php index 0f3b5c4..4dd64f9 100755 --- a/Application/ForeignKeyTransformerInterface.php +++ b/Application/ForeignKeyTransformerInterface.php @@ -3,19 +3,19 @@ namespace Ivoz\Core\Application; use Doctrine\Common\Collections\ArrayCollection; +use Ivoz\Core\Domain\Model\EntityInterface; interface ForeignKeyTransformerInterface { /** - * @param mixed $element + * @param EntityInterface|DataTransferObjectInterface|null $element * @param bool $persist */ public function transform($element, $persist = true); - /** - * @param array | null $elements - * @return ArrayCollection | null + * @param array $elements + * @return ArrayCollection */ - public function transformCollection(array $elements = null); + public function transformCollection(array $elements); } diff --git a/Domain/Event/EntityEventInterface.php b/Domain/Event/EntityEventInterface.php index 55f1bda..e396aed 100644 --- a/Domain/Event/EntityEventInterface.php +++ b/Domain/Event/EntityEventInterface.php @@ -6,11 +6,23 @@ interface EntityEventInterface extends DomainEventInterface { public function __construct(string $entityClass, $entityId, array $changeSet = null); + /** + * @return string + */ public function getId(); + /** + * @return string + */ public function getEntityClass(); + /** + * @return int|string + */ public function getEntityId(); + /** + * @return array + */ public function getData(); } diff --git a/Domain/Model/ChangelogTrait.php b/Domain/Model/ChangelogTrait.php index c7a1ae4..47f86b5 100644 --- a/Domain/Model/ChangelogTrait.php +++ b/Domain/Model/ChangelogTrait.php @@ -92,6 +92,7 @@ public function hasChanged(string $dbFieldName): bool } /** + * @return array * @throws \Exception */ public function getInitialValue(string $dbFieldName): mixed @@ -104,7 +105,7 @@ public function getInitialValue(string $dbFieldName): mixed } /** - * @return array + * @return array */ protected function getChangeSet(): array { diff --git a/Domain/Model/EntityInterface.php b/Domain/Model/EntityInterface.php index 4289ffd..24ffe66 100755 --- a/Domain/Model/EntityInterface.php +++ b/Domain/Model/EntityInterface.php @@ -44,7 +44,7 @@ public function getChangedFields(): array; */ public function getInitialValue(string $fieldName): mixed; - public static function createDto(int|string $id = null): DataTransferObjectInterface; + public static function createDto(int|string|null $id = null): DataTransferObjectInterface; /** * @todo move this into dto::fromEntity diff --git a/Infrastructure/Application/DoctrineForeignKeyTransformer.php b/Infrastructure/Application/DoctrineForeignKeyTransformer.php index eb8d1eb..e5bc27b 100755 --- a/Infrastructure/Application/DoctrineForeignKeyTransformer.php +++ b/Infrastructure/Application/DoctrineForeignKeyTransformer.php @@ -24,6 +24,8 @@ public function __construct(EntityManager $em) /** * @param mixed $element * @param bool $persist + * + * @return EntityInterface */ public function transform($element, $persist = true) { @@ -66,15 +68,11 @@ public function transform($element, $persist = true) } /** - * @param array | null $elements - * @return ArrayCollection | null + * @param array $elements + * @return ArrayCollection */ - public function transformCollection(array $elements = null) + public function transformCollection(array $elements) { - if (is_null($elements)) { - return null; - } - if (empty($elements)) { return new ArrayCollection(); } From 7fddb426c5629325f240a1cb10c2edc8a09ff8f8 Mon Sep 17 00:00:00 2001 From: Mikel Date: Wed, 17 Nov 2021 10:03:46 +0100 Subject: [PATCH 22/76] BC: updated LifecycleServiceCollectionTrait::addService definition --- Domain/Service/LifecycleServiceCollectionTrait.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Domain/Service/LifecycleServiceCollectionTrait.php b/Domain/Service/LifecycleServiceCollectionTrait.php index 3dbcf0d..b8e4ea6 100755 --- a/Domain/Service/LifecycleServiceCollectionTrait.php +++ b/Domain/Service/LifecycleServiceCollectionTrait.php @@ -57,7 +57,7 @@ public function setServices(string $event, array $services) } } - abstract protected function addService(string $event, $service); + abstract protected function addService(string $event, LifecycleEventHandlerInterface|DomainEventSubscriberInterface $service); /** * @return void From 7163cd014b9cb916d46876bfa6341c77923f0ccf Mon Sep 17 00:00:00 2001 From: Mikel Date: Tue, 30 Nov 2021 12:30:08 +0100 Subject: [PATCH 23/76] added phpstan scripts --- bin/test-phpstan | 23 +++++++++++++++++++++++ composer.json | 6 +++++- 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100755 bin/test-phpstan diff --git a/bin/test-phpstan b/bin/test-phpstan new file mode 100755 index 0000000..ba54135 --- /dev/null +++ b/bin/test-phpstan @@ -0,0 +1,23 @@ +#!/bin/bash + +set -e + +run_test () { + TARGET=$1 + echo "==========================" + echo "ivoz-core" + echo "==========================" + + ./vendor/bin/phpstan analyse \ + --level 5 \ + --ansi \ + --no-progress \ + --autoload-file ./vendor/autoload.php \ + --configuration phpstan.neon \ + ${TARGET} $2 +} + +PARENT_PATH=$( cd "$(dirname "${BASH_SOURCE[0]}")/../" ; pwd -P ) +pushd $PARENT_PATH + run_test . $1 +popd diff --git a/composer.json b/composer.json index c763bf7..ffab0ae 100644 --- a/composer.json +++ b/composer.json @@ -27,6 +27,8 @@ "php": ">=8.0", "beberlei/assert": "^3.0", "doctrine/orm": "^2.8", + "doctrine/dbal": "^2.12.1", + "doctrine/doctrine-migrations-bundle": "^3.0.3", "graze/guzzle-jsonrpc": "3.2.*", "guzzlehttp/guzzle": "^6.3", "lexik/jwt-authentication-bundle": "^2.5", @@ -34,8 +36,10 @@ "symfony/expression-language": "^5.1", "symfony/finder": "^5.1", "symfony/http-foundation": "^5.1", - "symfony/serializer": "^5.1" + "symfony/serializer": "^5.1", + "swiftmailer/swiftmailer": "v6.2.7" }, "require-dev": { + "phpstan/phpstan": "^1.0" } } From c0668405732da677993871780ff1aa8a47893add Mon Sep 17 00:00:00 2001 From: Mikel Date: Tue, 30 Nov 2021 12:31:19 +0100 Subject: [PATCH 24/76] fixed phpstan issues --- Domain/Assert/Assertion.php | 2 +- Domain/Model/Helper/DateTimeHelper.php | 2 +- .../DoctrineForeignKeyTransformer.php | 2 +- .../Service/Cgrates/FakeCgrRpcClient.php | 21 +++++++++++++++++++ .../Service/DoctrineEntityPersister.php | 1 + .../Domain/Service/DoctrineQueryRunner.php | 8 ++++++- .../Service/Lifecycle/CommandPersister.php | 2 +- .../Lifecycle/DoctrineEventSubscriber.php | 5 ++++- .../Doctrine/Hydration/ObjectHydrator.php | 1 + .../Doctrine/LoggableMigration.php | 2 +- .../Doctrine/Model/Helper/CriteriaHelper.php | 10 ++++++--- .../Doctrine/ORM/EntityManager.php | 11 ++++++---- .../Redis/FakeRedisMasterFactory.php | 10 +++++---- Infrastructure/Persistence/Redis/Lock.php | 2 +- Infrastructure/Persistence/Redis/Sentinel.php | 4 ++-- Infrastructure/Service/Rest/Client.php | 2 +- .../Compiler/DomainServiceCompiler.php | 4 ++-- .../Compiler/LifecycleCompiler.php | 8 ++----- 18 files changed, 67 insertions(+), 30 deletions(-) diff --git a/Domain/Assert/Assertion.php b/Domain/Assert/Assertion.php index 9611635..15d6f70 100644 --- a/Domain/Assert/Assertion.php +++ b/Domain/Assert/Assertion.php @@ -17,7 +17,7 @@ public static function regexFormat($pattern, $message = null, $propertyPath = nu $pattern = '/' . str_replace('/', '\/', $pattern) . '/'; - if (@preg_match($pattern, null) === false) { + if (@preg_match($pattern, '') === false) { $message = \sprintf( static::generateMessage($message) ?: '"%s" is not a valid regexp', static::stringify($pattern) diff --git a/Domain/Model/Helper/DateTimeHelper.php b/Domain/Model/Helper/DateTimeHelper.php index 3ec28c5..7bba51e 100755 --- a/Domain/Model/Helper/DateTimeHelper.php +++ b/Domain/Model/Helper/DateTimeHelper.php @@ -195,7 +195,7 @@ protected static function createFromString(string $value) protected static function getCurrentUtcDateTime(): \DateTime { return new \DateTime( - null, + 'now', new \DateTimeZone('UTC') ); } diff --git a/Infrastructure/Application/DoctrineForeignKeyTransformer.php b/Infrastructure/Application/DoctrineForeignKeyTransformer.php index e5bc27b..701965b 100755 --- a/Infrastructure/Application/DoctrineForeignKeyTransformer.php +++ b/Infrastructure/Application/DoctrineForeignKeyTransformer.php @@ -25,7 +25,7 @@ public function __construct(EntityManager $em) * @param mixed $element * @param bool $persist * - * @return EntityInterface + * @return ?EntityInterface */ public function transform($element, $persist = true) { diff --git a/Infrastructure/Domain/Service/Cgrates/FakeCgrRpcClient.php b/Infrastructure/Domain/Service/Cgrates/FakeCgrRpcClient.php index 469a73a..3ea1f05 100644 --- a/Infrastructure/Domain/Service/Cgrates/FakeCgrRpcClient.php +++ b/Infrastructure/Domain/Service/Cgrates/FakeCgrRpcClient.php @@ -6,11 +6,13 @@ use Graze\GuzzleHttp\JsonRpc\Message\Request; use Graze\GuzzleHttp\JsonRpc\Message\RequestInterface; use Graze\GuzzleHttp\JsonRpc\Message\Response; +use GuzzleHttp\Promise\Promise; class FakeCgrRpcClient implements ClientInterface { public function notification($method, array $params = null) { + return $this->createRequest(); } public function request($id, $method, array $params = null) @@ -34,13 +36,32 @@ public function send(RequestInterface $request) public function sendAsync(RequestInterface $request) { + return $this->createPromise(); } public function sendAll(array $requests) { + return [$this->createRequest()]; } public function sendAllAsync(array $requests) { + return $this->createPromise(); + } + + + private function createRequest() + { + return new Request( + 'POST', + '/uri', + [], + '[]' + ); + } + + private function createPromise() + { + return new Promise(); } } diff --git a/Infrastructure/Domain/Service/DoctrineEntityPersister.php b/Infrastructure/Domain/Service/DoctrineEntityPersister.php index 9e29710..4d8d8f7 100755 --- a/Infrastructure/Domain/Service/DoctrineEntityPersister.php +++ b/Infrastructure/Domain/Service/DoctrineEntityPersister.php @@ -161,6 +161,7 @@ public function persist(EntityInterface $entity, $dispatchImmediately = false) } if (in_array($state, $singleComputationValidStates)) { + /** @phpstan-ignore-next-line */ $this->em->flush($entity); return; } diff --git a/Infrastructure/Domain/Service/DoctrineQueryRunner.php b/Infrastructure/Domain/Service/DoctrineQueryRunner.php index ed490c6..5daa0d3 100755 --- a/Infrastructure/Domain/Service/DoctrineQueryRunner.php +++ b/Infrastructure/Domain/Service/DoctrineQueryRunner.php @@ -62,7 +62,11 @@ public function execute(string $entityName, AbstractQuery $query) } $retries = self::DEADLOCK_RETRIES; - while (0 < $retries--) { + /** @phpstan-ignore-next-line */ + while (0 < $retries) { + + $retries -= 1; + $this ->em ->getConnection() @@ -170,6 +174,7 @@ private function prepareChangelogEvent(string $entityName, AbstractQuery $query) /** @var \Closure $dqlParamResolver */ $dqlParamResolver = function () use (&$sqlParams, &$types) { + /** @var AbstractQuery $this */ assert( $this instanceof DqlQuery, new \Exception('dqlParamResolver context must be instance of ' . DqlQuery::class) @@ -177,6 +182,7 @@ private function prepareChangelogEvent(string $entityName, AbstractQuery $query) $parser = new Parser($this); $paramMappings = $parser->parse()->getParameterMappings(); + /** @phpstan-ignore-next-line */ list($params, $paramTypes) = $this->processParameterMappings($paramMappings); $sqlParams = $params; diff --git a/Infrastructure/Domain/Service/Lifecycle/CommandPersister.php b/Infrastructure/Domain/Service/Lifecycle/CommandPersister.php index e20314d..54fd2fa 100755 --- a/Infrastructure/Domain/Service/Lifecycle/CommandPersister.php +++ b/Infrastructure/Domain/Service/Lifecycle/CommandPersister.php @@ -120,7 +120,7 @@ public function persistEvents() private function registerFallbackCommand(): CommandWasExecuted { $command = new CommandWasExecuted( - 0, + '0', 'Unregistered', 'Unregistered', [], diff --git a/Infrastructure/Domain/Service/Lifecycle/DoctrineEventSubscriber.php b/Infrastructure/Domain/Service/Lifecycle/DoctrineEventSubscriber.php index 1011c94..1a3dfb6 100755 --- a/Infrastructure/Domain/Service/Lifecycle/DoctrineEventSubscriber.php +++ b/Infrastructure/Domain/Service/Lifecycle/DoctrineEventSubscriber.php @@ -205,7 +205,10 @@ public function onCommit(OnCommitEventArgs $args) } foreach ($this->flushedEntities as $entity) { - if (!$entity->__isInitialized__) { + if ( + !property_exists($entity, '__isInitialized__') + || !$entity->__isInitialized__ + ) { continue; } $entity->initChangelog(); diff --git a/Infrastructure/Persistence/Doctrine/Hydration/ObjectHydrator.php b/Infrastructure/Persistence/Doctrine/Hydration/ObjectHydrator.php index ffdf57c..9dbd78f 100644 --- a/Infrastructure/Persistence/Doctrine/Hydration/ObjectHydrator.php +++ b/Infrastructure/Persistence/Doctrine/Hydration/ObjectHydrator.php @@ -37,6 +37,7 @@ public function hydrateAll($stmt, $resultSetMapping, array $hints = array()) && is_object($response[0]); if ($mustTriggerEvents) { + /** @var string $reponseClass */ $reponseClass = get_class($response[0]); $foreignEntities = array_filter( $this->loadedEntities, diff --git a/Infrastructure/Persistence/Doctrine/LoggableMigration.php b/Infrastructure/Persistence/Doctrine/LoggableMigration.php index 6999d73..bc58ebe 100644 --- a/Infrastructure/Persistence/Doctrine/LoggableMigration.php +++ b/Infrastructure/Persistence/Doctrine/LoggableMigration.php @@ -28,7 +28,7 @@ public function postDown(Schema $schema): void private function logChanges(string $direction) { $event = new CommandWasExecuted( - 0, + '0', get_class($this), $direction, [], diff --git a/Infrastructure/Persistence/Doctrine/Model/Helper/CriteriaHelper.php b/Infrastructure/Persistence/Doctrine/Model/Helper/CriteriaHelper.php index 7544212..820ffb0 100755 --- a/Infrastructure/Persistence/Doctrine/Model/Helper/CriteriaHelper.php +++ b/Infrastructure/Persistence/Doctrine/Model/Helper/CriteriaHelper.php @@ -120,7 +120,7 @@ private static function arrayToExpressions(array $conditions) /** * @param string $field * @param string $operator - * @param null $value + * @param null|mixed $value * @return Comparison */ private static function createExpression(string $field, string $operator, $value = null) @@ -284,7 +284,7 @@ public static function append(string $operator, Criteria $baseCriteria, Criteria throw new \InvalidArgumentException('Unkown operator ' . $operator); } - /** @var CompositeExpression $baseExpression */ + /** @var CompositeExpression $expression */ $expression = self::simplifyCompositeExpression( $baseCriteria->getWhereExpression() ); @@ -306,8 +306,12 @@ public static function append(string $operator, Criteria $baseCriteria, Criteria return new Criteria($expression); } - private static function simplifyCompositeExpression(CompositeExpression $expression): CompositeExpression + private static function simplifyCompositeExpression(Expression $expression): Expression { + if (! $expression instanceof CompositeExpression) { + return $expression; + } + $expressionList = $expression->getExpressionList(); $firstExpression = current($expressionList); $isAndCondition = $expression->getType() === CompositeExpression::TYPE_AND; diff --git a/Infrastructure/Persistence/Doctrine/ORM/EntityManager.php b/Infrastructure/Persistence/Doctrine/ORM/EntityManager.php index 17b504d..c654a5c 100755 --- a/Infrastructure/Persistence/Doctrine/ORM/EntityManager.php +++ b/Infrastructure/Persistence/Doctrine/ORM/EntityManager.php @@ -27,12 +27,15 @@ public function disableBufferedQuery() private function setBufferedQuery(bool $enabled = true) { // https://www.php.net/manual/en/mysqlinfo.concepts.buffering.php - (function () use ($enabled) { + $this->connect(); - $driverName = $this->_conn->getAttribute(\PDO::ATTR_DRIVER_NAME); + + /** @var \Doctrine\DBAL\Driver\PDO\Connection $connection */ + $connection = $this->_conn; + $driverName = $connection->getAttribute(\PDO::ATTR_DRIVER_NAME); if ($driverName === 'mysql') { - $this->_conn->setAttribute( + $connection->setAttribute( \PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, $enabled ); @@ -65,7 +68,7 @@ public static function create($conn, Configuration $config, EventManager $eventM throw new \InvalidArgumentException("Invalid argument: " . $conn); } - return new static($conn, $config, $conn->getEventManager()); + return new self($conn, $config, $conn->getEventManager()); } /** diff --git a/Infrastructure/Persistence/Redis/FakeRedisMasterFactory.php b/Infrastructure/Persistence/Redis/FakeRedisMasterFactory.php index 430a16b..5491dde 100644 --- a/Infrastructure/Persistence/Redis/FakeRedisMasterFactory.php +++ b/Infrastructure/Persistence/Redis/FakeRedisMasterFactory.php @@ -14,13 +14,15 @@ public function connect( $reserved = null, $retryInterval = 0, $readTimeout = 0.0 - ) {} + ) { + return false; + } - public function lPush($key, ...$value1) {} + public function lPush($key, ...$value1) { return false; } - public function rPush($key, ...$value1) {} + public function rPush($key, ...$value1) { return false; } - public function blPop($key, $timeout_or_key, ...$extra_args) {} + public function blPop($key, $timeout_or_key, ...$extra_args) { return []; } }; return new $fakeRedis; diff --git a/Infrastructure/Persistence/Redis/Lock.php b/Infrastructure/Persistence/Redis/Lock.php index b9f7152..1362360 100644 --- a/Infrastructure/Persistence/Redis/Lock.php +++ b/Infrastructure/Persistence/Redis/Lock.php @@ -11,7 +11,7 @@ class Lock implements MutexInterface private $logger; private $dbIndex; - /** @var \Redis */ + /** @var ?\Redis */ private $redisMaster; private $lockKey; diff --git a/Infrastructure/Persistence/Redis/Sentinel.php b/Infrastructure/Persistence/Redis/Sentinel.php index 2d0e17c..d352063 100644 --- a/Infrastructure/Persistence/Redis/Sentinel.php +++ b/Infrastructure/Persistence/Redis/Sentinel.php @@ -42,7 +42,7 @@ public static function fromConfigArray( ) { $sentinelConfig = new SentinelConf($config); - return new static( + return new self( $sentinelConfig->get(), $logger ); @@ -97,7 +97,7 @@ private function getRedisMasterOrThrowException(RedisConf $config): RedisConf $masterName ); - if (empty($masters)) { + if (empty($master)) { throw new \RuntimeException( 'Unable to get redis master' ); diff --git a/Infrastructure/Service/Rest/Client.php b/Infrastructure/Service/Rest/Client.php index a7ddf76..25e213b 100644 --- a/Infrastructure/Service/Rest/Client.php +++ b/Infrastructure/Service/Rest/Client.php @@ -105,7 +105,7 @@ public function delete(string $uri, array $options = []) * @return ResponseInterface * @throws \RuntimeException */ - protected function request($method, $uri = '', array $options) + protected function request($method, $uri = '', array $options = []) { try { return $this->httpClient->request( diff --git a/Infrastructure/Symfony/DependencyInjection/Compiler/DomainServiceCompiler.php b/Infrastructure/Symfony/DependencyInjection/Compiler/DomainServiceCompiler.php index 4333a24..f0f36b0 100644 --- a/Infrastructure/Symfony/DependencyInjection/Compiler/DomainServiceCompiler.php +++ b/Infrastructure/Symfony/DependencyInjection/Compiler/DomainServiceCompiler.php @@ -127,9 +127,9 @@ protected function configureDomainEventSubscribers($fqdn) } /** - * @return array + * @return string[] * - * @psalm-return array + * @psalm-return array */ protected function getLifecycleEventHandlerServices(): array { diff --git a/Infrastructure/Symfony/DependencyInjection/Compiler/LifecycleCompiler.php b/Infrastructure/Symfony/DependencyInjection/Compiler/LifecycleCompiler.php index 7346016..50b7392 100644 --- a/Infrastructure/Symfony/DependencyInjection/Compiler/LifecycleCompiler.php +++ b/Infrastructure/Symfony/DependencyInjection/Compiler/LifecycleCompiler.php @@ -144,12 +144,8 @@ protected function getServicesByTag($tag): array { $services = $this->container->findTaggedServiceIds($tag); - /** - * @var Definition $a - * @var Definition $b - */ - uasort($services, function ($a, $b) { - return $a[0]['priority'] > $b[0]['priority']; + uasort($services, function (array $a, array $b) { + return (int) ($a[0]['priority'] > $b[0]['priority']); }); return array_keys($services); From 7ad13fba81cf027cc98722c751bcc66dff0db2b4 Mon Sep 17 00:00:00 2001 From: Mikel Madariaga Date: Fri, 10 Dec 2021 11:22:22 +0100 Subject: [PATCH 25/76] retry to resolve redis master on error --- Infrastructure/Persistence/Redis/Sentinel.php | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Infrastructure/Persistence/Redis/Sentinel.php b/Infrastructure/Persistence/Redis/Sentinel.php index d352063..781dae2 100644 --- a/Infrastructure/Persistence/Redis/Sentinel.php +++ b/Infrastructure/Persistence/Redis/Sentinel.php @@ -6,6 +6,8 @@ class Sentinel { + const RESOLVE_RETRIES = 30; + /** @var LoggerInterface */ protected $logger; @@ -48,8 +50,9 @@ public static function fromConfigArray( ); } - public function resolveMaster(): RedisConf + public function resolveMaster(int $retries = self::RESOLVE_RETRIES): RedisConf { + $resolveErrors = false; for ($i = 0; $i < count($this->sentinels); $i++) { try { $config = $this->sentinels[$i]; @@ -62,12 +65,18 @@ public function resolveMaster(): RedisConf break; } catch (\Exception $e) { $this->logger->error( - "ERROR: " . $e->getMessage() + "ERROR: " . $e->getMessage() . ". " . $retries . " retries left" ); + $resolveErrors = true; continue; } } + if ($resolveErrors && $retries > 0) { + sleep(1); + return $this->resolveMaster($retries - 1); + } + return $this->master; } From 21c8e4a161f27fe960d9d905f7923470ff556c11 Mon Sep 17 00:00:00 2001 From: Mikel Madariaga Date: Fri, 10 Dec 2021 11:36:51 +0100 Subject: [PATCH 26/76] added github actions --- .github/workflows/phpstan.yml | 24 ++++++++++++++++++++++++ composer.json | 2 +- phpstan.neon | 4 ++++ 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/phpstan.yml create mode 100644 phpstan.neon diff --git a/.github/workflows/phpstan.yml b/.github/workflows/phpstan.yml new file mode 100644 index 0000000..955d754 --- /dev/null +++ b/.github/workflows/phpstan.yml @@ -0,0 +1,24 @@ +name: PHPStan tests + +on: + push: + branches: [ 4.x ] + pull_request: + branches: [ 4.x ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: Validate composer.json + run: composer validate --strict + + - name: Install dependencies + uses: php-actions/composer@v6 + + - name: Run PHPStan tests + run: bin/test-phpstan diff --git a/composer.json b/composer.json index ffab0ae..11b6337 100644 --- a/composer.json +++ b/composer.json @@ -37,7 +37,7 @@ "symfony/finder": "^5.1", "symfony/http-foundation": "^5.1", "symfony/serializer": "^5.1", - "swiftmailer/swiftmailer": "v6.2.7" + "swiftmailer/swiftmailer": "6.2.*" }, "require-dev": { "phpstan/phpstan": "^1.0" diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000..cdc4c86 --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,4 @@ +parameters: + excludePaths: + analyse: + - vendor From 7d611a7b125ca4ef6a85c5d9e469ff2d3f9593e7 Mon Sep 17 00:00:00 2001 From: Mikel Date: Fri, 10 Dec 2021 12:15:10 +0100 Subject: [PATCH 27/76] fixed phpstan issues --- .../DependencyInjection/Compiler/RepositoryCompiler.php | 3 --- phpstan.neon | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Infrastructure/Symfony/DependencyInjection/Compiler/RepositoryCompiler.php b/Infrastructure/Symfony/DependencyInjection/Compiler/RepositoryCompiler.php index d16c333..757404b 100644 --- a/Infrastructure/Symfony/DependencyInjection/Compiler/RepositoryCompiler.php +++ b/Infrastructure/Symfony/DependencyInjection/Compiler/RepositoryCompiler.php @@ -4,7 +4,6 @@ use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; class RepositoryCompiler implements CompilerPassInterface { @@ -26,8 +25,6 @@ public function process(ContainerBuilder $container) } /** - * @param Definition[] $services - * * @return void */ protected function setRepositoryAliases(array $services) diff --git a/phpstan.neon b/phpstan.neon index cdc4c86..a85943e 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -2,3 +2,6 @@ parameters: excludePaths: analyse: - vendor + ignoreErrors: + - '#.*unknown class Ivoz\\Provider\\.*#' + - '#.*has invalid type Ivoz\\Provider\\.*#' From 665b2a1f23feda18301f65da8fd6d92ed1876760 Mon Sep 17 00:00:00 2001 From: Mikel Date: Mon, 21 Feb 2022 10:09:57 +0100 Subject: [PATCH 28/76] updated DataTransferObjectInterface hints --- Application/DataTransferObjectInterface.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Application/DataTransferObjectInterface.php b/Application/DataTransferObjectInterface.php index c15d340..d5e7d93 100755 --- a/Application/DataTransferObjectInterface.php +++ b/Application/DataTransferObjectInterface.php @@ -22,7 +22,13 @@ public function setId(int|string $id); public function getId(); public function normalize(string $context, string $role = ''): array; public function denormalize(array $data, string $context, string $role = ''): void; + /** + * @return array + */ public static function getPropertyMap(string $context = '', string $role = null): array; public function getSensitiveFields(): array; + /** + * @return array + */ public function toArray(bool $hideSensitiveData = false): array; } From 4989429a7a22cd984763be1fff19c70358cb8fba Mon Sep 17 00:00:00 2001 From: Mikel Madariaga Date: Thu, 16 Dec 2021 10:44:44 +0100 Subject: [PATCH 29/76] fixed array of arrays response attributes in DtoNormalizer --- Application/Model/DtoNormalizer.php | 34 ++++++++++++----------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/Application/Model/DtoNormalizer.php b/Application/Model/DtoNormalizer.php index 258b249..cb92a53 100644 --- a/Application/Model/DtoNormalizer.php +++ b/Application/Model/DtoNormalizer.php @@ -52,39 +52,33 @@ function ($key) use ($contextProperties) { } $validSubKeys = $contextProperties[$key]; - $response[$key] = $this->filterResponseValues($val, $validSubKeys); + $response[$key] = $this->filterResponseSubProperties( + $val, + $validSubKeys + ); } return $response; } - private function filterResponseValues($value, $validSubKeys) + private function filterResponseSubProperties(array $values, array $validSubKeys): array { - $filterCollectionItems = - is_array($value) - && is_array($validSubKeys) - && array_key_exists(0, $validSubKeys) - && is_array($validSubKeys[0]); - - if ($filterCollectionItems) { - foreach ($value as $k => $itemValue) { - $value[$k] = $this->filterResponseValues( - $value[$k], + if (is_array($validSubKeys[0])) { + $response = []; + foreach($values as $k => $value) { + $response[$k] = $this->filterResponseSubProperties( + $value, $validSubKeys[0] ); - - if (empty($value[$k])) { - unset($value[$k]); - } } - return $value; + return $response; } return array_filter( - $value, - function ($subkey) use ($validSubKeys) { - return in_array($subkey, $validSubKeys); + $values, + function ($key) use ($validSubKeys) { + return in_array($key, $validSubKeys); }, ARRAY_FILTER_USE_KEY ); From 95f333197dc308e51309f0003ced381edb3946a4 Mon Sep 17 00:00:00 2001 From: Mikel Madariaga Date: Thu, 16 Dec 2021 12:41:34 +0100 Subject: [PATCH 30/76] improved DtoNormalizer misconfiguration feedback --- Application/Model/DtoNormalizer.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Application/Model/DtoNormalizer.php b/Application/Model/DtoNormalizer.php index cb92a53..3f33ed5 100644 --- a/Application/Model/DtoNormalizer.php +++ b/Application/Model/DtoNormalizer.php @@ -52,6 +52,10 @@ function ($key) use ($contextProperties) { } $validSubKeys = $contextProperties[$key]; + if (!is_array($validSubKeys)) { + throw new \RuntimeException($key . ' context properties were expected to be array'); + } + $response[$key] = $this->filterResponseSubProperties( $val, $validSubKeys @@ -63,6 +67,10 @@ function ($key) use ($contextProperties) { private function filterResponseSubProperties(array $values, array $validSubKeys): array { + if (empty($validSubKeys)) { + return []; + } + if (is_array($validSubKeys[0])) { $response = []; foreach($values as $k => $value) { From bb7471b03fbb261ff772d3c2a55a82a40e6d6eb5 Mon Sep 17 00:00:00 2001 From: Mikel Madariaga Date: Mon, 3 Jan 2022 12:12:44 +0100 Subject: [PATCH 31/76] disable DQL query cache on DataGateway As it doesn't require arguments to be properly escaped it may end generating millions of cache files --- Application/Service/DataGateway.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Application/Service/DataGateway.php b/Application/Service/DataGateway.php index 9cc20bd..5fa6672 100755 --- a/Application/Service/DataGateway.php +++ b/Application/Service/DataGateway.php @@ -158,6 +158,7 @@ public function findBy( ->createFromArguments($entityName, $criteria, $orderBy, $limit, $offset) ->getQuery(); + $query->useQueryCache(false); $results = $query->getResult(); $response = []; @@ -194,6 +195,7 @@ public function findAllBy( ->setFirstResult(($currentPage - 1) * $chunkSize); $query = $qb->getQuery(); + $query->useQueryCache(false); $results = $query->getResult(); $continue = count($results) === $chunkSize; $currentPage++; @@ -250,6 +252,7 @@ public function countBy(string $entityName, array $criteria = null) $query = $queryBuilder ->getQuery(); + $query->useQueryCache(false); return $query->getSingleScalarResult(); } From ac9566ac170076262731fb2e34665f73f9ea39d3 Mon Sep 17 00:00:00 2001 From: Mikel Madariaga Date: Tue, 8 Feb 2022 09:17:05 +0100 Subject: [PATCH 32/76] improved changelog detection --- .../Service/Lifecycle/CommandPersister.php | 29 +++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/Infrastructure/Domain/Service/Lifecycle/CommandPersister.php b/Infrastructure/Domain/Service/Lifecycle/CommandPersister.php index 54fd2fa..6944c30 100755 --- a/Infrastructure/Domain/Service/Lifecycle/CommandPersister.php +++ b/Infrastructure/Domain/Service/Lifecycle/CommandPersister.php @@ -44,6 +44,8 @@ public function persistEvents() return; } + $entityChangeMap = []; + $commandNum = $this ->commandEventSubscriber ->countEvents(); @@ -75,7 +77,7 @@ public function persistEvents() * Command is null when first persisted entity comes from pre_persist event: * changelog will require to hit db twice */ - $command = $this + $this ->commandEventSubscriber ->getLatest(); @@ -92,9 +94,32 @@ public function persistEvents() $commandlog ); + $entity = $changeLog->getEntity() . '#' . $changeLog->getEntityId(); + $prevEntityData = array_key_exists($entity, $entityChangeMap) + ? $entityChangeMap[$entity] + : []; + + if (!isset($entityChangeMap[$entity])) { + $entityChangeMap[$entity] = []; + } + + $currentEntityData = $changeLog->getData(); + if (!is_array($currentEntityData)) { + $currentEntityData = []; + } + $dataDiff = array_diff( + $currentEntityData, + $prevEntityData + ); + $entityChangeMap[$entity] = $currentEntityData; + + if (count($dataDiff) !== count($currentEntityData)) { + $changeLog->replaceData($dataDiff); + } + $this->entityPersister->persist($changeLog); - $data = json_encode($changeLog->getData()); + $data = json_encode($dataDiff); if (strlen($data) > 140) { $data = substr($data, 0, 140) . '...'; } From d7383b019cf7665de5fbfeebd6b00cb448597018 Mon Sep 17 00:00:00 2001 From: Mikel Date: Thu, 10 Mar 2022 18:49:12 +0100 Subject: [PATCH 33/76] updated dependencies --- composer.json | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 11b6337..4a50c82 100644 --- a/composer.json +++ b/composer.json @@ -27,7 +27,7 @@ "php": ">=8.0", "beberlei/assert": "^3.0", "doctrine/orm": "^2.8", - "doctrine/dbal": "^2.12.1", + "doctrine/dbal": "^2.12.1 || ^3.2", "doctrine/doctrine-migrations-bundle": "^3.0.3", "graze/guzzle-jsonrpc": "3.2.*", "guzzlehttp/guzzle": "^6.3", @@ -41,5 +41,24 @@ }, "require-dev": { "phpstan/phpstan": "^1.0" + }, + "conflict": { + "symfony/security-bundle": "^6.0", + "symfony/security-core": "^6.0", + "symfony/security-csrf": "^6.0", + "symfony/security-http": "^6.0", + "symfony/stopwatch": "^6.0", + "symfony/string": "^6.0", + "symfony/twig-bridge": "^6.0", + "symfony/var-exporter": "^6.0", + "symfony/web-link": "^6.0", + "symfony/translation": "^6.0", + "symfony/yaml": "^6.0", + "symfony/cache": "^6.0", + "symfony/event-dispatcher": "^6.0", + "symfony/filesystem": "^6.0", + "symfony/monolog-bridge": "^6.0", + "symfony/options-resolver": "^6.0", + "symfony/password-hasher": "^6.0" } } From 9617f78a1833cca776b673791db8c193f3d93edc Mon Sep 17 00:00:00 2001 From: Mikel Madariaga Date: Fri, 11 Mar 2022 12:57:21 +0100 Subject: [PATCH 34/76] BC updated ChangelogTrait.createDto response signature --- Domain/Model/ChangelogTrait.php | 2 +- .../Persistence/Doctrine/Model/DBAL/Types/UtcDateTimeType.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Domain/Model/ChangelogTrait.php b/Domain/Model/ChangelogTrait.php index 47f86b5..fee7f50 100644 --- a/Domain/Model/ChangelogTrait.php +++ b/Domain/Model/ChangelogTrait.php @@ -24,7 +24,7 @@ trait ChangelogTrait abstract public function getId(); abstract protected function __toArray(); - abstract public static function createDto(string|int $id = null); + abstract public static function createDto(string|int $id = null): DataTransferObjectInterface; /** * TRUE on new entities until transaction is closed diff --git a/Infrastructure/Persistence/Doctrine/Model/DBAL/Types/UtcDateTimeType.php b/Infrastructure/Persistence/Doctrine/Model/DBAL/Types/UtcDateTimeType.php index 38b97f6..a41ea96 100755 --- a/Infrastructure/Persistence/Doctrine/Model/DBAL/Types/UtcDateTimeType.php +++ b/Infrastructure/Persistence/Doctrine/Model/DBAL/Types/UtcDateTimeType.php @@ -10,7 +10,7 @@ class UtcDateTimeType extends DateTimeType { static private $utc; - public function convertToDatabaseValue($value, AbstractPlatform $platform) + public function convertToDatabaseValue($value, AbstractPlatform $platform): mixed { if (is_string($value)) { return $value; From 8a79a96e554a3ef3b525fe338015f7fae283ab9c Mon Sep 17 00:00:00 2001 From: Mikel Madariaga Date: Mon, 14 Mar 2022 12:03:12 +0100 Subject: [PATCH 35/76] moved Changelog from Provider to Core namespace --- Domain/Model/Changelog/Changelog.php | 62 ++++ Domain/Model/Changelog/ChangelogAbstract.php | 298 +++++++++++++++++ Domain/Model/Changelog/ChangelogDto.php | 8 + .../Model/Changelog/ChangelogDtoAbstract.php | 207 ++++++++++++ Domain/Model/Changelog/ChangelogInterface.php | 68 ++++ .../Model/Changelog/ChangelogRepository.php | 11 + Domain/Model/Changelog/ChangelogTrait.php | 82 +++++ Domain/Model/Commandlog/Commandlog.php | 51 +++ .../Model/Commandlog/CommandlogAbstract.php | 315 ++++++++++++++++++ Domain/Model/Commandlog/CommandlogDto.php | 8 + .../Commandlog/CommandlogDtoAbstract.php | 207 ++++++++++++ .../Model/Commandlog/CommandlogInterface.php | 63 ++++ .../Model/Commandlog/CommandlogRepository.php | 11 + Domain/Model/Commandlog/CommandlogTrait.php | 82 +++++ .../Service/Lifecycle/CommandPersister.php | 4 +- .../Doctrine/LoggableMigration.php | 4 +- .../Mapping/Changelog.Changelog.orm.xml | 11 + .../Changelog.ChangelogAbstract.orm.xml | 24 ++ .../Mapping/Commandlog.Commandlog.orm.xml | 11 + .../Commandlog.CommandlogAbstract.orm.xml | 20 ++ 20 files changed, 1543 insertions(+), 4 deletions(-) create mode 100644 Domain/Model/Changelog/Changelog.php create mode 100644 Domain/Model/Changelog/ChangelogAbstract.php create mode 100644 Domain/Model/Changelog/ChangelogDto.php create mode 100644 Domain/Model/Changelog/ChangelogDtoAbstract.php create mode 100644 Domain/Model/Changelog/ChangelogInterface.php create mode 100644 Domain/Model/Changelog/ChangelogRepository.php create mode 100644 Domain/Model/Changelog/ChangelogTrait.php create mode 100644 Domain/Model/Commandlog/Commandlog.php create mode 100644 Domain/Model/Commandlog/CommandlogAbstract.php create mode 100644 Domain/Model/Commandlog/CommandlogDto.php create mode 100644 Domain/Model/Commandlog/CommandlogDtoAbstract.php create mode 100644 Domain/Model/Commandlog/CommandlogInterface.php create mode 100644 Domain/Model/Commandlog/CommandlogRepository.php create mode 100644 Domain/Model/Commandlog/CommandlogTrait.php create mode 100644 Infrastructure/Persistence/Doctrine/Mapping/Changelog.Changelog.orm.xml create mode 100644 Infrastructure/Persistence/Doctrine/Mapping/Changelog.ChangelogAbstract.orm.xml create mode 100644 Infrastructure/Persistence/Doctrine/Mapping/Commandlog.Commandlog.orm.xml create mode 100644 Infrastructure/Persistence/Doctrine/Mapping/Commandlog.CommandlogAbstract.orm.xml diff --git a/Domain/Model/Changelog/Changelog.php b/Domain/Model/Changelog/Changelog.php new file mode 100644 index 0000000..d3c3799 --- /dev/null +++ b/Domain/Model/Changelog/Changelog.php @@ -0,0 +1,62 @@ +getEntityClass(), + (string) $event->getEntityId(), + $event->getOccurredOn(), + $event->getMicrotime() + ); + + $entity->id = $event->getId(); + $entity->setData( + $event->getData() + ); + + $entity->setCommand($command); + + $entity->sanitizeValues(); + $entity->initChangelog(); + + return $entity; + } + + /** + * @param array $data | null + * @return static + */ + public function replaceData($data = null) + { + return $this->setData($data); + } + + /** + * Get id + * @codeCoverageIgnore + * @return string + */ + public function getId(): ?string + { + return $this->id; + } +} diff --git a/Domain/Model/Changelog/ChangelogAbstract.php b/Domain/Model/Changelog/ChangelogAbstract.php new file mode 100644 index 0000000..8090018 --- /dev/null +++ b/Domain/Model/Changelog/ChangelogAbstract.php @@ -0,0 +1,298 @@ +setEntity($entity); + $this->setEntityId($entityId); + $this->setCreatedOn($createdOn); + $this->setMicrotime($microtime); + } + + abstract public function getId(): null|string|int; + + public function __toString(): string + { + return sprintf( + "%s#%s", + "Changelog", + (string) $this->getId() + ); + } + + /** + * @throws \Exception + */ + protected function sanitizeValues(): void + { + } + + public static function createDto(string|int|null $id = null): ChangelogDto + { + return new ChangelogDto($id); + } + + /** + * @internal use EntityTools instead + * @param null|ChangelogInterface $entity + */ + public static function entityToDto(?EntityInterface $entity, int $depth = 0): ?ChangelogDto + { + if (!$entity) { + return null; + } + + Assertion::isInstanceOf($entity, ChangelogInterface::class); + + if ($depth < 1) { + return static::createDto($entity->getId()); + } + + if ($entity instanceof \Doctrine\ORM\Proxy\Proxy && !$entity->__isInitialized()) { + return static::createDto($entity->getId()); + } + + $dto = $entity->toDto($depth - 1); + + return $dto; + } + + /** + * Factory method + * @internal use EntityTools instead + * @param ChangelogDto $dto + */ + public static function fromDto( + DataTransferObjectInterface $dto, + ForeignKeyTransformerInterface $fkTransformer + ): static { + Assertion::isInstanceOf($dto, ChangelogDto::class); + $entity = $dto->getEntity(); + Assertion::notNull($entity, 'getEntity value is null, but non null value was expected.'); + $entityId = $dto->getEntityId(); + Assertion::notNull($entityId, 'getEntityId value is null, but non null value was expected.'); + $createdOn = $dto->getCreatedOn(); + Assertion::notNull($createdOn, 'getCreatedOn value is null, but non null value was expected.'); + $microtime = $dto->getMicrotime(); + Assertion::notNull($microtime, 'getMicrotime value is null, but non null value was expected.'); + $command = $dto->getCommand(); + Assertion::notNull($command, 'getCommand value is null, but non null value was expected.'); + + $self = new static( + $entity, + $entityId, + $createdOn, + $microtime + ); + + $self + ->setData($dto->getData()) + ->setCommand($fkTransformer->transform($command)); + + $self->initChangelog(); + + return $self; + } + + /** + * @internal use EntityTools instead + * @param ChangelogDto $dto + */ + public function updateFromDto( + DataTransferObjectInterface $dto, + ForeignKeyTransformerInterface $fkTransformer + ): static { + Assertion::isInstanceOf($dto, ChangelogDto::class); + + $entity = $dto->getEntity(); + Assertion::notNull($entity, 'getEntity value is null, but non null value was expected.'); + $entityId = $dto->getEntityId(); + Assertion::notNull($entityId, 'getEntityId value is null, but non null value was expected.'); + $createdOn = $dto->getCreatedOn(); + Assertion::notNull($createdOn, 'getCreatedOn value is null, but non null value was expected.'); + $microtime = $dto->getMicrotime(); + Assertion::notNull($microtime, 'getMicrotime value is null, but non null value was expected.'); + $command = $dto->getCommand(); + Assertion::notNull($command, 'getCommand value is null, but non null value was expected.'); + + $this + ->setEntity($entity) + ->setEntityId($entityId) + ->setData($dto->getData()) + ->setCreatedOn($createdOn) + ->setMicrotime($microtime) + ->setCommand($fkTransformer->transform($command)); + + return $this; + } + + /** + * @internal use EntityTools instead + */ + public function toDto(int $depth = 0): ChangelogDto + { + return self::createDto() + ->setEntity(self::getEntity()) + ->setEntityId(self::getEntityId()) + ->setData(self::getData()) + ->setCreatedOn(self::getCreatedOn()) + ->setMicrotime(self::getMicrotime()) + ->setCommand(Commandlog::entityToDto(self::getCommand(), $depth)); + } + + protected function __toArray(): array + { + return [ + 'entity' => self::getEntity(), + 'entityId' => self::getEntityId(), + 'data' => self::getData(), + 'createdOn' => self::getCreatedOn(), + 'microtime' => self::getMicrotime(), + 'commandId' => self::getCommand()->getId() + ]; + } + + protected function setEntity(string $entity): static + { + Assertion::maxLength($entity, 150, 'entity value "%s" is too long, it should have no more than %d characters, but has %d characters.'); + + $this->entity = $entity; + + return $this; + } + + public function getEntity(): string + { + return $this->entity; + } + + protected function setEntityId(string $entityId): static + { + Assertion::maxLength($entityId, 36, 'entityId value "%s" is too long, it should have no more than %d characters, but has %d characters.'); + + $this->entityId = $entityId; + + return $this; + } + + public function getEntityId(): string + { + return $this->entityId; + } + + protected function setData(?array $data = null): static + { + $this->data = $data; + + return $this; + } + + public function getData(): ?array + { + return $this->data; + } + + protected function setCreatedOn(string|\DateTimeInterface $createdOn): static + { + + /** @var \Datetime */ + $createdOn = DateTimeHelper::createOrFix( + $createdOn, + null + ); + + if ($this->isInitialized() && $this->createdOn == $createdOn) { + return $this; + } + + $this->createdOn = $createdOn; + + return $this; + } + + public function getCreatedOn(): \DateTime + { + return clone $this->createdOn; + } + + protected function setMicrotime(int $microtime): static + { + $this->microtime = $microtime; + + return $this; + } + + public function getMicrotime(): int + { + return $this->microtime; + } + + protected function setCommand(CommandlogInterface $command): static + { + $this->command = $command; + + return $this; + } + + public function getCommand(): CommandlogInterface + { + return $this->command; + } +} diff --git a/Domain/Model/Changelog/ChangelogDto.php b/Domain/Model/Changelog/ChangelogDto.php new file mode 100644 index 0000000..5fa87ab --- /dev/null +++ b/Domain/Model/Changelog/ChangelogDto.php @@ -0,0 +1,8 @@ +setId($id); + } + + /** + * @inheritdoc + */ + public static function getPropertyMap(string $context = '', string $role = null): array + { + if ($context === self::CONTEXT_COLLECTION) { + return ['id' => 'id']; + } + + return [ + 'entity' => 'entity', + 'entityId' => 'entityId', + 'data' => 'data', + 'createdOn' => 'createdOn', + 'microtime' => 'microtime', + 'id' => 'id', + 'commandId' => 'command' + ]; + } + + /** + * @return array + */ + public function toArray(bool $hideSensitiveData = false): array + { + $response = [ + 'entity' => $this->getEntity(), + 'entityId' => $this->getEntityId(), + 'data' => $this->getData(), + 'createdOn' => $this->getCreatedOn(), + 'microtime' => $this->getMicrotime(), + 'id' => $this->getId(), + 'command' => $this->getCommand() + ]; + + if (!$hideSensitiveData) { + return $response; + } + + foreach ($this->sensitiveFields as $sensitiveField) { + if (!array_key_exists($sensitiveField, $response)) { + throw new \Exception($sensitiveField . ' field was not found'); + } + $response[$sensitiveField] = '*****'; + } + + return $response; + } + + public function setEntity(string $entity): static + { + $this->entity = $entity; + + return $this; + } + + public function getEntity(): ?string + { + return $this->entity; + } + + public function setEntityId(string $entityId): static + { + $this->entityId = $entityId; + + return $this; + } + + public function getEntityId(): ?string + { + return $this->entityId; + } + + public function setData(?array $data): static + { + $this->data = $data; + + return $this; + } + + public function getData(): ?array + { + return $this->data; + } + + public function setCreatedOn(\DateTimeInterface|string $createdOn): static + { + $this->createdOn = $createdOn; + + return $this; + } + + public function getCreatedOn(): \DateTimeInterface|string|null + { + return $this->createdOn; + } + + public function setMicrotime(int $microtime): static + { + $this->microtime = $microtime; + + return $this; + } + + public function getMicrotime(): ?int + { + return $this->microtime; + } + + public function setId($id): static + { + $this->id = $id; + + return $this; + } + + public function getId(): ?string + { + return $this->id; + } + + public function setCommand(?CommandlogDto $command): static + { + $this->command = $command; + + return $this; + } + + public function getCommand(): ?CommandlogDto + { + return $this->command; + } + + public function setCommandId($id): static + { + $value = !is_null($id) + ? new CommandlogDto($id) + : null; + + return $this->setCommand($value); + } + + public function getCommandId() + { + if ($dto = $this->getCommand()) { + return $dto->getId(); + } + + return null; + } +} diff --git a/Domain/Model/Changelog/ChangelogInterface.php b/Domain/Model/Changelog/ChangelogInterface.php new file mode 100644 index 0000000..a5ea3dd --- /dev/null +++ b/Domain/Model/Changelog/ChangelogInterface.php @@ -0,0 +1,68 @@ + $data | null + * @return static + */ + public function replaceData($data = null); + + /** + * Get id + * @codeCoverageIgnore + * @return string + */ + public function getId(): ?string; + + public static function createDto(string|int|null $id = null): ChangelogDto; + + /** + * @internal use EntityTools instead + * @param null|ChangelogInterface $entity + */ + public static function entityToDto(?EntityInterface $entity, int $depth = 0): ?ChangelogDto; + + /** + * Factory method + * @internal use EntityTools instead + * @param ChangelogDto $dto + */ + public static function fromDto(DataTransferObjectInterface $dto, ForeignKeyTransformerInterface $fkTransformer): static; + + /** + * @internal use EntityTools instead + */ + public function toDto(int $depth = 0): ChangelogDto; + + public function getEntity(): string; + + public function getEntityId(): string; + + public function getData(): ?array; + + public function getCreatedOn(): \DateTime; + + public function getMicrotime(): int; + + public function getCommand(): CommandlogInterface; + + public function isInitialized(): bool; +} diff --git a/Domain/Model/Changelog/ChangelogRepository.php b/Domain/Model/Changelog/ChangelogRepository.php new file mode 100644 index 0000000..d74e299 --- /dev/null +++ b/Domain/Model/Changelog/ChangelogRepository.php @@ -0,0 +1,11 @@ +sanitizeValues(); + if ($dto->getId()) { + $self->id = $dto->getId(); + $self->initChangelog(); + } + + return $self; + } + + /** + * @internal use EntityTools instead + * @param ChangelogDto $dto + */ + public function updateFromDto( + DataTransferObjectInterface $dto, + ForeignKeyTransformerInterface $fkTransformer + ): static { + parent::updateFromDto($dto, $fkTransformer); + + $this->sanitizeValues(); + + return $this; + } + + /** + * @internal use EntityTools instead + */ + public function toDto(int $depth = 0): ChangelogDto + { + $dto = parent::toDto($depth); + return $dto + ->setId($this->getId()); + } + + protected function __toArray(): array + { + return parent::__toArray() + [ + 'id' => self::getId() + ]; + } +} diff --git a/Domain/Model/Commandlog/Commandlog.php b/Domain/Model/Commandlog/Commandlog.php new file mode 100644 index 0000000..22ee44f --- /dev/null +++ b/Domain/Model/Commandlog/Commandlog.php @@ -0,0 +1,51 @@ +id; + } + + /** + * @param \Ivoz\Core\Application\Event\CommandEventInterface $event + * @return self + */ + public static function fromEvent(CommandEventInterface $event) + { + $entity = new static( + $event->getRequestId(), + $event->getService(), + $event->getOccurredOn(), + $event->getMicrotime() + ); + + $entity->id = $event->getId(); + $entity->setAgent( + $event->getAgent() + ); + $entity->setMethod( + $event->getMethod() + ); + $entity->setArguments( + $event->getArguments() + ); + + $entity->sanitizeValues(); + $entity->initChangelog(); + + return $entity; + } +} diff --git a/Domain/Model/Commandlog/CommandlogAbstract.php b/Domain/Model/Commandlog/CommandlogAbstract.php new file mode 100644 index 0000000..a2f7deb --- /dev/null +++ b/Domain/Model/Commandlog/CommandlogAbstract.php @@ -0,0 +1,315 @@ +setRequestId($requestId); + $this->setClass($class); + $this->setCreatedOn($createdOn); + $this->setMicrotime($microtime); + } + + abstract public function getId(): null|string|int; + + public function __toString(): string + { + return sprintf( + "%s#%s", + "Commandlog", + (string) $this->getId() + ); + } + + /** + * @throws \Exception + */ + protected function sanitizeValues(): void + { + } + + public static function createDto(string|int|null $id = null): CommandlogDto + { + return new CommandlogDto($id); + } + + /** + * @internal use EntityTools instead + * @param null|CommandlogInterface $entity + */ + public static function entityToDto(?EntityInterface $entity, int $depth = 0): ?CommandlogDto + { + if (!$entity) { + return null; + } + + Assertion::isInstanceOf($entity, CommandlogInterface::class); + + if ($depth < 1) { + return static::createDto($entity->getId()); + } + + if ($entity instanceof \Doctrine\ORM\Proxy\Proxy && !$entity->__isInitialized()) { + return static::createDto($entity->getId()); + } + + $dto = $entity->toDto($depth - 1); + + return $dto; + } + + /** + * Factory method + * @internal use EntityTools instead + * @param CommandlogDto $dto + */ + public static function fromDto( + DataTransferObjectInterface $dto, + ForeignKeyTransformerInterface $fkTransformer + ): static { + Assertion::isInstanceOf($dto, CommandlogDto::class); + $requestId = $dto->getRequestId(); + Assertion::notNull($requestId, 'getRequestId value is null, but non null value was expected.'); + $class = $dto->getClass(); + Assertion::notNull($class, 'getClass value is null, but non null value was expected.'); + $createdOn = $dto->getCreatedOn(); + Assertion::notNull($createdOn, 'getCreatedOn value is null, but non null value was expected.'); + $microtime = $dto->getMicrotime(); + Assertion::notNull($microtime, 'getMicrotime value is null, but non null value was expected.'); + + $self = new static( + $requestId, + $class, + $createdOn, + $microtime + ); + + $self + ->setMethod($dto->getMethod()) + ->setArguments($dto->getArguments()) + ->setAgent($dto->getAgent()); + + $self->initChangelog(); + + return $self; + } + + /** + * @internal use EntityTools instead + * @param CommandlogDto $dto + */ + public function updateFromDto( + DataTransferObjectInterface $dto, + ForeignKeyTransformerInterface $fkTransformer + ): static { + Assertion::isInstanceOf($dto, CommandlogDto::class); + + $requestId = $dto->getRequestId(); + Assertion::notNull($requestId, 'getRequestId value is null, but non null value was expected.'); + $class = $dto->getClass(); + Assertion::notNull($class, 'getClass value is null, but non null value was expected.'); + $createdOn = $dto->getCreatedOn(); + Assertion::notNull($createdOn, 'getCreatedOn value is null, but non null value was expected.'); + $microtime = $dto->getMicrotime(); + Assertion::notNull($microtime, 'getMicrotime value is null, but non null value was expected.'); + + $this + ->setRequestId($requestId) + ->setClass($class) + ->setMethod($dto->getMethod()) + ->setArguments($dto->getArguments()) + ->setAgent($dto->getAgent()) + ->setCreatedOn($createdOn) + ->setMicrotime($microtime); + + return $this; + } + + /** + * @internal use EntityTools instead + */ + public function toDto(int $depth = 0): CommandlogDto + { + return self::createDto() + ->setRequestId(self::getRequestId()) + ->setClass(self::getClass()) + ->setMethod(self::getMethod()) + ->setArguments(self::getArguments()) + ->setAgent(self::getAgent()) + ->setCreatedOn(self::getCreatedOn()) + ->setMicrotime(self::getMicrotime()); + } + + protected function __toArray(): array + { + return [ + 'requestId' => self::getRequestId(), + 'class' => self::getClass(), + 'method' => self::getMethod(), + 'arguments' => self::getArguments(), + 'agent' => self::getAgent(), + 'createdOn' => self::getCreatedOn(), + 'microtime' => self::getMicrotime() + ]; + } + + protected function setRequestId(string $requestId): static + { + $this->requestId = $requestId; + + return $this; + } + + public function getRequestId(): string + { + return $this->requestId; + } + + protected function setClass(string $class): static + { + Assertion::maxLength($class, 50, 'class value "%s" is too long, it should have no more than %d characters, but has %d characters.'); + + $this->class = $class; + + return $this; + } + + public function getClass(): string + { + return $this->class; + } + + protected function setMethod(?string $method = null): static + { + if (!is_null($method)) { + Assertion::maxLength($method, 64, 'method value "%s" is too long, it should have no more than %d characters, but has %d characters.'); + } + + $this->method = $method; + + return $this; + } + + public function getMethod(): ?string + { + return $this->method; + } + + protected function setArguments(?array $arguments = null): static + { + $this->arguments = $arguments; + + return $this; + } + + public function getArguments(): ?array + { + return $this->arguments; + } + + protected function setAgent(?array $agent = null): static + { + $this->agent = $agent; + + return $this; + } + + public function getAgent(): ?array + { + return $this->agent; + } + + protected function setCreatedOn(string|\DateTimeInterface $createdOn): static + { + + /** @var \Datetime */ + $createdOn = DateTimeHelper::createOrFix( + $createdOn, + null + ); + + if ($this->isInitialized() && $this->createdOn == $createdOn) { + return $this; + } + + $this->createdOn = $createdOn; + + return $this; + } + + public function getCreatedOn(): \DateTime + { + return clone $this->createdOn; + } + + protected function setMicrotime(int $microtime): static + { + $this->microtime = $microtime; + + return $this; + } + + public function getMicrotime(): int + { + return $this->microtime; + } +} diff --git a/Domain/Model/Commandlog/CommandlogDto.php b/Domain/Model/Commandlog/CommandlogDto.php new file mode 100644 index 0000000..9ad8e71 --- /dev/null +++ b/Domain/Model/Commandlog/CommandlogDto.php @@ -0,0 +1,8 @@ +setId($id); + } + + /** + * @inheritdoc + */ + public static function getPropertyMap(string $context = '', string $role = null): array + { + if ($context === self::CONTEXT_COLLECTION) { + return ['id' => 'id']; + } + + return [ + 'requestId' => 'requestId', + 'class' => 'class', + 'method' => 'method', + 'arguments' => 'arguments', + 'agent' => 'agent', + 'createdOn' => 'createdOn', + 'microtime' => 'microtime', + 'id' => 'id' + ]; + } + + /** + * @return array + */ + public function toArray(bool $hideSensitiveData = false): array + { + $response = [ + 'requestId' => $this->getRequestId(), + 'class' => $this->getClass(), + 'method' => $this->getMethod(), + 'arguments' => $this->getArguments(), + 'agent' => $this->getAgent(), + 'createdOn' => $this->getCreatedOn(), + 'microtime' => $this->getMicrotime(), + 'id' => $this->getId() + ]; + + if (!$hideSensitiveData) { + return $response; + } + + foreach ($this->sensitiveFields as $sensitiveField) { + if (!array_key_exists($sensitiveField, $response)) { + throw new \Exception($sensitiveField . ' field was not found'); + } + $response[$sensitiveField] = '*****'; + } + + return $response; + } + + public function setRequestId(string $requestId): static + { + $this->requestId = $requestId; + + return $this; + } + + public function getRequestId(): ?string + { + return $this->requestId; + } + + public function setClass(string $class): static + { + $this->class = $class; + + return $this; + } + + public function getClass(): ?string + { + return $this->class; + } + + public function setMethod(?string $method): static + { + $this->method = $method; + + return $this; + } + + public function getMethod(): ?string + { + return $this->method; + } + + public function setArguments(?array $arguments): static + { + $this->arguments = $arguments; + + return $this; + } + + public function getArguments(): ?array + { + return $this->arguments; + } + + public function setAgent(?array $agent): static + { + $this->agent = $agent; + + return $this; + } + + public function getAgent(): ?array + { + return $this->agent; + } + + public function setCreatedOn(\DateTimeInterface|string $createdOn): static + { + $this->createdOn = $createdOn; + + return $this; + } + + public function getCreatedOn(): \DateTimeInterface|string|null + { + return $this->createdOn; + } + + public function setMicrotime(int $microtime): static + { + $this->microtime = $microtime; + + return $this; + } + + public function getMicrotime(): ?int + { + return $this->microtime; + } + + public function setId($id): static + { + $this->id = $id; + + return $this; + } + + public function getId(): ?string + { + return $this->id; + } +} diff --git a/Domain/Model/Commandlog/CommandlogInterface.php b/Domain/Model/Commandlog/CommandlogInterface.php new file mode 100644 index 0000000..1826dde --- /dev/null +++ b/Domain/Model/Commandlog/CommandlogInterface.php @@ -0,0 +1,63 @@ +sanitizeValues(); + if ($dto->getId()) { + $self->id = $dto->getId(); + $self->initChangelog(); + } + + return $self; + } + + /** + * @internal use EntityTools instead + * @param CommandlogDto $dto + */ + public function updateFromDto( + DataTransferObjectInterface $dto, + ForeignKeyTransformerInterface $fkTransformer + ): static { + parent::updateFromDto($dto, $fkTransformer); + + $this->sanitizeValues(); + + return $this; + } + + /** + * @internal use EntityTools instead + */ + public function toDto(int $depth = 0): CommandlogDto + { + $dto = parent::toDto($depth); + return $dto + ->setId($this->getId()); + } + + protected function __toArray(): array + { + return parent::__toArray() + [ + 'id' => self::getId() + ]; + } +} diff --git a/Infrastructure/Domain/Service/Lifecycle/CommandPersister.php b/Infrastructure/Domain/Service/Lifecycle/CommandPersister.php index 6944c30..03da8e1 100755 --- a/Infrastructure/Domain/Service/Lifecycle/CommandPersister.php +++ b/Infrastructure/Domain/Service/Lifecycle/CommandPersister.php @@ -6,8 +6,8 @@ use Ivoz\Core\Application\Service\CommandEventSubscriber; use Ivoz\Core\Domain\Service\EntityEventSubscriber; use Ivoz\Core\Domain\Service\EntityPersisterInterface; -use Ivoz\Provider\Domain\Model\Changelog\Changelog; -use Ivoz\Provider\Domain\Model\Commandlog\Commandlog; +use Ivoz\Core\Domain\Model\Changelog\Changelog; +use Ivoz\Core\Domain\Model\Commandlog\Commandlog; use Psr\Log\LoggerInterface; class CommandPersister diff --git a/Infrastructure/Persistence/Doctrine/LoggableMigration.php b/Infrastructure/Persistence/Doctrine/LoggableMigration.php index bc58ebe..d9b0092 100644 --- a/Infrastructure/Persistence/Doctrine/LoggableMigration.php +++ b/Infrastructure/Persistence/Doctrine/LoggableMigration.php @@ -6,8 +6,8 @@ use Doctrine\DBAL\Schema\Schema; use Ivoz\Core\Application\Event\CommandWasExecuted; use Ivoz\Core\Domain\Event\EntityWasUpdated; -use Ivoz\Provider\Domain\Model\Changelog\Changelog; -use Ivoz\Provider\Domain\Model\Commandlog\Commandlog; +use Ivoz\Core\Domain\Model\Changelog\Changelog; +use Ivoz\Core\Domain\Model\Commandlog\Commandlog; abstract class LoggableMigration extends AbstractMigration { diff --git a/Infrastructure/Persistence/Doctrine/Mapping/Changelog.Changelog.orm.xml b/Infrastructure/Persistence/Doctrine/Mapping/Changelog.Changelog.orm.xml new file mode 100644 index 0000000..b4a1148 --- /dev/null +++ b/Infrastructure/Persistence/Doctrine/Mapping/Changelog.Changelog.orm.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/Infrastructure/Persistence/Doctrine/Mapping/Changelog.ChangelogAbstract.orm.xml b/Infrastructure/Persistence/Doctrine/Mapping/Changelog.ChangelogAbstract.orm.xml new file mode 100644 index 0000000..ab6fd45 --- /dev/null +++ b/Infrastructure/Persistence/Doctrine/Mapping/Changelog.ChangelogAbstract.orm.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Infrastructure/Persistence/Doctrine/Mapping/Commandlog.Commandlog.orm.xml b/Infrastructure/Persistence/Doctrine/Mapping/Commandlog.Commandlog.orm.xml new file mode 100644 index 0000000..ea8a882 --- /dev/null +++ b/Infrastructure/Persistence/Doctrine/Mapping/Commandlog.Commandlog.orm.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/Infrastructure/Persistence/Doctrine/Mapping/Commandlog.CommandlogAbstract.orm.xml b/Infrastructure/Persistence/Doctrine/Mapping/Commandlog.CommandlogAbstract.orm.xml new file mode 100644 index 0000000..6d579b6 --- /dev/null +++ b/Infrastructure/Persistence/Doctrine/Mapping/Commandlog.CommandlogAbstract.orm.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + From 782d9bb9d2b2f8907ad33ac0dade6900cdf27327 Mon Sep 17 00:00:00 2001 From: Mikel Date: Tue, 15 Mar 2022 10:29:41 +0100 Subject: [PATCH 36/76] fixed phpstan issues and removed doctrine/dbal 2.x compatibility --- Domain/Model/ChangelogTrait.php | 2 +- Infrastructure/Domain/Service/DoctrineQueryRunner.php | 7 ------- Infrastructure/Persistence/Doctrine/ORM/EntityManager.php | 7 +++---- .../Persistence/Doctrine/ORM/Mapping/QuoteStrategy.php | 5 ++++- .../Doctrine/Service/DuplicateEntryCommonErrorHandler.php | 4 ++-- .../Symfony/EventListener/DomainExceptionListener.php | 6 +++++- composer.json | 2 +- phpstan.neon | 2 ++ 8 files changed, 18 insertions(+), 17 deletions(-) diff --git a/Domain/Model/ChangelogTrait.php b/Domain/Model/ChangelogTrait.php index fee7f50..088f56c 100644 --- a/Domain/Model/ChangelogTrait.php +++ b/Domain/Model/ChangelogTrait.php @@ -92,7 +92,7 @@ public function hasChanged(string $dbFieldName): bool } /** - * @return array + * @return mixed|array * @throws \Exception */ public function getInitialValue(string $dbFieldName): mixed diff --git a/Infrastructure/Domain/Service/DoctrineQueryRunner.php b/Infrastructure/Domain/Service/DoctrineQueryRunner.php index 5daa0d3..226acaa 100755 --- a/Infrastructure/Domain/Service/DoctrineQueryRunner.php +++ b/Infrastructure/Domain/Service/DoctrineQueryRunner.php @@ -37,11 +37,7 @@ public function __construct( } /** - * @param string $entityName - * @param AbstractQuery $query * @return int affected rows - * @throws \Doctrine\DBAL\ConnectionException - * @throws \Doctrine\DBAL\DBALException */ public function execute(string $entityName, AbstractQuery $query) { @@ -121,10 +117,7 @@ public function execute(string $entityName, AbstractQuery $query) } /** - * @param AbstractQuery $query - * @param EntityEventInterface $event * @return int $affectedRows - * @throws \Doctrine\DBAL\DBALException */ private function runQueryAndReturnAffectedRows(AbstractQuery $query, EntityEventInterface $event) { diff --git a/Infrastructure/Persistence/Doctrine/ORM/EntityManager.php b/Infrastructure/Persistence/Doctrine/ORM/EntityManager.php index c654a5c..d8a9038 100755 --- a/Infrastructure/Persistence/Doctrine/ORM/EntityManager.php +++ b/Infrastructure/Persistence/Doctrine/ORM/EntityManager.php @@ -29,11 +29,10 @@ private function setBufferedQuery(bool $enabled = true) // https://www.php.net/manual/en/mysqlinfo.concepts.buffering.php (function () use ($enabled) { - $this->connect(); - - /** @var \Doctrine\DBAL\Driver\PDO\Connection $connection */ - $connection = $this->_conn; + /** @var \PDO $connection */ + $connection = $this->getNativeConnection(); $driverName = $connection->getAttribute(\PDO::ATTR_DRIVER_NAME); + if ($driverName === 'mysql') { $connection->setAttribute( \PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, diff --git a/Infrastructure/Persistence/Doctrine/ORM/Mapping/QuoteStrategy.php b/Infrastructure/Persistence/Doctrine/ORM/Mapping/QuoteStrategy.php index 6c77c24..9027cfd 100644 --- a/Infrastructure/Persistence/Doctrine/ORM/Mapping/QuoteStrategy.php +++ b/Infrastructure/Persistence/Doctrine/ORM/Mapping/QuoteStrategy.php @@ -5,9 +5,12 @@ use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\ORM\Mapping\ClassMetadata; use Doctrine\ORM\Mapping\DefaultQuoteStrategy; +use Doctrine\ORM\Internal\SQLResultCasing; class QuoteStrategy extends DefaultQuoteStrategy { + use SQLResultCasing; + /** * {@inheritdoc} */ @@ -16,6 +19,6 @@ public function getColumnAlias($columnName, $counter, AbstractPlatform $platform $columnName = parent::getColumnAlias(...func_get_args()); $columnName = is_numeric($columnName[0]) ? '_' . $columnName : $columnName; - return $platform->getSQLResultCasing($columnName); + return $this->getSQLResultCasing($platform, $columnName); } } diff --git a/Infrastructure/Persistence/Doctrine/Service/DuplicateEntryCommonErrorHandler.php b/Infrastructure/Persistence/Doctrine/Service/DuplicateEntryCommonErrorHandler.php index c2a0d7a..6b566d3 100644 --- a/Infrastructure/Persistence/Doctrine/Service/DuplicateEntryCommonErrorHandler.php +++ b/Infrastructure/Persistence/Doctrine/Service/DuplicateEntryCommonErrorHandler.php @@ -2,7 +2,7 @@ namespace Ivoz\Core\Infrastructure\Persistence\Doctrine\Service; -use Doctrine\DBAL\Driver\PDOException; +use Doctrine\DBAL\Driver\PDO\Exception as PDOException; use Doctrine\DBAL\Exception\UniqueConstraintViolationException; use Ivoz\Core\Domain\Service\CommonPersistErrorHandlerInterface; @@ -34,7 +34,7 @@ public function handle(\Throwable $exception) return; } - $isDuplicatedError = $pdoException->getErrorCode() === self::MYSQL_ERROR_DUPLICATE_ENTRY; + $isDuplicatedError = $pdoException->getCode() === self::MYSQL_ERROR_DUPLICATE_ENTRY; if ($isDuplicatedError) { throw new \DomainException( diff --git a/Infrastructure/Symfony/EventListener/DomainExceptionListener.php b/Infrastructure/Symfony/EventListener/DomainExceptionListener.php index 5d34509..a050178 100644 --- a/Infrastructure/Symfony/EventListener/DomainExceptionListener.php +++ b/Infrastructure/Symfony/EventListener/DomainExceptionListener.php @@ -25,9 +25,13 @@ public function onKernelException(ExceptionEvent $event) return; } + $exceptionCode = $exception->getCode() + ? $exception->getCode() + : Response::HTTP_FAILED_DEPENDENCY; + $event->setResponse(new Response( $exception->getMessage(), - $exception->getCode() ?? Response::HTTP_FAILED_DEPENDENCY, + $exceptionCode, [ 'X-Content-Type-Options' => 'nosniff', 'X-Frame-Options' => 'deny', diff --git a/composer.json b/composer.json index 4a50c82..262a9c7 100644 --- a/composer.json +++ b/composer.json @@ -27,7 +27,7 @@ "php": ">=8.0", "beberlei/assert": "^3.0", "doctrine/orm": "^2.8", - "doctrine/dbal": "^2.12.1 || ^3.2", + "doctrine/dbal": "^3.2", "doctrine/doctrine-migrations-bundle": "^3.0.3", "graze/guzzle-jsonrpc": "3.2.*", "guzzlehttp/guzzle": "^6.3", diff --git a/phpstan.neon b/phpstan.neon index a85943e..aacb9e6 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -5,3 +5,5 @@ parameters: ignoreErrors: - '#.*unknown class Ivoz\\Provider\\.*#' - '#.*has invalid type Ivoz\\Provider\\.*#' + - '#Unsafe usage of new static\(\)#' + - '#.*has invalid type Doctrine\\DBAL\\Driver\\ResultStatement#' From 2a8a325e2744b3db9d1f938fb6eccdaf27a25975 Mon Sep 17 00:00:00 2001 From: Roger Batista Date: Tue, 15 Mar 2022 09:53:09 +0100 Subject: [PATCH 37/76] Updated json field types --- .../Doctrine/Mapping/Changelog.ChangelogAbstract.orm.xml | 2 +- .../Doctrine/Mapping/Commandlog.CommandlogAbstract.orm.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Infrastructure/Persistence/Doctrine/Mapping/Changelog.ChangelogAbstract.orm.xml b/Infrastructure/Persistence/Doctrine/Mapping/Changelog.ChangelogAbstract.orm.xml index ab6fd45..0407868 100644 --- a/Infrastructure/Persistence/Doctrine/Mapping/Changelog.ChangelogAbstract.orm.xml +++ b/Infrastructure/Persistence/Doctrine/Mapping/Changelog.ChangelogAbstract.orm.xml @@ -12,7 +12,7 @@