From 54af8fc92e17b094db1bc044ac17bf0b2928cfa1 Mon Sep 17 00:00:00 2001 From: Alex Zamponi <562324+alexz707@users.noreply.github.com> Date: Thu, 23 May 2024 17:21:44 +0200 Subject: [PATCH] Add tag create, read and update controllers --- config/tags.yaml | 25 ++++ src/Exception/InvalidParentIdException.php | 31 +++++ .../Request/CreateTagRequestBody.php | 34 ++++++ .../Request/UpdateTagRequestBody.php | 34 ++++++ src/Tag/Controller/CollectionController.php | 89 ++++++++++++++ src/Tag/Controller/CreateController.php | 77 ++++++++++++ src/Tag/Controller/GetController.php | 63 ++++++++++ src/Tag/Controller/UpdateController.php | 71 +++++++++++ src/Tag/Hydrator/TagHydrator.php | 62 ++++++++++ src/Tag/Hydrator/TagHydratorInterface.php | 23 ++++ src/Tag/Repository/TagRepository.php | 114 ++++++++++++++++++ src/Tag/Repository/TagRepositoryInterface.php | 21 ++++ src/Tag/Request/CreateTagParameters.php | 49 ++++++++ src/Tag/Request/TagsParameters.php | 44 +++++++ src/Tag/Request/UpdateTagParameters.php | 49 ++++++++ src/Tag/Schema/Tag.php | 89 ++++++++++++++ src/Tag/Service/TagService.php | 56 +++++++++ src/Tag/Service/TagServiceInterface.php | 18 +++ 18 files changed, 949 insertions(+) create mode 100644 config/tags.yaml create mode 100644 src/Exception/InvalidParentIdException.php create mode 100644 src/Tag/Attributes/Request/CreateTagRequestBody.php create mode 100644 src/Tag/Attributes/Request/UpdateTagRequestBody.php create mode 100644 src/Tag/Controller/CollectionController.php create mode 100644 src/Tag/Controller/CreateController.php create mode 100644 src/Tag/Controller/GetController.php create mode 100644 src/Tag/Controller/UpdateController.php create mode 100644 src/Tag/Hydrator/TagHydrator.php create mode 100644 src/Tag/Hydrator/TagHydratorInterface.php create mode 100644 src/Tag/Repository/TagRepository.php create mode 100644 src/Tag/Repository/TagRepositoryInterface.php create mode 100644 src/Tag/Request/CreateTagParameters.php create mode 100644 src/Tag/Request/TagsParameters.php create mode 100644 src/Tag/Request/UpdateTagParameters.php create mode 100644 src/Tag/Schema/Tag.php create mode 100644 src/Tag/Service/TagService.php create mode 100644 src/Tag/Service/TagServiceInterface.php diff --git a/config/tags.yaml b/config/tags.yaml new file mode 100644 index 000000000..047c57741 --- /dev/null +++ b/config/tags.yaml @@ -0,0 +1,25 @@ +services: + _defaults: + autowire: true + autoconfigure: true + public: false + + # controllers are imported separately to make sure they're public + # and have a tag that allows actions to type-hint services + Pimcore\Bundle\StudioBackendBundle\Tag\Controller\: + resource: '../src/Tag/Controller' + public: true + tags: [ 'controller.service_arguments' ] + + Pimcore\Bundle\StudioBackendBundle\Tag\Repository\TagRepositoryInterface: + class: Pimcore\Bundle\StudioBackendBundle\Tag\Repository\TagRepository + + Pimcore\Bundle\StudioBackendBundle\Tag\Hydrator\TagHydratorInterface: + class: Pimcore\Bundle\StudioBackendBundle\Tag\Hydrator\TagHydrator + + # Services + Pimcore\Bundle\StudioBackendBundle\Tag\Service\TagServiceInterface: + class: Pimcore\Bundle\StudioBackendBundle\Tag\Service\TagService + + + diff --git a/src/Exception/InvalidParentIdException.php b/src/Exception/InvalidParentIdException.php new file mode 100644 index 000000000..e57293437 --- /dev/null +++ b/src/Exception/InvalidParentIdException.php @@ -0,0 +1,31 @@ +name] + )] + #[PageParameter] + #[PageSizeParameter] + #[ElementTypeParameter(false, null)] + #[FilterParameter] + #[ParentIdParameter] + #[SuccessResponse( + description: 'Tags filtered based on type and query parameters', + content: new ItemsJson(Tag::class) + )] + #[BadRequestResponse] + #[UnauthorizedResponse] + #[MethodNotAllowedResponse] + #[UnsupportedMediaTypeResponse] + #[UnprocessableContentResponse] + public function getTags( + #[MapQueryString] TagsParameters $parameters): JsonResponse + { + return $this->jsonResponse(['items' => $this->tagService->listTags($parameters)]); + } +} diff --git a/src/Tag/Controller/CreateController.php b/src/Tag/Controller/CreateController.php new file mode 100644 index 000000000..d129e881d --- /dev/null +++ b/src/Tag/Controller/CreateController.php @@ -0,0 +1,77 @@ +name] + )] + #[CreateTagRequestBody] + #[SuccessResponse( + description: 'Tag data as json', + content: new JsonContent(ref: Tag::class, type: 'object') + )] + #[BadRequestResponse] + #[UnauthorizedResponse] + #[MethodNotAllowedResponse] + #[UnsupportedMediaTypeResponse] + #[UnprocessableContentResponse] + public function createTag(#[MapRequestPayload] CreateTagParameters $parameters): JsonResponse + { + + return $this->jsonResponse($this->tagService->createTag($parameters)); + } +} diff --git a/src/Tag/Controller/GetController.php b/src/Tag/Controller/GetController.php new file mode 100644 index 000000000..e968d71d5 --- /dev/null +++ b/src/Tag/Controller/GetController.php @@ -0,0 +1,63 @@ +name] + )] + #[IdParameter(type: 'tag')] + #[SuccessResponse( + description: 'Tag data as json', + content: new JsonContent(ref: Tag::class) + )] + #[UnauthorizedResponse] + #[NotFoundResponse] + #[MethodNotAllowedResponse] + #[UnsupportedMediaTypeResponse] + #[UnprocessableContentResponse] + public function getTags(int $id): JsonResponse + { + return $this->jsonResponse( + $this->tagService->getTag($id) + + ); + } +} diff --git a/src/Tag/Controller/UpdateController.php b/src/Tag/Controller/UpdateController.php new file mode 100644 index 000000000..491965f18 --- /dev/null +++ b/src/Tag/Controller/UpdateController.php @@ -0,0 +1,71 @@ +name] + )] + #[IdParameter(type: 'tag', schema: new Schema(type: 'integer', example: 10))] + #[UpdateTagRequestBody] + #[SuccessResponse( + description: 'Updated tag data as json', + content: new JsonContent(ref: Tag::class, type: 'object') + )] + #[DefaultResponses([ + HttpResponseCodes::UNAUTHORIZED, + HttpResponseCodes::NOT_FOUND, + ])] + public function updateTag(int $id, #[MapRequestPayload] UpdateTagParameters $parameters): JsonResponse + { + return $this->jsonResponse($this->tagService->updateTag($id, $parameters)); + } +} diff --git a/src/Tag/Hydrator/TagHydrator.php b/src/Tag/Hydrator/TagHydrator.php new file mode 100644 index 000000000..44f0cdac2 --- /dev/null +++ b/src/Tag/Hydrator/TagHydrator.php @@ -0,0 +1,62 @@ +getId(), + parentId: $tag->getParentId(), + text: $tag->getName(), + path: $tag->getNamePath(), + hasChildren: $tag->hasChildren(), + iconName: $this->iconService->getIconForTag() + ); + } + + public function hydrateRecursive(ElementTag $tag): Tag { + $children = []; + foreach ($tag->getChildren() as $child) { + $children[] = $this->hydrateRecursive($child); + } + + $result = $this->hydrate($tag); + $result->setChildren($children); + return $result; + } + + /** + * @param array $tags + * @return array + */ + public function hydrateNestedList(array $tags): array { + $tagMap = []; + $nestedTags = []; + + foreach ($tags as $tag) { + $tagMap[$tag->getId()] = $this->hydrate($tag); + } + + foreach ($tagMap as $tag) { + if ($tag->getParentId() === 0 || !array_key_exists($tag->getParentId(), $tagMap)) { + $nestedTags[] = $tag; + continue; + } + $tagMap[$tag->getParentId()]->addChild($tag); + } + return $nestedTags; + } +} \ No newline at end of file diff --git a/src/Tag/Hydrator/TagHydratorInterface.php b/src/Tag/Hydrator/TagHydratorInterface.php new file mode 100644 index 000000000..684f8e48c --- /dev/null +++ b/src/Tag/Hydrator/TagHydratorInterface.php @@ -0,0 +1,23 @@ + $tags + * @return array + */ + public function hydrateNestedList(array $tags): array; +} \ No newline at end of file diff --git a/src/Tag/Repository/TagRepository.php b/src/Tag/Repository/TagRepository.php new file mode 100644 index 000000000..1788761da --- /dev/null +++ b/src/Tag/Repository/TagRepository.php @@ -0,0 +1,114 @@ +tagResolver->getById($id); + if (!$tag) { + throw new ElementNotFoundException($id); + } + return $tag; + } + + public function listTags(TagsParameters $parameters): TagListing + { + $tagList = new TagListing(); + $tagList->setOrderKey('name'); + + if ($parameters->getParentId() !== null) { + $tagList->setCondition('parentId = ?', $parameters->getParentId()); + } + + if ($parameters->getFilter() === null) { + return $tagList; + } + + $filterTagList = new TagListing(); + $filterTagList->setCondition( + 'LOWER(`name`) LIKE ?', + ['%' . $filterTagList->escapeLike(mb_strtolower($parameters->getFilter())) . '%'] + ); + + $filterIds = [0]; + foreach ($filterTagList->load() as $filterTag) { + $filterIds[] = $filterTag->getId(); + if ($filterTag->getParentId() === 0) { + continue; + } + + $ids = explode('/', $filterTag->getIdPath()); + foreach ($ids as $id) { + if ($id !== '') { + $filterIds[] = (int)$id; + } + } + } + + $filterIds = array_unique(array_values($filterIds)); + $tagList->setConditionVariablesFromSetCondition([]); + $tagList->setCondition('id IN('.implode(',', $filterIds).')'); + + return $tagList; + } + + public function addTag(CreateTagParameters $params): Tag + { + $new = new Tag(); + $new->setParentId($params->getParentId()); + $new->setName($params->getName()); + $new->save(); + return $new; + } + + public function updateTag(int $id, UpdateTagParameters $params): Tag + { + $tag = $this->getTagById($id); + + if ($params->getParentId() !== null) { + $tag->setParentId($params->getParentId()); + } + + if ($params->getName() !== null) { + $tag->setName($params->getName()); + } + $tag->save(); + return $tag; + } +} diff --git a/src/Tag/Repository/TagRepositoryInterface.php b/src/Tag/Repository/TagRepositoryInterface.php new file mode 100644 index 000000000..9744fe955 --- /dev/null +++ b/src/Tag/Repository/TagRepositoryInterface.php @@ -0,0 +1,21 @@ +parentId; + } + + public function getName(): string + { + return $this->name; + } +} diff --git a/src/Tag/Request/TagsParameters.php b/src/Tag/Request/TagsParameters.php new file mode 100644 index 000000000..97822391d --- /dev/null +++ b/src/Tag/Request/TagsParameters.php @@ -0,0 +1,44 @@ +parentId; + } + + public function getFilter(): ?string + { + return $this->filter; + } +} diff --git a/src/Tag/Request/UpdateTagParameters.php b/src/Tag/Request/UpdateTagParameters.php new file mode 100644 index 000000000..ea223be8a --- /dev/null +++ b/src/Tag/Request/UpdateTagParameters.php @@ -0,0 +1,49 @@ +parentId; + } + + public function getName(): ?string + { + return $this->name; + } +} diff --git a/src/Tag/Schema/Tag.php b/src/Tag/Schema/Tag.php new file mode 100644 index 000000000..072b4d5e9 --- /dev/null +++ b/src/Tag/Schema/Tag.php @@ -0,0 +1,89 @@ +id; + } + + public function getParentId(): int + { + return $this->parentId; + } + + public function isHasChildren(): bool + { + return $this->hasChildren; + } + + public function getPath(): string + { + return $this->path; + } + + public function getText(): string + { + return $this->text; + } + + public function getChildren(): array + { + return $this->children; + } + + /** + * @param array $children + */ + public function setChildren(array $children): void + { + $this->children = $children; + } + + public function addChild(Tag $child): void + { + $this->children[] = $child; + } + + public function getIconName(): string + { + return $this->iconName; + } +} diff --git a/src/Tag/Service/TagService.php b/src/Tag/Service/TagService.php new file mode 100644 index 000000000..b9c6c6672 --- /dev/null +++ b/src/Tag/Service/TagService.php @@ -0,0 +1,56 @@ +tagHydrator->hydrateRecursive($this->tagRepository->getTagById($id)); + } + + public function listTags(TagsParameters $parameters): array + { + $tags = $this->tagRepository->listTags($parameters); + return $this->tagHydrator->hydrateNestedList($tags->load()); + } + + public function createTag(CreateTagParameters $tag): Tag + { + if ($tag->getParentId() !== 0) { + try { + $this->tagRepository->getTagById($tag->getParentId()); + } catch (ElementNotFoundException) { + throw new InvalidParentIdException($tag->getParentId()); + } + } + + return $this->tagHydrator->hydrate($this->tagRepository->addTag($tag)); + } + + public function updateTag(int $id, UpdateTagParameters $parameters): Tag + { + $tag = $this->tagRepository->getTagById($id); + + return $this->tagHydrator->hydrate($this->tagRepository->updateTag($id, $parameters)); + } +} \ No newline at end of file diff --git a/src/Tag/Service/TagServiceInterface.php b/src/Tag/Service/TagServiceInterface.php new file mode 100644 index 000000000..740545437 --- /dev/null +++ b/src/Tag/Service/TagServiceInterface.php @@ -0,0 +1,18 @@ +