From 3db92f377bb7b4a83d52cce70c6cb26a19610ba7 Mon Sep 17 00:00:00 2001 From: Dmitry Tsemma Date: Mon, 27 May 2024 13:05:23 +0300 Subject: [PATCH] FRW-7201 Added DELETE method support for Data Exchange API. (#10925) FRW-7201 Added DELETE method support for Data Exchange API. --- .../Transfer/dynamic_entity.transfer.xml | 2 + .../Business/Creator/DynamicEntityCreator.php | 1 - .../Business/Deleter/DynamicEntityDeleter.php | 171 ++++++++++++++++++ .../Deleter/DynamicEntityDeleterInterface.php | 23 +++ .../Business/DynamicEntityBusinessFactory.php | 14 ++ .../Business/DynamicEntityFacade.php | 16 ++ .../Business/DynamicEntityFacadeInterface.php | 15 ++ .../Business/Mapper/DynamicEntityMapper.php | 22 +++ .../Mapper/DynamicEntityMapperInterface.php | 12 ++ .../Business/Reader/DynamicEntityReader.php | 44 ++--- .../Reader/DynamicEntityReaderInterface.php | 18 -- ...ynamicEntityConfigurationTreeValidator.php | 8 +- .../DynamicEntityEntityManager.php | 107 +++++++++++ .../DynamicEntityEntityManagerInterface.php | 12 ++ .../DynamicEntityPersistenceFactory.php | 28 ++- ...atabaseExceptionToErrorMapperInterface.php | 9 +- .../Mapper/ExceptionToErrorMapper.php | 18 +- .../DeleteParentRowExceptionToErrorMapper.php | 108 +++++++++++ .../DuplicateEntryExceptionToErrorMapper.php | 8 +- .../NotNullableExceptionToErrorMapper.php | 10 +- .../DeleteParentRowExceptionToErrorMapper.php | 108 +++++++++++ .../DuplicateKeyExceptionToErrorMapper.php | 8 +- ...NotNullViolationExceptionToErrorMapper.php | 8 +- .../Propel/Mapper/DynamicEntityMapper.php | 9 + .../Business/DynamicEntityFacadeTest.php | 15 +- .../_support/DynamicEntityBusinessTester.php | 3 +- 26 files changed, 714 insertions(+), 83 deletions(-) create mode 100644 src/Spryker/Zed/DynamicEntity/Business/Deleter/DynamicEntityDeleter.php create mode 100644 src/Spryker/Zed/DynamicEntity/Business/Deleter/DynamicEntityDeleterInterface.php create mode 100644 src/Spryker/Zed/DynamicEntity/Persistence/Mapper/MySql/DeleteParentRowExceptionToErrorMapper.php rename src/Spryker/Zed/DynamicEntity/Persistence/Mapper/{Mysql => MySql}/DuplicateEntryExceptionToErrorMapper.php (89%) rename src/Spryker/Zed/DynamicEntity/Persistence/Mapper/{Mysql => MySql}/NotNullableExceptionToErrorMapper.php (85%) create mode 100644 src/Spryker/Zed/DynamicEntity/Persistence/Mapper/PostgreSql/DeleteParentRowExceptionToErrorMapper.php rename src/Spryker/Zed/DynamicEntity/Persistence/Mapper/{Postgresql => PostgreSql}/DuplicateKeyExceptionToErrorMapper.php (88%) rename src/Spryker/Zed/DynamicEntity/Persistence/Mapper/{Postgresql => PostgreSql}/NotNullViolationExceptionToErrorMapper.php (88%) diff --git a/src/Spryker/Shared/DynamicEntity/Transfer/dynamic_entity.transfer.xml b/src/Spryker/Shared/DynamicEntity/Transfer/dynamic_entity.transfer.xml index 0445222..f44247e 100644 --- a/src/Spryker/Shared/DynamicEntity/Transfer/dynamic_entity.transfer.xml +++ b/src/Spryker/Shared/DynamicEntity/Transfer/dynamic_entity.transfer.xml @@ -61,6 +61,7 @@ + @@ -103,6 +104,7 @@ + diff --git a/src/Spryker/Zed/DynamicEntity/Business/Creator/DynamicEntityCreator.php b/src/Spryker/Zed/DynamicEntity/Business/Creator/DynamicEntityCreator.php index 6f4bfbe..d0ea2e5 100644 --- a/src/Spryker/Zed/DynamicEntity/Business/Creator/DynamicEntityCreator.php +++ b/src/Spryker/Zed/DynamicEntity/Business/Creator/DynamicEntityCreator.php @@ -122,7 +122,6 @@ protected function executeDynamicEntityPostCreatePlugins( DynamicEntityConfigurationTransfer $dynamicEntityConfigurationTransfer, DynamicEntityCollectionResponseTransfer $dynamicEntityCollectionResponseTransfer ): DynamicEntityCollectionResponseTransfer { - $dynamicEntityPostEditResponseTransfer = new DynamicEntityPostEditResponseTransfer(); $dynamicEntityPostEditRequestTransfers = $this->dynamicEntityMapper ->mapDynamicEntityCollectionResponseTransferToPostEditRequestTransfersArray( $dynamicEntityConfigurationTransfer, diff --git a/src/Spryker/Zed/DynamicEntity/Business/Deleter/DynamicEntityDeleter.php b/src/Spryker/Zed/DynamicEntity/Business/Deleter/DynamicEntityDeleter.php new file mode 100644 index 0000000..76dedbc --- /dev/null +++ b/src/Spryker/Zed/DynamicEntity/Business/Deleter/DynamicEntityDeleter.php @@ -0,0 +1,171 @@ +entityManager = $entityManager; + $this->dynamicEntityMapper = $dynamicEntityMapper; + $this->dynamicEntityReader = $dynamicEntityReader; + } + + /** + * @param \Generated\Shared\Transfer\DynamicEntityCollectionDeleteCriteriaTransfer $dynamicEntityCollectionDeleteCriteriaTransfer + * + * @return \Generated\Shared\Transfer\DynamicEntityCollectionResponseTransfer + */ + public function deleteEntityCollection( + DynamicEntityCollectionDeleteCriteriaTransfer $dynamicEntityCollectionDeleteCriteriaTransfer + ): DynamicEntityCollectionResponseTransfer { + $dynamicEntityCriteriaTransfer = $this->dynamicEntityMapper->mapDynamicEntityCollectionDeleteCriteriaTransferToDynamicEntityCriteriaTransfer( + $dynamicEntityCollectionDeleteCriteriaTransfer, + new DynamicEntityCriteriaTransfer(), + ); + + $dynamicEntityConfigurationTransfer = $this->getDynamicEntityConfigurationTransfer($dynamicEntityCriteriaTransfer); + + if ($dynamicEntityConfigurationTransfer->getDynamicEntityDefinitionOrFail()->getIsDeletable() !== true) { + return $this->createErrorResponse($dynamicEntityCriteriaTransfer, static::ERROR_MESSAGE_METHOD_NOT_ALLOWED); + } + + $dynamicEntityCollectionTransfer = $this->dynamicEntityReader->getEntityCollection($dynamicEntityCriteriaTransfer); + + if ($dynamicEntityCollectionTransfer->getDynamicEntities()->count() === 0) { + return $this->createErrorResponse($dynamicEntityCriteriaTransfer, static::ERROR_MESSAGE_ENTITY_NOT_EXIST); + } + + if ($dynamicEntityCollectionTransfer->getErrors()->count() !== 0) { + return $this->createDynamicEntityCollectionResponseTransfer($dynamicEntityCollectionTransfer); + } + + return $this->entityManager->deleteDynamicEntity( + $dynamicEntityCollectionTransfer, + $dynamicEntityConfigurationTransfer, + ); + } + + /** + * @param \Generated\Shared\Transfer\DynamicEntityCriteriaTransfer $dynamicEntityCriteriaTransfer + * @param string $errorMessage + * + * @return \Generated\Shared\Transfer\DynamicEntityCollectionResponseTransfer + */ + protected function createErrorResponse( + DynamicEntityCriteriaTransfer $dynamicEntityCriteriaTransfer, + string $errorMessage + ): DynamicEntityCollectionResponseTransfer { + $errorTransfer = (new ErrorTransfer()) + ->setMessage($errorMessage) + ->setParameters([ + static::PLACEHOLDER_ALIAS_NAME => $dynamicEntityCriteriaTransfer->getDynamicEntityConditionsOrFail()->getTableAliasOrFail(), + ]); + + return (new DynamicEntityCollectionResponseTransfer()) + ->addError($errorTransfer); + } + + /** + * @param \Generated\Shared\Transfer\DynamicEntityCollectionTransfer $dynamicEntityCollectionTransfer + * + * @return \Generated\Shared\Transfer\DynamicEntityCollectionResponseTransfer + */ + protected function createDynamicEntityCollectionResponseTransfer( + DynamicEntityCollectionTransfer $dynamicEntityCollectionTransfer + ): DynamicEntityCollectionResponseTransfer { + $dynamicEntityCollectionResponseTransfer = new DynamicEntityCollectionResponseTransfer(); + foreach ($dynamicEntityCollectionTransfer->getErrors() as $errorTransfer) { + $dynamicEntityCollectionResponseTransfer->addError($errorTransfer); + } + + return $dynamicEntityCollectionResponseTransfer; + } + + /** + * @param \Generated\Shared\Transfer\DynamicEntityCriteriaTransfer $dynamicEntityCriteriaTransfer + * + * @return \Generated\Shared\Transfer\DynamicEntityConfigurationTransfer + */ + protected function getDynamicEntityConfigurationTransfer(DynamicEntityCriteriaTransfer $dynamicEntityCriteriaTransfer): DynamicEntityConfigurationTransfer + { + $tableAlias = $dynamicEntityCriteriaTransfer->getDynamicEntityConditionsOrFail()->getTableAliasOrFail(); + $dynamicEntityConfigurationResponse = $this->dynamicEntityReader->getDynamicEntityConfigurationTransferTree((new DynamicEntityCollectionRequestTransfer())->setTableAlias($tableAlias)); + + return $dynamicEntityConfigurationResponse->getDynamicEntityConfigurationTransfer(); + } + + /** + * @param string $tableAlias + * + * @return string + */ + protected function buildErrorPath(string $tableAlias): string + { + return sprintf(static::ERROR_PATH_PLACEHOLDER, $tableAlias, static::ERROR_PATH_INDEX); + } +} diff --git a/src/Spryker/Zed/DynamicEntity/Business/Deleter/DynamicEntityDeleterInterface.php b/src/Spryker/Zed/DynamicEntity/Business/Deleter/DynamicEntityDeleterInterface.php new file mode 100644 index 0000000..d6c217f --- /dev/null +++ b/src/Spryker/Zed/DynamicEntity/Business/Deleter/DynamicEntityDeleterInterface.php @@ -0,0 +1,23 @@ +getEntityManager(), + $this->createDynamicEntityMapper(), + $this->createDynamicEntityReader(), + ); + } + /** * @return \Spryker\Zed\DynamicEntity\Business\Validator\DynamicEntityValidatorInterface */ diff --git a/src/Spryker/Zed/DynamicEntity/Business/DynamicEntityFacade.php b/src/Spryker/Zed/DynamicEntity/Business/DynamicEntityFacade.php index bd8bc32..cbcaa7b 100644 --- a/src/Spryker/Zed/DynamicEntity/Business/DynamicEntityFacade.php +++ b/src/Spryker/Zed/DynamicEntity/Business/DynamicEntityFacade.php @@ -7,6 +7,7 @@ namespace Spryker\Zed\DynamicEntity\Business; +use Generated\Shared\Transfer\DynamicEntityCollectionDeleteCriteriaTransfer; use Generated\Shared\Transfer\DynamicEntityCollectionRequestTransfer; use Generated\Shared\Transfer\DynamicEntityCollectionResponseTransfer; use Generated\Shared\Transfer\DynamicEntityCollectionTransfer; @@ -138,4 +139,19 @@ public function updateDynamicEntityConfigurationCollection( ): DynamicEntityConfigurationCollectionResponseTransfer { return $this->getFactory()->createDynamicEntityConfigurationUpdater()->updateDynamicEntityConfigurationCollection($dynamicEntityConfigurationCollectionTransfer); } + + /** + * {@inheritDoc} + * + * @api + * + * @param \Generated\Shared\Transfer\DynamicEntityCollectionDeleteCriteriaTransfer $dynamicEntityCollectionDeleteCriteriaTransfer + * + * @return \Generated\Shared\Transfer\DynamicEntityCollectionResponseTransfer + */ + public function deleteDynamicEntityCollection( + DynamicEntityCollectionDeleteCriteriaTransfer $dynamicEntityCollectionDeleteCriteriaTransfer + ): DynamicEntityCollectionResponseTransfer { + return $this->getFactory()->createDynamicEntityDeleter()->deleteEntityCollection($dynamicEntityCollectionDeleteCriteriaTransfer); + } } diff --git a/src/Spryker/Zed/DynamicEntity/Business/DynamicEntityFacadeInterface.php b/src/Spryker/Zed/DynamicEntity/Business/DynamicEntityFacadeInterface.php index 04a5e4b..4e25533 100644 --- a/src/Spryker/Zed/DynamicEntity/Business/DynamicEntityFacadeInterface.php +++ b/src/Spryker/Zed/DynamicEntity/Business/DynamicEntityFacadeInterface.php @@ -7,6 +7,7 @@ namespace Spryker\Zed\DynamicEntity\Business; +use Generated\Shared\Transfer\DynamicEntityCollectionDeleteCriteriaTransfer; use Generated\Shared\Transfer\DynamicEntityCollectionRequestTransfer; use Generated\Shared\Transfer\DynamicEntityCollectionResponseTransfer; use Generated\Shared\Transfer\DynamicEntityCollectionTransfer; @@ -129,4 +130,18 @@ public function createDynamicEntityConfigurationCollection( public function updateDynamicEntityConfigurationCollection( DynamicEntityConfigurationCollectionRequestTransfer $dynamicEntityConfigurationCollectionTransfer ): DynamicEntityConfigurationCollectionResponseTransfer; + + /** + * Specification: + * - Deletes a collection of entities based on the provided criteria. + * + * @api + * + * @param \Generated\Shared\Transfer\DynamicEntityCollectionDeleteCriteriaTransfer $dynamicEntityCollectionDeleteCriteriaTransfer + * + * @return \Generated\Shared\Transfer\DynamicEntityCollectionResponseTransfer + */ + public function deleteDynamicEntityCollection( + DynamicEntityCollectionDeleteCriteriaTransfer $dynamicEntityCollectionDeleteCriteriaTransfer + ): DynamicEntityCollectionResponseTransfer; } diff --git a/src/Spryker/Zed/DynamicEntity/Business/Mapper/DynamicEntityMapper.php b/src/Spryker/Zed/DynamicEntity/Business/Mapper/DynamicEntityMapper.php index 48b3750..14097b6 100644 --- a/src/Spryker/Zed/DynamicEntity/Business/Mapper/DynamicEntityMapper.php +++ b/src/Spryker/Zed/DynamicEntity/Business/Mapper/DynamicEntityMapper.php @@ -7,6 +7,7 @@ namespace Spryker\Zed\DynamicEntity\Business\Mapper; +use Generated\Shared\Transfer\DynamicEntityCollectionDeleteCriteriaTransfer; use Generated\Shared\Transfer\DynamicEntityCollectionRequestTransfer; use Generated\Shared\Transfer\DynamicEntityCollectionResponseTransfer; use Generated\Shared\Transfer\DynamicEntityCollectionTransfer; @@ -36,6 +37,11 @@ class DynamicEntityMapper implements DynamicEntityMapperInterface */ protected const IDENTIFIER = 'identifier'; + /** + * @var string + */ + protected const IS_DELETABLE = 'isDeletable'; + /** * @var string */ @@ -101,6 +107,9 @@ protected function mapDynamicEntityDefinitionToDynamicEntityDefinitionTransfer( } $dynamicEntityDefinitionTransfer->setIdentifier($definition[static::IDENTIFIER]); + if (array_key_exists(static::IS_DELETABLE, $definition)) { + $dynamicEntityDefinitionTransfer->setIsDeletable($definition[static::IS_DELETABLE]); + } foreach ($definition[static::FIELDS] as $field) { $dynamicEntityFieldDefinitionTransfer = (new DynamicEntityFieldDefinitionTransfer())->fromArray($field, true); @@ -367,6 +376,19 @@ public function mapDynamicEntityTransferToDynamicEntityConditionsTransfer( return $dynamicEntityConditionsTransfer; } + /** + * @param \Generated\Shared\Transfer\DynamicEntityCollectionDeleteCriteriaTransfer $dynamicEntityCollectionDeleteCriteriaTransfer + * @param \Generated\Shared\Transfer\DynamicEntityCriteriaTransfer $dynamicEntityCriteriaTransfer + * + * @return \Generated\Shared\Transfer\DynamicEntityCriteriaTransfer + */ + public function mapDynamicEntityCollectionDeleteCriteriaTransferToDynamicEntityCriteriaTransfer( + DynamicEntityCollectionDeleteCriteriaTransfer $dynamicEntityCollectionDeleteCriteriaTransfer, + DynamicEntityCriteriaTransfer $dynamicEntityCriteriaTransfer + ): DynamicEntityCriteriaTransfer { + return $dynamicEntityCriteriaTransfer->fromArray($dynamicEntityCollectionDeleteCriteriaTransfer->toArray(true, true), true); + } + /** * @param \Generated\Shared\Transfer\DynamicEntityConfigurationTransfer $dynamicEntityConfigurationTransfer * diff --git a/src/Spryker/Zed/DynamicEntity/Business/Mapper/DynamicEntityMapperInterface.php b/src/Spryker/Zed/DynamicEntity/Business/Mapper/DynamicEntityMapperInterface.php index 7d10856..62e3b47 100644 --- a/src/Spryker/Zed/DynamicEntity/Business/Mapper/DynamicEntityMapperInterface.php +++ b/src/Spryker/Zed/DynamicEntity/Business/Mapper/DynamicEntityMapperInterface.php @@ -7,6 +7,7 @@ namespace Spryker\Zed\DynamicEntity\Business\Mapper; +use Generated\Shared\Transfer\DynamicEntityCollectionDeleteCriteriaTransfer; use Generated\Shared\Transfer\DynamicEntityCollectionRequestTransfer; use Generated\Shared\Transfer\DynamicEntityCollectionResponseTransfer; use Generated\Shared\Transfer\DynamicEntityCollectionTransfer; @@ -109,4 +110,15 @@ public function mapDynamicEntityTransferToDynamicEntityConditionsTransfer( DynamicEntityTransfer $dynamicEntityTransfer, DynamicEntityConfigurationTransfer $dynamicEntityConfigurationTransfer ): ?DynamicEntityConditionsTransfer; + + /** + * @param \Generated\Shared\Transfer\DynamicEntityCollectionDeleteCriteriaTransfer $dynamicEntityCollectionDeleteCriteriaTransfer + * @param \Generated\Shared\Transfer\DynamicEntityCriteriaTransfer $dynamicEntityCriteriaTransfer + * + * @return \Generated\Shared\Transfer\DynamicEntityCriteriaTransfer + */ + public function mapDynamicEntityCollectionDeleteCriteriaTransferToDynamicEntityCriteriaTransfer( + DynamicEntityCollectionDeleteCriteriaTransfer $dynamicEntityCollectionDeleteCriteriaTransfer, + DynamicEntityCriteriaTransfer $dynamicEntityCriteriaTransfer + ): DynamicEntityCriteriaTransfer; } diff --git a/src/Spryker/Zed/DynamicEntity/Business/Reader/DynamicEntityReader.php b/src/Spryker/Zed/DynamicEntity/Business/Reader/DynamicEntityReader.php index 08a1e71..515abe2 100644 --- a/src/Spryker/Zed/DynamicEntity/Business/Reader/DynamicEntityReader.php +++ b/src/Spryker/Zed/DynamicEntity/Business/Reader/DynamicEntityReader.php @@ -110,31 +110,6 @@ public function getEntityCollection(DynamicEntityCriteriaTransfer $dynamicEntity return $this->getEntityCollectionByConfiguration($dynamicEntityCriteriaTransfer, $dynamicEntityConfigurationTransfer); } - /** - * @param \Generated\Shared\Transfer\DynamicEntityCollectionRequestTransfer $dynamicEntityCollectionRequestTransfer - * - * @return \Generated\Shared\Transfer\DynamicEntityConfigurationCollectionTransfer - */ - public function getDynamicEntityConfigurationCollection( - DynamicEntityCollectionRequestTransfer $dynamicEntityCollectionRequestTransfer - ): DynamicEntityConfigurationCollectionTransfer { - $dynamicEntityCriteriaTransfer = $this->dynamicEntityMapper->mapDynamicEntityCollectionRequestTransferToDynamicEntityCriteriaTransfer($dynamicEntityCollectionRequestTransfer); - - return $this->repository->getDynamicEntityConfigurationByDynamicEntityCriteria( - $dynamicEntityCriteriaTransfer, - ); - } - - /** - * @param string $tableAlias - * - * @return \Generated\Shared\Transfer\DynamicEntityConfigurationTransfer|null - */ - public function findDynamicEntityConfigurationByTableAlias(string $tableAlias): ?DynamicEntityConfigurationTransfer - { - return $this->repository->findDynamicEntityConfigurationByTableAlias($tableAlias); - } - /** * @param \Generated\Shared\Transfer\DynamicEntityCollectionRequestTransfer $dynamicEntityCollectionRequestTransfer * @@ -145,7 +120,9 @@ public function findDynamicEntityConfigurationByTableAlias(string $tableAlias): public function getDynamicEntityConfigurationTransferTree( DynamicEntityCollectionRequestTransfer $dynamicEntityCollectionRequestTransfer ): DynamicEntityConfigurationResponseInterface { - $dynamicEntityConfigurationCollectionTransfer = $this->getDynamicEntityConfigurationCollection($dynamicEntityCollectionRequestTransfer); + $dynamicEntityCriteriaTransfer = $this->dynamicEntityMapper->mapDynamicEntityCollectionRequestTransferToDynamicEntityCriteriaTransfer($dynamicEntityCollectionRequestTransfer); + + $dynamicEntityConfigurationCollectionTransfer = $this->getDynamicEntityConfigurationCollection($dynamicEntityCriteriaTransfer); $errorTransfer = $this->dynamicEntityConfigurationTreeValidator ->validateDynamicEntityCollectionRequestByDynamicEntityConfigurationCollection( @@ -158,8 +135,6 @@ public function getDynamicEntityConfigurationTransferTree( return $dynamicEntityConfigurationResponse->addErrorTransfer($errorTransfer); } - $dynamicEntityCriteriaTransfer = $this->dynamicEntityMapper->mapDynamicEntityCollectionRequestTransferToDynamicEntityCriteriaTransfer($dynamicEntityCollectionRequestTransfer); - $dynamicEntityConfigurationTransfer = $this->dynamicEntityRelationTreeBuilder->buildDynamicEntityConfigurationTransferTree( $dynamicEntityCriteriaTransfer, $dynamicEntityConfigurationCollectionTransfer, @@ -174,6 +149,19 @@ public function getDynamicEntityConfigurationTransferTree( return $dynamicEntityConfigurationResponse; } + /** + * @param \Generated\Shared\Transfer\DynamicEntityCriteriaTransfer $dynamicEntityCriteriaTransfer + * + * @return \Generated\Shared\Transfer\DynamicEntityConfigurationCollectionTransfer + */ + protected function getDynamicEntityConfigurationCollection( + DynamicEntityCriteriaTransfer $dynamicEntityCriteriaTransfer + ): DynamicEntityConfigurationCollectionTransfer { + return $this->repository->getDynamicEntityConfigurationByDynamicEntityCriteria( + $dynamicEntityCriteriaTransfer, + ); + } + /** * @param \Generated\Shared\Transfer\DynamicEntityCriteriaTransfer $dynamicEntityCriteriaTransfer * @param \Generated\Shared\Transfer\DynamicEntityConfigurationTransfer $dynamicEntityConfigurationTransfer diff --git a/src/Spryker/Zed/DynamicEntity/Business/Reader/DynamicEntityReaderInterface.php b/src/Spryker/Zed/DynamicEntity/Business/Reader/DynamicEntityReaderInterface.php index 1edd7f8..1f2b9d8 100644 --- a/src/Spryker/Zed/DynamicEntity/Business/Reader/DynamicEntityReaderInterface.php +++ b/src/Spryker/Zed/DynamicEntity/Business/Reader/DynamicEntityReaderInterface.php @@ -9,8 +9,6 @@ use Generated\Shared\Transfer\DynamicEntityCollectionRequestTransfer; use Generated\Shared\Transfer\DynamicEntityCollectionTransfer; -use Generated\Shared\Transfer\DynamicEntityConfigurationCollectionTransfer; -use Generated\Shared\Transfer\DynamicEntityConfigurationTransfer; use Generated\Shared\Transfer\DynamicEntityCriteriaTransfer; use Spryker\Zed\DynamicEntity\Business\Configuration\DynamicEntityConfigurationResponseInterface; @@ -23,22 +21,6 @@ interface DynamicEntityReaderInterface */ public function getEntityCollection(DynamicEntityCriteriaTransfer $dynamicEntityCriteriaTransfer): DynamicEntityCollectionTransfer; - /** - * @param \Generated\Shared\Transfer\DynamicEntityCollectionRequestTransfer $dynamicEntityCollectionRequestTransfer - * - * @return \Generated\Shared\Transfer\DynamicEntityConfigurationCollectionTransfer - */ - public function getDynamicEntityConfigurationCollection( - DynamicEntityCollectionRequestTransfer $dynamicEntityCollectionRequestTransfer - ): DynamicEntityConfigurationCollectionTransfer; - - /** - * @param string $tableAlias - * - * @return \Generated\Shared\Transfer\DynamicEntityConfigurationTransfer|null - */ - public function findDynamicEntityConfigurationByTableAlias(string $tableAlias): ?DynamicEntityConfigurationTransfer; - /** * @param \Generated\Shared\Transfer\DynamicEntityCollectionRequestTransfer $dynamicEntityCollectionRequestTransfer * diff --git a/src/Spryker/Zed/DynamicEntity/Business/Validator/DynamicEntityConfigurationTreeValidator.php b/src/Spryker/Zed/DynamicEntity/Business/Validator/DynamicEntityConfigurationTreeValidator.php index d7e4534..7859488 100644 --- a/src/Spryker/Zed/DynamicEntity/Business/Validator/DynamicEntityConfigurationTreeValidator.php +++ b/src/Spryker/Zed/DynamicEntity/Business/Validator/DynamicEntityConfigurationTreeValidator.php @@ -85,12 +85,12 @@ public function validateDynamicEntityConfigurationCollection( ); } - $rootDynamicEntityConfigurationTranfer = $this->getDynamicEntityConfigurationEntityByTableAlias( + $rootDynamicEntityConfigurationTransfer = $this->getDynamicEntityConfigurationEntityByTableAlias( $dynamicEntityConfigurationCollectionTransfer, $tableAlias, ); - if ($rootDynamicEntityConfigurationTranfer === null) { + if ($rootDynamicEntityConfigurationTransfer === null) { return $this->createErrorTransfer( static::ERROR_MESSAGE_CONFIGURATION_NOT_FOUND, [ @@ -101,7 +101,7 @@ public function validateDynamicEntityConfigurationCollection( $filterFieldValidationError = $this->validateFilterField( $dynamicEntityCriteriaTransfer, - $rootDynamicEntityConfigurationTranfer, + $rootDynamicEntityConfigurationTransfer, ); if ($filterFieldValidationError !== null) { @@ -111,7 +111,7 @@ public function validateDynamicEntityConfigurationCollection( return $this->validateRelationChainsSequence( $dynamicEntityConfigurationCollectionTransfer, $dynamicEntityCriteriaTransfer, - $rootDynamicEntityConfigurationTranfer, + $rootDynamicEntityConfigurationTransfer, ); } diff --git a/src/Spryker/Zed/DynamicEntity/Persistence/DynamicEntityEntityManager.php b/src/Spryker/Zed/DynamicEntity/Persistence/DynamicEntityEntityManager.php index b035071..f284fe8 100644 --- a/src/Spryker/Zed/DynamicEntity/Persistence/DynamicEntityEntityManager.php +++ b/src/Spryker/Zed/DynamicEntity/Persistence/DynamicEntityEntityManager.php @@ -10,6 +10,7 @@ use Exception; use Generated\Shared\Transfer\DynamicEntityCollectionRequestTransfer; use Generated\Shared\Transfer\DynamicEntityCollectionResponseTransfer; +use Generated\Shared\Transfer\DynamicEntityCollectionTransfer; use Generated\Shared\Transfer\DynamicEntityConditionsTransfer; use Generated\Shared\Transfer\DynamicEntityConfigurationCollectionTransfer; use Generated\Shared\Transfer\DynamicEntityConfigurationRelationTransfer; @@ -28,6 +29,7 @@ use Spryker\Zed\DynamicEntity\DynamicEntityConfig; use Spryker\Zed\Kernel\Persistence\AbstractEntityManager; use Spryker\Zed\Kernel\Persistence\EntityManager\TransactionTrait; +use Spryker\Zed\PropelOrm\Business\Runtime\ActiveQuery\Criteria; /** * @method \Spryker\Zed\DynamicEntity\Persistence\DynamicEntityPersistenceFactory getFactory() @@ -61,6 +63,16 @@ class DynamicEntityEntityManager extends AbstractEntityManager implements Dynami */ protected const KEY_RELATION_FIELD_MAPPINGS = 'relation_field_mappings'; + /** + * @var string + */ + protected const IDENTIFIER_INFO_PLACEHOLDER = '%s.%s = %s'; + + /** + * @var string + */ + protected const PREFIX_GETTER_METHOD = 'get'; + /** * @param \Generated\Shared\Transfer\DynamicEntityConfigurationTransfer $dynamicEntityConfigurationTransfer * @@ -334,6 +346,47 @@ public function createDynamicEntityConfigurationRelation( return $childDynamicEntityConfigurationCollectionTransfer; } + /** + * @param \Generated\Shared\Transfer\DynamicEntityCollectionTransfer $dynamicEntityCollectionTransfer + * @param \Generated\Shared\Transfer\DynamicEntityConfigurationTransfer $dynamicEntityConfigurationTransfer + * + * @return \Generated\Shared\Transfer\DynamicEntityCollectionResponseTransfer + */ + public function deleteDynamicEntity( + DynamicEntityCollectionTransfer $dynamicEntityCollectionTransfer, + DynamicEntityConfigurationTransfer $dynamicEntityConfigurationTransfer + ): DynamicEntityCollectionResponseTransfer { + $dynamicEntityCollectionResponseTransfer = new DynamicEntityCollectionResponseTransfer(); + $dynamicEntityQueryClassName = $this->getFactory()->createDynamicEntityQueryBuilder() + ->assertEntityQueryClassNameExists($dynamicEntityConfigurationTransfer->getTableNameOrFail()); + + $dynamicEntityIdentifiers = []; + foreach ($dynamicEntityCollectionTransfer->getDynamicEntities() as $dynamicEntityTransfer) { + $dynamicEntityIdentifiers[] = $dynamicEntityTransfer->getIdentifierOrFail(); + } + /** @var \Propel\Runtime\ActiveQuery\ModelCriteria $dynamicEntityQuery */ + $dynamicEntityQuery = new $dynamicEntityQueryClassName(); + $identifier = $this->convertSnakeCaseToCamelCase($dynamicEntityConfigurationTransfer->getDynamicEntityDefinitionOrFail()->getIdentifierOrFail()); + $objectCollection = $dynamicEntityQuery->filterBy($identifier, $dynamicEntityIdentifiers, Criteria::IN)->find(); + + foreach ($objectCollection as $object) { + try { + $object->delete(); + } catch (Exception $exception) { + $getterMethodName = static::PREFIX_GETTER_METHOD . ucfirst($identifier); + + return $this->handleDeleteException( + $dynamicEntityCollectionResponseTransfer, + $dynamicEntityConfigurationTransfer, + $this->generateIdentifierInfo($dynamicEntityConfigurationTransfer, $object->{$getterMethodName}()), + $exception, + ); + } + } + + return $dynamicEntityCollectionResponseTransfer; + } + /** * @param \Generated\Shared\Transfer\DynamicEntityRelationFieldMappingTransfer $relationFieldMappingTransfer * @@ -605,6 +658,32 @@ protected function handleSaveException( throw $exception; } + /** + * @param \Generated\Shared\Transfer\DynamicEntityCollectionResponseTransfer $dynamicEntityCollectionResponseTransfer + * @param \Generated\Shared\Transfer\DynamicEntityConfigurationTransfer $dynamicEntityConfigurationTransfer + * @param string $errorPath + * @param \Exception $exception + * + * @throws \Exception + * + * @return \Generated\Shared\Transfer\DynamicEntityCollectionResponseTransfer + */ + protected function handleDeleteException( + DynamicEntityCollectionResponseTransfer $dynamicEntityCollectionResponseTransfer, + DynamicEntityConfigurationTransfer $dynamicEntityConfigurationTransfer, + string $errorPath, + Exception $exception + ): DynamicEntityCollectionResponseTransfer { + $errorMessageTransfer = $this->getFactory()->createExceptionToErrorMapper() + ->map($exception, $dynamicEntityConfigurationTransfer, $errorPath); + + if ($errorMessageTransfer !== null) { + return $dynamicEntityCollectionResponseTransfer->addError($errorMessageTransfer); + } + + throw $exception; + } + /** * @param \Generated\Shared\Transfer\DynamicEntityCollectionResponseTransfer $dynamicEntityCollectionResponseTransfer * @param string $errorMessage @@ -657,4 +736,32 @@ protected function addIdentifierIsNotCreatableError( ], ); } + + /** + * @param string $input + * + * @return string + */ + protected function convertSnakeCaseToCamelCase(string $input): string + { + return str_replace('_', '', ucwords($input, '_')); + } + + /** + * @param \Generated\Shared\Transfer\DynamicEntityConfigurationTransfer $dynamicEntityConfigurationTransfer + * @param string $identifier + * + * @return string + */ + protected function generateIdentifierInfo( + DynamicEntityConfigurationTransfer $dynamicEntityConfigurationTransfer, + string $identifier + ): string { + return sprintf( + static::IDENTIFIER_INFO_PLACEHOLDER, + $dynamicEntityConfigurationTransfer->getTableAliasOrFail(), + $this->getIdentifierVisibleName($dynamicEntityConfigurationTransfer), + $identifier, + ); + } } diff --git a/src/Spryker/Zed/DynamicEntity/Persistence/DynamicEntityEntityManagerInterface.php b/src/Spryker/Zed/DynamicEntity/Persistence/DynamicEntityEntityManagerInterface.php index 4d33e94..2cb9787 100644 --- a/src/Spryker/Zed/DynamicEntity/Persistence/DynamicEntityEntityManagerInterface.php +++ b/src/Spryker/Zed/DynamicEntity/Persistence/DynamicEntityEntityManagerInterface.php @@ -9,6 +9,7 @@ use Generated\Shared\Transfer\DynamicEntityCollectionRequestTransfer; use Generated\Shared\Transfer\DynamicEntityCollectionResponseTransfer; +use Generated\Shared\Transfer\DynamicEntityCollectionTransfer; use Generated\Shared\Transfer\DynamicEntityConditionsTransfer; use Generated\Shared\Transfer\DynamicEntityConfigurationCollectionTransfer; use Generated\Shared\Transfer\DynamicEntityConfigurationRelationTransfer; @@ -107,4 +108,15 @@ public function createDynamicEntityConfigurationRelation( DynamicEntityConfigurationTransfer $parentDynamicEntityConfigurationTransfer, array $indexedChildRelations ): DynamicEntityConfigurationCollectionTransfer; + + /** + * @param \Generated\Shared\Transfer\DynamicEntityCollectionTransfer $dynamicEntityCollectionTransfer + * @param \Generated\Shared\Transfer\DynamicEntityConfigurationTransfer $dynamicEntityConfigurationTransfer + * + * @return \Generated\Shared\Transfer\DynamicEntityCollectionResponseTransfer + */ + public function deleteDynamicEntity( + DynamicEntityCollectionTransfer $dynamicEntityCollectionTransfer, + DynamicEntityConfigurationTransfer $dynamicEntityConfigurationTransfer + ): DynamicEntityCollectionResponseTransfer; } diff --git a/src/Spryker/Zed/DynamicEntity/Persistence/DynamicEntityPersistenceFactory.php b/src/Spryker/Zed/DynamicEntity/Persistence/DynamicEntityPersistenceFactory.php index c86dabd..05a7feb 100644 --- a/src/Spryker/Zed/DynamicEntity/Persistence/DynamicEntityPersistenceFactory.php +++ b/src/Spryker/Zed/DynamicEntity/Persistence/DynamicEntityPersistenceFactory.php @@ -20,10 +20,12 @@ use Spryker\Zed\DynamicEntity\Persistence\Mapper\DatabaseExceptionToErrorMapperInterface; use Spryker\Zed\DynamicEntity\Persistence\Mapper\ExceptionToErrorMapper; use Spryker\Zed\DynamicEntity\Persistence\Mapper\ExceptionToErrorMapperInterface; -use Spryker\Zed\DynamicEntity\Persistence\Mapper\Mysql\DuplicateEntryExceptionToErrorMapper; -use Spryker\Zed\DynamicEntity\Persistence\Mapper\Mysql\NotNullableExceptionToErrorMapper; -use Spryker\Zed\DynamicEntity\Persistence\Mapper\Postgresql\DuplicateKeyExceptionToErrorMapper; -use Spryker\Zed\DynamicEntity\Persistence\Mapper\Postgresql\NotNullViolationExceptionToErrorMapper; +use Spryker\Zed\DynamicEntity\Persistence\Mapper\MySql\DeleteParentRowExceptionToErrorMapper as MySqlDeleteParentRowExceptionToErrorMapper; +use Spryker\Zed\DynamicEntity\Persistence\Mapper\MySql\DuplicateEntryExceptionToErrorMapper; +use Spryker\Zed\DynamicEntity\Persistence\Mapper\MySql\NotNullableExceptionToErrorMapper; +use Spryker\Zed\DynamicEntity\Persistence\Mapper\PostgreSql\DeleteParentRowExceptionToErrorMapper as PostgreSqlDeleteParentRowExceptionToErrorMapper; +use Spryker\Zed\DynamicEntity\Persistence\Mapper\PostgreSql\DuplicateKeyExceptionToErrorMapper; +use Spryker\Zed\DynamicEntity\Persistence\Mapper\PostgreSql\NotNullViolationExceptionToErrorMapper; use Spryker\Zed\DynamicEntity\Persistence\Propel\Mapper\DynamicEntityMapper; use Spryker\Zed\DynamicEntity\Persistence\Resetter\DynamicEntityResetter; use Spryker\Zed\DynamicEntity\Persistence\Resetter\DynamicEntityResetterInterface; @@ -90,9 +92,11 @@ public function getDatabaseExceptionToErrorMappers(): array //MySQL $this->createDuplicateEntryExceptionToErrorMapper(), $this->createNotNullableExceptionToErrorMapper(), + $this->createMySqlDeleteParentRowExceptionToErrorMapper(), //PostgreSQL $this->createDuplicateKeyExceptionToErrorMapper(), $this->createNotNullViolationExceptionToErrorMapper(), + $this->createPostgreSqlDeleteParentRowExceptionToErrorMapper(), ]; } @@ -128,6 +132,22 @@ public function createNotNullViolationExceptionToErrorMapper(): DatabaseExceptio return new NotNullViolationExceptionToErrorMapper(); } + /** + * @return \Spryker\Zed\DynamicEntity\Persistence\Mapper\DatabaseExceptionToErrorMapperInterface + */ + public function createMySqlDeleteParentRowExceptionToErrorMapper(): DatabaseExceptionToErrorMapperInterface + { + return new MySqlDeleteParentRowExceptionToErrorMapper(); + } + + /** + * @return \Spryker\Zed\DynamicEntity\Persistence\Mapper\DatabaseExceptionToErrorMapperInterface + */ + public function createPostgreSqlDeleteParentRowExceptionToErrorMapper(): DatabaseExceptionToErrorMapperInterface + { + return new PostgreSqlDeleteParentRowExceptionToErrorMapper(); + } + /** * @return \Spryker\Zed\DynamicEntity\Persistence\Resetter\DynamicEntityResetterInterface */ diff --git a/src/Spryker/Zed/DynamicEntity/Persistence/Mapper/DatabaseExceptionToErrorMapperInterface.php b/src/Spryker/Zed/DynamicEntity/Persistence/Mapper/DatabaseExceptionToErrorMapperInterface.php index cf0ee18..2a73bc0 100644 --- a/src/Spryker/Zed/DynamicEntity/Persistence/Mapper/DatabaseExceptionToErrorMapperInterface.php +++ b/src/Spryker/Zed/DynamicEntity/Persistence/Mapper/DatabaseExceptionToErrorMapperInterface.php @@ -11,6 +11,11 @@ interface DatabaseExceptionToErrorMapperInterface { + /** + * @var string + */ + public const ERROR_PATH = 'errorPath'; + /** * @param \Exception $exception * @@ -24,11 +29,11 @@ public function isApplicable(Exception $exception): bool; public function getErrorGlossaryKey(): string; /** - * @param string $errorPath + * @param array $params * * @return array */ - public function getErrorGlossaryParams(string $errorPath): array; + public function getErrorGlossaryParams(array $params): array; /** * @param \Exception $exception diff --git a/src/Spryker/Zed/DynamicEntity/Persistence/Mapper/ExceptionToErrorMapper.php b/src/Spryker/Zed/DynamicEntity/Persistence/Mapper/ExceptionToErrorMapper.php index ee3b3e2..140da4e 100644 --- a/src/Spryker/Zed/DynamicEntity/Persistence/Mapper/ExceptionToErrorMapper.php +++ b/src/Spryker/Zed/DynamicEntity/Persistence/Mapper/ExceptionToErrorMapper.php @@ -23,6 +23,16 @@ class ExceptionToErrorMapper implements ExceptionToErrorMapperInterface */ protected const RELATION_CHAIN_PLACEHOLDER = '%s.%s'; + /** + * @var string + */ + protected const EXCEPTION = 'exception'; + + /** + * @var string + */ + protected const ERROR_PATH = 'errorPath'; + /** * @param array<\Spryker\Zed\DynamicEntity\Persistence\Mapper\DatabaseExceptionToErrorMapperInterface> $databaseExceptionToErrorMappers */ @@ -53,7 +63,13 @@ public function map( $databaseExceptionToErrorMapper->mapExceptionToErrorMessage($exception), ); $errorKey = $databaseExceptionToErrorMapper->getErrorGlossaryKey(); - $errorDetails = $databaseExceptionToErrorMapper->getErrorGlossaryParams($errorPath); + + $errorDetails = $databaseExceptionToErrorMapper->getErrorGlossaryParams( + [ + static::ERROR_PATH => $errorPath, + static::EXCEPTION => $exception, + ], + ); return (new ErrorTransfer()) ->setEntityIdentifier($dynamicEntityConfigurationTransfer->getTableAliasOrFail()) diff --git a/src/Spryker/Zed/DynamicEntity/Persistence/Mapper/MySql/DeleteParentRowExceptionToErrorMapper.php b/src/Spryker/Zed/DynamicEntity/Persistence/Mapper/MySql/DeleteParentRowExceptionToErrorMapper.php new file mode 100644 index 0000000..2d36c44 --- /dev/null +++ b/src/Spryker/Zed/DynamicEntity/Persistence/Mapper/MySql/DeleteParentRowExceptionToErrorMapper.php @@ -0,0 +1,108 @@ +getPrevious(); + if ($previousException === null) { + return false; + } + + $code = (string)$previousException->getCode(); + $errorMatches = (bool)strpos($previousException->getMessage(), static::FOREIGN_KEY_CONSTRAINT_FAILS) === true; + + return $code === static::ERROR_CODE_INTEGRITY_CONSTRAINT && $errorMatches === true; + } + + /** + * @return string + */ + public function getErrorGlossaryKey(): string + { + return static::GLOSSARY_KEY_ERROR_DELETE_FOREIGN_KEY_CONSTRAINT_FAILS; + } + + /** + * @param array $params + * + * @return array + */ + public function getErrorGlossaryParams(array $params): array + { + return [ + DynamicEntityConfig::ERROR_PATH => $params[static::ERROR_PATH], + static::CHILD_ENTITY_PATTERN => $this->getChildEntity($params), + ]; + } + + /** + * @param \Exception $exception + * + * @return string|null + */ + public function mapExceptionToErrorMessage(Exception $exception): ?string + { + return null; + } + + /** + * @param array $params + * + * @return string + */ + protected function getChildEntity(array $params): string + { + $exception = $params[static::EXCEPTION]; + $previousExceptionMessage = ($exception->getPrevious())->getMessage(); + preg_match(static::REGEX, $previousExceptionMessage, $matches); + + return $matches[2]; + } +} diff --git a/src/Spryker/Zed/DynamicEntity/Persistence/Mapper/Mysql/DuplicateEntryExceptionToErrorMapper.php b/src/Spryker/Zed/DynamicEntity/Persistence/Mapper/MySql/DuplicateEntryExceptionToErrorMapper.php similarity index 89% rename from src/Spryker/Zed/DynamicEntity/Persistence/Mapper/Mysql/DuplicateEntryExceptionToErrorMapper.php rename to src/Spryker/Zed/DynamicEntity/Persistence/Mapper/MySql/DuplicateEntryExceptionToErrorMapper.php index fc39f06..67199aa 100644 --- a/src/Spryker/Zed/DynamicEntity/Persistence/Mapper/Mysql/DuplicateEntryExceptionToErrorMapper.php +++ b/src/Spryker/Zed/DynamicEntity/Persistence/Mapper/MySql/DuplicateEntryExceptionToErrorMapper.php @@ -5,7 +5,7 @@ * Use of this software requires acceptance of the Evaluation License Agreement. See LICENSE file. */ -namespace Spryker\Zed\DynamicEntity\Persistence\Mapper\Mysql; +namespace Spryker\Zed\DynamicEntity\Persistence\Mapper\MySql; use Exception; use Spryker\Zed\DynamicEntity\DynamicEntityConfig; @@ -55,14 +55,14 @@ public function getErrorGlossaryKey(): string } /** - * @param string $errorPath + * @param array $params * * @return array */ - public function getErrorGlossaryParams(string $errorPath): array + public function getErrorGlossaryParams(array $params): array { return [ - DynamicEntityConfig::ERROR_PATH => $errorPath, + DynamicEntityConfig::ERROR_PATH => $params[static::ERROR_PATH], ]; } diff --git a/src/Spryker/Zed/DynamicEntity/Persistence/Mapper/Mysql/NotNullableExceptionToErrorMapper.php b/src/Spryker/Zed/DynamicEntity/Persistence/Mapper/MySql/NotNullableExceptionToErrorMapper.php similarity index 85% rename from src/Spryker/Zed/DynamicEntity/Persistence/Mapper/Mysql/NotNullableExceptionToErrorMapper.php rename to src/Spryker/Zed/DynamicEntity/Persistence/Mapper/MySql/NotNullableExceptionToErrorMapper.php index f18d0b0..1054ba5 100644 --- a/src/Spryker/Zed/DynamicEntity/Persistence/Mapper/Mysql/NotNullableExceptionToErrorMapper.php +++ b/src/Spryker/Zed/DynamicEntity/Persistence/Mapper/MySql/NotNullableExceptionToErrorMapper.php @@ -5,7 +5,7 @@ * Use of this software requires acceptance of the Evaluation License Agreement. See LICENSE file. */ -namespace Spryker\Zed\DynamicEntity\Persistence\Mapper\Mysql; +namespace Spryker\Zed\DynamicEntity\Persistence\Mapper\MySql; use Exception; use Spryker\Zed\DynamicEntity\DynamicEntityConfig; @@ -43,7 +43,7 @@ public function isApplicable(Exception $exception): bool $code = (string)$previousException->getCode(); $errorMatches = (bool)preg_match(static::NOT_NULL_ENTRY_REGEX, $previousException->getMessage(), $matches); - return ($code === static::ERROR_CODE_INTEGRITY_CONSTRAINT && $errorMatches !== null); + return $code === static::ERROR_CODE_INTEGRITY_CONSTRAINT && $errorMatches === true; } /** @@ -55,14 +55,14 @@ public function getErrorGlossaryKey(): string } /** - * @param string $errorPath + * @param array $params * * @return array */ - public function getErrorGlossaryParams(string $errorPath): array + public function getErrorGlossaryParams(array $params): array { return [ - DynamicEntityConfig::ERROR_PATH => $errorPath, + DynamicEntityConfig::ERROR_PATH => $params[static::ERROR_PATH], ]; } diff --git a/src/Spryker/Zed/DynamicEntity/Persistence/Mapper/PostgreSql/DeleteParentRowExceptionToErrorMapper.php b/src/Spryker/Zed/DynamicEntity/Persistence/Mapper/PostgreSql/DeleteParentRowExceptionToErrorMapper.php new file mode 100644 index 0000000..c8a36b7 --- /dev/null +++ b/src/Spryker/Zed/DynamicEntity/Persistence/Mapper/PostgreSql/DeleteParentRowExceptionToErrorMapper.php @@ -0,0 +1,108 @@ +getPrevious(); + if ($previousException === null) { + return false; + } + + $code = (string)$previousException->getCode(); + $errorMatches = (bool)strpos($previousException->getMessage(), static::FOREIGN_KEY_CONSTRAINT_FAILS) === true; + + return $code === static::ERROR_CODE_INTEGRITY_CONSTRAINT && $errorMatches === true; + } + + /** + * @return string + */ + public function getErrorGlossaryKey(): string + { + return static::GLOSSARY_KEY_ERROR_DELETE_FOREIGN_KEY_CONSTRAINT_FAILS; + } + + /** + * @param array $params + * + * @return array + */ + public function getErrorGlossaryParams(array $params): array + { + return [ + DynamicEntityConfig::ERROR_PATH => $params[static::ERROR_PATH], + static::CHILD_ENTITY_PATTERN => $this->getChildEntity($params), + ]; + } + + /** + * @param \Exception $exception + * + * @return string|null + */ + public function mapExceptionToErrorMessage(Exception $exception): ?string + { + return null; + } + + /** + * @param array $params + * + * @return string + */ + protected function getChildEntity(array $params): string + { + $exception = $params[static::EXCEPTION]; + $previousExceptionMessage = ($exception->getPrevious())->getMessage(); + preg_match(static::REFERENCE_TABLE_REGEX, $previousExceptionMessage, $matches); + + return $matches[1]; + } +} diff --git a/src/Spryker/Zed/DynamicEntity/Persistence/Mapper/Postgresql/DuplicateKeyExceptionToErrorMapper.php b/src/Spryker/Zed/DynamicEntity/Persistence/Mapper/PostgreSql/DuplicateKeyExceptionToErrorMapper.php similarity index 88% rename from src/Spryker/Zed/DynamicEntity/Persistence/Mapper/Postgresql/DuplicateKeyExceptionToErrorMapper.php rename to src/Spryker/Zed/DynamicEntity/Persistence/Mapper/PostgreSql/DuplicateKeyExceptionToErrorMapper.php index 612d215..e7fa61e 100644 --- a/src/Spryker/Zed/DynamicEntity/Persistence/Mapper/Postgresql/DuplicateKeyExceptionToErrorMapper.php +++ b/src/Spryker/Zed/DynamicEntity/Persistence/Mapper/PostgreSql/DuplicateKeyExceptionToErrorMapper.php @@ -5,7 +5,7 @@ * Use of this software requires acceptance of the Evaluation License Agreement. See LICENSE file. */ -namespace Spryker\Zed\DynamicEntity\Persistence\Mapper\Postgresql; +namespace Spryker\Zed\DynamicEntity\Persistence\Mapper\PostgreSql; use Exception; use Spryker\Zed\DynamicEntity\DynamicEntityConfig; @@ -53,14 +53,14 @@ public function getErrorGlossaryKey(): string } /** - * @param string $errorPath + * @param array $params * * @return array */ - public function getErrorGlossaryParams(string $errorPath): array + public function getErrorGlossaryParams(array $params): array { return [ - DynamicEntityConfig::ERROR_PATH => $errorPath, + DynamicEntityConfig::ERROR_PATH => $params[static::ERROR_PATH], ]; } diff --git a/src/Spryker/Zed/DynamicEntity/Persistence/Mapper/Postgresql/NotNullViolationExceptionToErrorMapper.php b/src/Spryker/Zed/DynamicEntity/Persistence/Mapper/PostgreSql/NotNullViolationExceptionToErrorMapper.php similarity index 88% rename from src/Spryker/Zed/DynamicEntity/Persistence/Mapper/Postgresql/NotNullViolationExceptionToErrorMapper.php rename to src/Spryker/Zed/DynamicEntity/Persistence/Mapper/PostgreSql/NotNullViolationExceptionToErrorMapper.php index 7b71985..b73c8e5 100644 --- a/src/Spryker/Zed/DynamicEntity/Persistence/Mapper/Postgresql/NotNullViolationExceptionToErrorMapper.php +++ b/src/Spryker/Zed/DynamicEntity/Persistence/Mapper/PostgreSql/NotNullViolationExceptionToErrorMapper.php @@ -5,7 +5,7 @@ * Use of this software requires acceptance of the Evaluation License Agreement. See LICENSE file. */ -namespace Spryker\Zed\DynamicEntity\Persistence\Mapper\Postgresql; +namespace Spryker\Zed\DynamicEntity\Persistence\Mapper\PostgreSql; use Exception; use Spryker\Zed\DynamicEntity\DynamicEntityConfig; @@ -53,14 +53,14 @@ public function getErrorGlossaryKey(): string } /** - * @param string $errorPath + * @param array $params * * @return array */ - public function getErrorGlossaryParams(string $errorPath): array + public function getErrorGlossaryParams(array $params): array { return [ - DynamicEntityConfig::ERROR_PATH => $errorPath, + DynamicEntityConfig::ERROR_PATH => $params[static::ERROR_PATH], ]; } diff --git a/src/Spryker/Zed/DynamicEntity/Persistence/Propel/Mapper/DynamicEntityMapper.php b/src/Spryker/Zed/DynamicEntity/Persistence/Propel/Mapper/DynamicEntityMapper.php index de46548..19011a0 100644 --- a/src/Spryker/Zed/DynamicEntity/Persistence/Propel/Mapper/DynamicEntityMapper.php +++ b/src/Spryker/Zed/DynamicEntity/Persistence/Propel/Mapper/DynamicEntityMapper.php @@ -39,6 +39,11 @@ class DynamicEntityMapper */ protected const IDENTIFIER = 'identifier'; + /** + * @var string + */ + protected const IS_DELETABLE = 'isDeletable'; + /** * @var string */ @@ -106,6 +111,7 @@ public function mapDynamicEntityConfigurationTransferToEntity( $modifiedDefinitions = $dynamicEntityDefinitionTransfer->modifiedToArray(true, true); $definitionForEntity = [ static::IDENTIFIER => $definitions[static::IDENTIFIER], + static::IS_DELETABLE => $definitions[static::IS_DELETABLE], static::FIELDS => $modifiedDefinitions[static::FIELD_DEFINITIONS] ?? [], ]; @@ -328,6 +334,9 @@ protected function mapDynamicEntityDefinitionToDynamicEntityDefinitionTransfer( } $dynamicEntityDefinitionTransfer->setIdentifier($config[static::IDENTIFIER]); + if (array_key_exists(static::IS_DELETABLE, $config)) { + $dynamicEntityDefinitionTransfer->setIsDeletable($config[static::IS_DELETABLE]); + } foreach ($config[static::FIELDS] as $field) { $dynamicEntityFieldDefinitionTransfer = (new DynamicEntityFieldDefinitionTransfer())->fromArray($field, true); diff --git a/tests/SprykerTest/Zed/DynamicEntity/Business/DynamicEntityFacadeTest.php b/tests/SprykerTest/Zed/DynamicEntity/Business/DynamicEntityFacadeTest.php index 0e25a5c..f0544eb 100644 --- a/tests/SprykerTest/Zed/DynamicEntity/Business/DynamicEntityFacadeTest.php +++ b/tests/SprykerTest/Zed/DynamicEntity/Business/DynamicEntityFacadeTest.php @@ -143,10 +143,10 @@ public function testGetDynamicEntityCollectionReturnsNotEmptyCollection(): void $dynamicEntityCollectionTransfer = $this->dynamicEntityFacade->getDynamicEntityCollection($dynamicEntityCriteriaTransfer); //Assert - $totalEntitesCount = SpyDynamicEntityConfigurationQuery::create()->find()->count(); - $this->assertCount($totalEntitesCount, $dynamicEntityCollectionTransfer->getDynamicEntities()); - $this->assertEquals($this->tester::FOO_TABLE_ALIAS_1, $dynamicEntityCollectionTransfer->getDynamicEntities()[$totalEntitesCount - 1]->getFields()[$this->tester::TABLE_ALIAS_FIELD_NAME]); - $this->assertNotContains('dynamicEntityDefinition', $dynamicEntityCollectionTransfer->getDynamicEntities()[$totalEntitesCount - 1]->getFields()); + $totalEntitiesCount = SpyDynamicEntityConfigurationQuery::create()->find()->count(); + $this->assertCount($totalEntitiesCount, $dynamicEntityCollectionTransfer->getDynamicEntities()); + $this->assertEquals($this->tester::FOO_TABLE_ALIAS_1, $dynamicEntityCollectionTransfer->getDynamicEntities()[$totalEntitiesCount - 1]->getFields()[$this->tester::TABLE_ALIAS_FIELD_NAME]); + $this->assertNotContains('dynamicEntityDefinition', $dynamicEntityCollectionTransfer->getDynamicEntities()[$totalEntitiesCount - 1]->getFields()); } /** @@ -184,9 +184,10 @@ public function testGetDynamicEntityCollectionReturnsFilteredCollectionByMultipl //Assert $this->assertCount(2, $dynamicEntityCollectionTransfer->getDynamicEntities()); - $this->assertEquals($this->tester::BAR_TABLE_ALIAS, $dynamicEntityCollectionTransfer->getDynamicEntities()[0]->getFields()[$this->tester::TABLE_ALIAS_FIELD_NAME]); - $this->assertEquals($this->tester::FOO_TABLE_ALIAS_1, $dynamicEntityCollectionTransfer->getDynamicEntities()[1]->getFields()[$this->tester::TABLE_ALIAS_FIELD_NAME]); - $this->assertNotContains('dynamicEntityDefinition', $dynamicEntityCollectionTransfer->getDynamicEntities()[0]->getFields()); + foreach ($dynamicEntityCollectionTransfer->getDynamicEntities() as $dynamicEntityTransfer) { + $this->assertContains($dynamicEntityTransfer->getFields()[$this->tester::TABLE_ALIAS_FIELD_NAME], [$this->tester::FOO_TABLE_ALIAS_1, $this->tester::BAR_TABLE_ALIAS]); + $this->assertNotContains('dynamicEntityDefinition', $dynamicEntityTransfer->getFields()); + } } /** diff --git a/tests/SprykerTest/Zed/DynamicEntity/_support/DynamicEntityBusinessTester.php b/tests/SprykerTest/Zed/DynamicEntity/_support/DynamicEntityBusinessTester.php index df1f8a5..ad1d43d 100644 --- a/tests/SprykerTest/Zed/DynamicEntity/_support/DynamicEntityBusinessTester.php +++ b/tests/SprykerTest/Zed/DynamicEntity/_support/DynamicEntityBusinessTester.php @@ -167,6 +167,7 @@ public function createDynamicEntityConfigurationTransfer( $dynamicEntityDefinitionTransfer = (new DynamicEntityDefinitionTransfer()) ->setIdentifier('id_test_table') + ->setIsDeletable(true) ->addFieldDefinition($idDynamicEntityFieldDefinitionTransfer) ->addFieldDefinition($stringDynamicEntityFieldDefinitionTransfer) ->addFieldDefinition($intDynamicEntityFieldDefinitionTransfer) @@ -349,7 +350,7 @@ public function createDefinitionArray(): array public function getExpectedDefinition(): string { return <<<'EOT' -{"identifier":"id_test_table","fields":[{"fieldName":"id_test_table","fieldVisibleName":"id","type":"integer","isCreatable":false,"isEditable":false,"validation":{"isRequired":false}},{"fieldName":"string_field","fieldVisibleName":"string_field","type":"string","isCreatable":true,"isEditable":true,"validation":{"isRequired":true,"minLength":1,"maxLength":255}},{"fieldName":"int_field","fieldVisibleName":"int_field","type":"integer","isCreatable":true,"isEditable":true,"validation":{"isRequired":true,"min":100,"max":255}},{"fieldName":"bool_field","fieldVisibleName":"bool_field","type":"boolean","isCreatable":true,"isEditable":true,"validation":{"isRequired":true}},{"fieldName":"decimal_field","fieldVisibleName":"decimal_field","type":"decimal","isCreatable":true,"isEditable":true,"validation":{"isRequired":true,"scale":2,"precision":10}}]} +{"identifier":"id_test_table","isDeletable":true,"fields":[{"fieldName":"id_test_table","fieldVisibleName":"id","type":"integer","isCreatable":false,"isEditable":false,"validation":{"isRequired":false}},{"fieldName":"string_field","fieldVisibleName":"string_field","type":"string","isCreatable":true,"isEditable":true,"validation":{"isRequired":true,"minLength":1,"maxLength":255}},{"fieldName":"int_field","fieldVisibleName":"int_field","type":"integer","isCreatable":true,"isEditable":true,"validation":{"isRequired":true,"min":100,"max":255}},{"fieldName":"bool_field","fieldVisibleName":"bool_field","type":"boolean","isCreatable":true,"isEditable":true,"validation":{"isRequired":true}},{"fieldName":"decimal_field","fieldVisibleName":"decimal_field","type":"decimal","isCreatable":true,"isEditable":true,"validation":{"isRequired":true,"scale":2,"precision":10}}]} EOT; }