From 6fc01076e29460a882e1c580afc7279e798c0523 Mon Sep 17 00:00:00 2001 From: Alexey Skobkin Date: Sun, 15 Jan 2017 05:54:38 +0300 Subject: [PATCH] fix #30. Factories and API clients refactored to DTO. Some other changes. --- .../Command/UpdateSubscriptionsCommand.php | 2 +- .../Controller/Api/CrawlerController.php | 2 +- .../Bundle/PointToolsBundle/DTO/Api/Auth.php | 42 +-- .../PointToolsBundle/DTO/Api/Comment.php | 126 +++++++ .../DTO/Api/Crawler/MetaPost.php | 37 --- .../PointToolsBundle/DTO/Api/Crawler/Post.php | 187 ----------- .../DTO/Api/Crawler/PostsPage.php | 44 --- .../PointToolsBundle/DTO/Api/Crawler/User.php | 70 ---- .../PointToolsBundle/DTO/Api/MetaPost.php | 52 +++ .../Bundle/PointToolsBundle/DTO/Api/Post.php | 157 +++++++++ .../PointToolsBundle/DTO/Api/PostsPage.php | 51 +++ .../Bundle/PointToolsBundle/DTO/Api/User.php | 226 +++++++++++++ .../DTO/Api/ValidableInterface.php | 7 + .../Exception/Api/ApiException.php | 8 + .../Exception/Api/ForbiddenException.php | 8 + .../Api}/InvalidResponseException.php | 3 +- .../Exception/Api/NetworkException.php | 8 + .../Exception/Api/NotFoundException.php | 8 + .../Exception/Api/ServerProblemException.php | 8 + .../Exception/Api/UnauthorizedException.php | 8 + .../Api}/UserNotFoundException.php | 3 +- .../Factory/Blog/InvalidPostDataException.php | 5 +- .../Factory/InvalidUserDataException.php | 25 ++ .../SubscriptionManagerException.php | 3 +- .../config/serializer/DTO.Api.Auth.yml | 11 + .../config/serializer/DTO.Api.Comment.yml | 23 ++ .../config/serializer/DTO.Api.MetaPost.yml | 10 + .../config/serializer/DTO.Api.Post.yml | 25 ++ .../config/serializer/DTO.Api.PostPage.yml | 7 + .../config/serializer/DTO.Api.User.yml | 49 +++ .../Resources/config/services.yml | 46 +-- .../PointToolsBundle/Service/AbstractApi.php | 120 ------- .../Service/Api/AbstractApi.php | 176 ++++++++++ .../Service/{ => Api}/PostApi.php | 7 +- .../PointToolsBundle/Service/Api/UserApi.php | 183 +++++++++++ .../Service/Exceptions/ApiException.php | 9 - .../Factory/InvalidUserDataException.php | 27 -- .../Service/Factory/AbstractFactory.php | 19 ++ .../Service/Factory/Blogs/CommentFactory.php | 83 +---- .../Service/Factory/Blogs/FileFactory.php | 16 +- .../Service/Factory/Blogs/PostFactory.php | 21 +- .../Service/Factory/Blogs/TagFactory.php | 10 +- .../Factory/Telegram/AccountFactory.php | 7 +- .../Service/Factory/UserFactory.php | 80 ++--- .../Telegram/PrivateMessageProcessor.php | 4 +- .../PointToolsBundle/Service/UserApi.php | 311 ------------------ 46 files changed, 1297 insertions(+), 1037 deletions(-) create mode 100644 src/Skobkin/Bundle/PointToolsBundle/DTO/Api/Comment.php delete mode 100644 src/Skobkin/Bundle/PointToolsBundle/DTO/Api/Crawler/MetaPost.php delete mode 100644 src/Skobkin/Bundle/PointToolsBundle/DTO/Api/Crawler/Post.php delete mode 100644 src/Skobkin/Bundle/PointToolsBundle/DTO/Api/Crawler/PostsPage.php delete mode 100644 src/Skobkin/Bundle/PointToolsBundle/DTO/Api/Crawler/User.php create mode 100644 src/Skobkin/Bundle/PointToolsBundle/DTO/Api/MetaPost.php create mode 100644 src/Skobkin/Bundle/PointToolsBundle/DTO/Api/Post.php create mode 100644 src/Skobkin/Bundle/PointToolsBundle/DTO/Api/PostsPage.php create mode 100644 src/Skobkin/Bundle/PointToolsBundle/DTO/Api/User.php create mode 100644 src/Skobkin/Bundle/PointToolsBundle/DTO/Api/ValidableInterface.php create mode 100644 src/Skobkin/Bundle/PointToolsBundle/Exception/Api/ApiException.php create mode 100644 src/Skobkin/Bundle/PointToolsBundle/Exception/Api/ForbiddenException.php rename src/Skobkin/Bundle/PointToolsBundle/{Service/Exceptions => Exception/Api}/InvalidResponseException.php (50%) create mode 100644 src/Skobkin/Bundle/PointToolsBundle/Exception/Api/NetworkException.php create mode 100644 src/Skobkin/Bundle/PointToolsBundle/Exception/Api/NotFoundException.php create mode 100644 src/Skobkin/Bundle/PointToolsBundle/Exception/Api/ServerProblemException.php create mode 100644 src/Skobkin/Bundle/PointToolsBundle/Exception/Api/UnauthorizedException.php rename src/Skobkin/Bundle/PointToolsBundle/{Service/Exceptions => Exception/Api}/UserNotFoundException.php (91%) create mode 100644 src/Skobkin/Bundle/PointToolsBundle/Exception/Factory/InvalidUserDataException.php rename src/Skobkin/Bundle/PointToolsBundle/{Service/Exceptions => Exception}/SubscriptionManagerException.php (51%) create mode 100644 src/Skobkin/Bundle/PointToolsBundle/Resources/config/serializer/DTO.Api.Auth.yml create mode 100644 src/Skobkin/Bundle/PointToolsBundle/Resources/config/serializer/DTO.Api.Comment.yml create mode 100644 src/Skobkin/Bundle/PointToolsBundle/Resources/config/serializer/DTO.Api.MetaPost.yml create mode 100644 src/Skobkin/Bundle/PointToolsBundle/Resources/config/serializer/DTO.Api.Post.yml create mode 100644 src/Skobkin/Bundle/PointToolsBundle/Resources/config/serializer/DTO.Api.PostPage.yml create mode 100644 src/Skobkin/Bundle/PointToolsBundle/Resources/config/serializer/DTO.Api.User.yml delete mode 100644 src/Skobkin/Bundle/PointToolsBundle/Service/AbstractApi.php create mode 100644 src/Skobkin/Bundle/PointToolsBundle/Service/Api/AbstractApi.php rename src/Skobkin/Bundle/PointToolsBundle/Service/{ => Api}/PostApi.php (55%) create mode 100644 src/Skobkin/Bundle/PointToolsBundle/Service/Api/UserApi.php delete mode 100644 src/Skobkin/Bundle/PointToolsBundle/Service/Exceptions/ApiException.php delete mode 100644 src/Skobkin/Bundle/PointToolsBundle/Service/Exceptions/Factory/InvalidUserDataException.php create mode 100644 src/Skobkin/Bundle/PointToolsBundle/Service/Factory/AbstractFactory.php delete mode 100644 src/Skobkin/Bundle/PointToolsBundle/Service/UserApi.php diff --git a/src/Skobkin/Bundle/PointToolsBundle/Command/UpdateSubscriptionsCommand.php b/src/Skobkin/Bundle/PointToolsBundle/Command/UpdateSubscriptionsCommand.php index 746a1c3..001ca97 100644 --- a/src/Skobkin/Bundle/PointToolsBundle/Command/UpdateSubscriptionsCommand.php +++ b/src/Skobkin/Bundle/PointToolsBundle/Command/UpdateSubscriptionsCommand.php @@ -8,7 +8,7 @@ use Skobkin\Bundle\PointToolsBundle\Entity\Subscription; use Skobkin\Bundle\PointToolsBundle\Entity\User; use Skobkin\Bundle\PointToolsBundle\Repository\UserRepository; use Skobkin\Bundle\PointToolsBundle\Service\SubscriptionsManager; -use Skobkin\Bundle\PointToolsBundle\Service\UserApi; +use Skobkin\Bundle\PointToolsBundle\Service\Api\UserApi; use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; use Symfony\Component\Console\Helper\ProgressBar; use Symfony\Component\Console\Input\InputInterface; diff --git a/src/Skobkin/Bundle/PointToolsBundle/Controller/Api/CrawlerController.php b/src/Skobkin/Bundle/PointToolsBundle/Controller/Api/CrawlerController.php index 277aabc..93b2711 100644 --- a/src/Skobkin/Bundle/PointToolsBundle/Controller/Api/CrawlerController.php +++ b/src/Skobkin/Bundle/PointToolsBundle/Controller/Api/CrawlerController.php @@ -21,7 +21,7 @@ class CrawlerController extends AbstractApiController $serializer = $this->get('jms_serializer'); - $page = $serializer->deserialize($json, 'Skobkin\Bundle\PointToolsBundle\DTO\Api\Crawler\PostsPage', 'json'); + $page = $serializer->deserialize($json, 'Skobkin\Bundle\PointToolsBundle\DTO\Api\PostsPage', 'json'); /** @var PostFactory $factory */ $factory = $this->get('app.point.post_factory'); diff --git a/src/Skobkin/Bundle/PointToolsBundle/DTO/Api/Auth.php b/src/Skobkin/Bundle/PointToolsBundle/DTO/Api/Auth.php index e43a83e..8d7eba1 100644 --- a/src/Skobkin/Bundle/PointToolsBundle/DTO/Api/Auth.php +++ b/src/Skobkin/Bundle/PointToolsBundle/DTO/Api/Auth.php @@ -2,35 +2,20 @@ namespace Skobkin\Bundle\PointToolsBundle\DTO\Api; -use JMS\Serializer\Annotation as JMSS; - -/** - * @JMSS\ExclusionPolicy("none") - * @JMSS\AccessType("public_method") - */ -class Auth +class Auth implements ValidableInterface { /** - * @var string - * - * @JMSS\SerializedName("token") - * @JMSS\Type("string") + * @var string|null */ private $token; /** - * @var string - * - * @JMSS\SerializedName("csrf_token") - * @JMSS\Type("string") + * @var string|null */ private $csRfToken; /** - * @var string - * - * @JMSS\SerializedName("error") - * @JMSS\Type("string") + * @var string|null */ private $error; @@ -40,11 +25,9 @@ class Auth return $this->token; } - public function setToken(?string $token): self + public function setToken(?string $token): void { $this->token = $token; - - return $this; } public function getCsRfToken(): ?string @@ -52,11 +35,9 @@ class Auth return $this->csRfToken; } - public function setCsRfToken(?string $csRfToken): self + public function setCsRfToken(?string $csRfToken): void { $this->csRfToken = $csRfToken; - - return $this; } public function getError(): ?string @@ -64,10 +45,17 @@ class Auth return $this->error; } - public function setError(?string $error): self + public function setError(?string $error): void { $this->error = $error; + } - return $this; + public function isValid(): bool + { + if (null !== $this->token && null !== $this->csRfToken && null === $this->error) { + return true; + } + + return false; } } \ No newline at end of file diff --git a/src/Skobkin/Bundle/PointToolsBundle/DTO/Api/Comment.php b/src/Skobkin/Bundle/PointToolsBundle/DTO/Api/Comment.php new file mode 100644 index 0000000..26916f3 --- /dev/null +++ b/src/Skobkin/Bundle/PointToolsBundle/DTO/Api/Comment.php @@ -0,0 +1,126 @@ +postId; + } + + public function setPostId(?string $postId): void + { + $this->postId = $postId; + } + + public function getNumber(): ?int + { + return $this->number; + } + + public function setNumber(?int $number): void + { + $this->number = $number; + } + + public function getToCommentId(): ?int + { + return $this->toCommentId; + } + + public function setToCommentId(?int $toCommentId): void + { + $this->toCommentId = $toCommentId; + } + + public function getCreated(): string + { + return $this->created; + } + + public function setCreated(?string $created): void + { + $this->created = $created; + } + + public function getText(): ?string + { + return $this->text; + } + + public function setText(?string $text): void + { + $this->text = $text; + } + + public function getAuthor(): ?User + { + return $this->author; + } + + public function setAuthor(?User $author): void + { + $this->author = $author; + } + + public function isIsRec(): ?bool + { + return $this->isRec; + } + + public function getIsRec(): ?bool + { + return $this->isRec; + } + + public function setIsRec(?bool $isRec): void + { + $this->isRec = $isRec; + } + + public function isValid(): bool + { + if (null !== $this->postId && null !== $this->number && null !== $this->author && null !== $this->text) { + return true; + } + + return false; + } +} \ No newline at end of file diff --git a/src/Skobkin/Bundle/PointToolsBundle/DTO/Api/Crawler/MetaPost.php b/src/Skobkin/Bundle/PointToolsBundle/DTO/Api/Crawler/MetaPost.php deleted file mode 100644 index fd266e1..0000000 --- a/src/Skobkin/Bundle/PointToolsBundle/DTO/Api/Crawler/MetaPost.php +++ /dev/null @@ -1,37 +0,0 @@ -post; - } - - public function setPost(Post $post): self - { - $this->post = $post; - - return $this; - } -} \ No newline at end of file diff --git a/src/Skobkin/Bundle/PointToolsBundle/DTO/Api/Crawler/Post.php b/src/Skobkin/Bundle/PointToolsBundle/DTO/Api/Crawler/Post.php deleted file mode 100644 index 2f2a832..0000000 --- a/src/Skobkin/Bundle/PointToolsBundle/DTO/Api/Crawler/Post.php +++ /dev/null @@ -1,187 +0,0 @@ -") - */ - private $tags; - - /** - * @var string[] - * - * @JMSS\SerializedName("files") - * @JMSS\Type("array") - */ - private $files; - - /** - * @var User - * - * @JMSS\SerializedName("author") - * @JMSS\Type("Skobkin\Bundle\PointToolsBundle\DTO\Api\Crawler\User") - * @JMSS\MaxDepth(1) - */ - private $author; - - /** - * @var string - * - * @JMSS\SerializedName("text") - * @JMSS\Type("string") - */ - private $text; - - /** - * @var string - * - * @JMSS\SerializedName("created") - * @JMSS\Type("string") - */ - private $created; - - /** - * @var string - * - * @JMSS\SerializedName("type") - * @JMSS\Type("string") - */ - private $type; - - /** - * @var bool - * - * @JMSS\SerializedName("private") - * @JMSS\Type("boolean") - */ - private $private; - - - public function getId(): ?string - { - return $this->id; - } - - public function setId(?string $id): self - { - $this->id = $id; - - return $this; - } - - /** - * @return string[] - */ - public function getTags(): ?array - { - return $this->tags; - } - - public function setTags(?array $tags): self - { - $this->tags = $tags; - return $this; - } - - /** - * @return string[] - */ - public function getFiles(): ?array - { - return $this->files; - } - - /** - * @param string[] $files - * - * @return Post - */ - public function setFiles(?array $files): self - { - $this->files = $files; - - return $this; - } - - public function getAuthor(): ?User - { - return $this->author; - } - - public function setAuthor(?User $author): self - { - $this->author = $author; - return $this; - } - - public function getText(): ?string - { - return $this->text; - } - - public function setText(?string $text): self - { - $this->text = $text; - - return $this; - } - - public function getCreated(): ?string - { - return $this->created; - } - - public function setCreated(?string $created): self - { - $this->created = $created; - - return $this; - } - - public function getType(): ?string - { - return $this->type; - } - - public function setType(?string $type): self - { - $this->type = $type; - - return $this; - } - - public function getPrivate(): ?bool - { - return $this->private; - } - - public function isPrivate(): ?bool - { - return $this->private; - } - - public function setPrivate(?bool $private): self - { - $this->private = $private; - return $this; - } -} \ No newline at end of file diff --git a/src/Skobkin/Bundle/PointToolsBundle/DTO/Api/Crawler/PostsPage.php b/src/Skobkin/Bundle/PointToolsBundle/DTO/Api/Crawler/PostsPage.php deleted file mode 100644 index 1e18b0a..0000000 --- a/src/Skobkin/Bundle/PointToolsBundle/DTO/Api/Crawler/PostsPage.php +++ /dev/null @@ -1,44 +0,0 @@ -") - * @JMSS\MaxDepth(3) - */ - private $posts; - - /** - * @return MetaPost[] - */ - public function getPosts(): ?array - { - return $this->posts; - } - - /** - * @todo move to constructor - * - * @param MetaPost[] $posts - * @return PostsPage - */ - public function setPosts(?array $posts): self - { - $this->posts = $posts; - - return $this; - } - - -} \ No newline at end of file diff --git a/src/Skobkin/Bundle/PointToolsBundle/DTO/Api/Crawler/User.php b/src/Skobkin/Bundle/PointToolsBundle/DTO/Api/Crawler/User.php deleted file mode 100644 index 829e4f1..0000000 --- a/src/Skobkin/Bundle/PointToolsBundle/DTO/Api/Crawler/User.php +++ /dev/null @@ -1,70 +0,0 @@ -id; - } - - public function setId(?string $id): self - { - $this->id = $id; - return $this; - } - - public function getLogin(): ?string - { - return $this->login; - } - - public function setLogin(?string $login): self - { - $this->login = $login; - return $this; - } - - public function getName(): ?string - { - return $this->name; - } - - public function setName(?string $name): self - { - $this->name = $name; - return $this; - } -} \ No newline at end of file diff --git a/src/Skobkin/Bundle/PointToolsBundle/DTO/Api/MetaPost.php b/src/Skobkin/Bundle/PointToolsBundle/DTO/Api/MetaPost.php new file mode 100644 index 0000000..cb2f26a --- /dev/null +++ b/src/Skobkin/Bundle/PointToolsBundle/DTO/Api/MetaPost.php @@ -0,0 +1,52 @@ +post; + } + + public function setPost(?Post $post): void + { + $this->post = $post; + } + + /** + * @return Comment[]|null + */ + public function getComments(): ?array + { + return $this->comments; + } + + /** + * @param Comment[]|null $comments + */ + public function setComments(?array $comments): void + { + $this->comments = $comments; + } + + public function isValid(): bool + { + if (null !== $this->post && $this->post->isValid()) { + return true; + } + + return false; + } +} \ No newline at end of file diff --git a/src/Skobkin/Bundle/PointToolsBundle/DTO/Api/Post.php b/src/Skobkin/Bundle/PointToolsBundle/DTO/Api/Post.php new file mode 100644 index 0000000..76bc035 --- /dev/null +++ b/src/Skobkin/Bundle/PointToolsBundle/DTO/Api/Post.php @@ -0,0 +1,157 @@ +id; + } + + public function setId(?string $id): void + { + $this->id = $id; + } + + /** + * @return string[]|null + */ + public function getTags(): ?array + { + return $this->tags; + } + + public function setTags(?array $tags): void + { + $this->tags = $tags; + } + + /** + * @return string[]|null + */ + public function getFiles(): ?array + { + return $this->files; + } + + /** + * @param string[]|null $files + */ + public function setFiles(?array $files): void + { + $this->files = $files; + } + + public function getAuthor(): ?User + { + return $this->author; + } + + public function setAuthor(?User $author): void + { + $this->author = $author; + } + + public function getText(): ?string + { + return $this->text; + } + + public function setText(?string $text): void + { + $this->text = $text; + } + + public function getCreated(): ?string + { + return $this->created; + } + + public function setCreated(?string $created): void + { + $this->created = $created; + } + + public function getType(): ?string + { + return $this->type; + } + + public function setType(?string $type): void + { + $this->type = $type; + } + + public function getPrivate(): ?bool + { + return $this->private; + } + + public function isPrivate(): ?bool + { + return $this->private; + } + + public function setPrivate(?bool $private): void + { + $this->private = $private; + } + + public function isValid(): bool + { + if ( + null !== $this->id && + null !== $this->author && + $this->author->isValid() && + null !== $this->text && + null !== $this->created && + null !== $this->type + ) { + return true; + } + + return false; + } +} \ No newline at end of file diff --git a/src/Skobkin/Bundle/PointToolsBundle/DTO/Api/PostsPage.php b/src/Skobkin/Bundle/PointToolsBundle/DTO/Api/PostsPage.php new file mode 100644 index 0000000..29b327b --- /dev/null +++ b/src/Skobkin/Bundle/PointToolsBundle/DTO/Api/PostsPage.php @@ -0,0 +1,51 @@ +posts; + } + + /** + * @param MetaPost[]|null $posts + */ + public function setPosts(?array $posts): void + { + $this->posts = $posts; + } + + public function getHasNext(): ?bool + { + return $this->hasNext; + } + + public function setHasNext(?bool $hasNext): void + { + $this->hasNext = $hasNext; + } + + public function isValid(): bool + { + if (null !== $this->posts) { + return true; + } + + return false; + } +} \ No newline at end of file diff --git a/src/Skobkin/Bundle/PointToolsBundle/DTO/Api/User.php b/src/Skobkin/Bundle/PointToolsBundle/DTO/Api/User.php new file mode 100644 index 0000000..c34b3f9 --- /dev/null +++ b/src/Skobkin/Bundle/PointToolsBundle/DTO/Api/User.php @@ -0,0 +1,226 @@ +id; + } + + public function setId(?string $id): void + { + $this->id = $id; + } + + public function getLogin(): ?string + { + return $this->login; + } + + public function setLogin(?string $login): void + { + $this->login = $login; + } + + public function getName(): ?string + { + return $this->name; + } + + public function setName(?string $name): void + { + $this->name = $name; + } + + public function getAbout(): ?string + { + return $this->about; + } + + public function setAbout(?string $about): void + { + $this->about = $about; + } + + public function getXmpp(): ?string + { + return $this->xmpp; + } + + public function setXmpp(?string $xmpp): void + { + $this->xmpp = $xmpp; + } + + public function getCreated(): ?string + { + return $this->created; + } + + public function setCreated(?string $created): void + { + $this->created = $created; + } + + public function getGender(): ?bool + { + return $this->gender; + } + + public function setGender(?bool $gender): void + { + $this->gender = $gender; + } + + public function getDenyAnonymous(): ?bool + { + return $this->denyAnonymous; + } + + public function setDenyAnonymous(?bool $denyAnonymous): void + { + $this->denyAnonymous = $denyAnonymous; + } + + public function getPrivate(): ?bool + { + return $this->private; + } + + public function setPrivate(?bool $private): void + { + $this->private = $private; + } + + public function getBirthDate(): ?string + { + return $this->birthDate; + } + + public function setBirthDate(?string $birthDate): void + { + $this->birthDate = $birthDate; + } + + public function getHomepage(): ?string + { + return $this->homepage; + } + + public function setHomepage(?string $homepage): void + { + $this->homepage = $homepage; + } + + public function getEmail(): ?string + { + return $this->email; + } + + public function setEmail(?string $email): void + { + $this->email = $email; + } + + public function getLocation(): ?string + { + return $this->location; + } + + public function setLocation(?string $location): void + { + $this->location = $location; + } + + public function getError(): ?string + { + return $this->error; + } + + public function setError(?string $error): void + { + $this->error = $error; + } + + public function isValid(): bool + { + if (null === $this->error && null !== $this->id && null !== $this->login) { + return true; + } + + return false; + } +} \ No newline at end of file diff --git a/src/Skobkin/Bundle/PointToolsBundle/DTO/Api/ValidableInterface.php b/src/Skobkin/Bundle/PointToolsBundle/DTO/Api/ValidableInterface.php new file mode 100644 index 0000000..a98c8b6 --- /dev/null +++ b/src/Skobkin/Bundle/PointToolsBundle/DTO/Api/ValidableInterface.php @@ -0,0 +1,7 @@ +post = $post; diff --git a/src/Skobkin/Bundle/PointToolsBundle/Exception/Factory/InvalidUserDataException.php b/src/Skobkin/Bundle/PointToolsBundle/Exception/Factory/InvalidUserDataException.php new file mode 100644 index 0000000..2cd18e6 --- /dev/null +++ b/src/Skobkin/Bundle/PointToolsBundle/Exception/Factory/InvalidUserDataException.php @@ -0,0 +1,25 @@ +user = $user; + + parent::__construct($message, $code, $previous); + } + + public function getUser(): UserDTO + { + return $this->user; + } +} \ No newline at end of file diff --git a/src/Skobkin/Bundle/PointToolsBundle/Service/Exceptions/SubscriptionManagerException.php b/src/Skobkin/Bundle/PointToolsBundle/Exception/SubscriptionManagerException.php similarity index 51% rename from src/Skobkin/Bundle/PointToolsBundle/Service/Exceptions/SubscriptionManagerException.php rename to src/Skobkin/Bundle/PointToolsBundle/Exception/SubscriptionManagerException.php index 337d64e..c90933d 100644 --- a/src/Skobkin/Bundle/PointToolsBundle/Service/Exceptions/SubscriptionManagerException.php +++ b/src/Skobkin/Bundle/PointToolsBundle/Exception/SubscriptionManagerException.php @@ -1,7 +1,6 @@ ' + max_depth: 2 diff --git a/src/Skobkin/Bundle/PointToolsBundle/Resources/config/serializer/DTO.Api.Post.yml b/src/Skobkin/Bundle/PointToolsBundle/Resources/config/serializer/DTO.Api.Post.yml new file mode 100644 index 0000000..31d3de4 --- /dev/null +++ b/src/Skobkin/Bundle/PointToolsBundle/Resources/config/serializer/DTO.Api.Post.yml @@ -0,0 +1,25 @@ +Skobkin\Bundle\PointToolsBundle\DTO\Api\Post: + exclusion_policy: none + access_type: public_method + properties: + id: + type: string + #groups: [] + tags: + type: 'array' + files: + type: 'array' + author: + type: Skobkin\Bundle\PointToolsBundle\DTO\Api\User + max_depth: 1 + text: + type: string + created: + type: string + type: + type: string + private: + type: boolean + + #callback_methods: + # post_deserialize: [foo, bar] diff --git a/src/Skobkin/Bundle/PointToolsBundle/Resources/config/serializer/DTO.Api.PostPage.yml b/src/Skobkin/Bundle/PointToolsBundle/Resources/config/serializer/DTO.Api.PostPage.yml new file mode 100644 index 0000000..c75e14f --- /dev/null +++ b/src/Skobkin/Bundle/PointToolsBundle/Resources/config/serializer/DTO.Api.PostPage.yml @@ -0,0 +1,7 @@ +Skobkin\Bundle\PointToolsBundle\DTO\Api\PostPage: + exclusion_policy: none + access_type: public_method + properties: + posts: + type: 'array' + max_depth: 3 diff --git a/src/Skobkin/Bundle/PointToolsBundle/Resources/config/serializer/DTO.Api.User.yml b/src/Skobkin/Bundle/PointToolsBundle/Resources/config/serializer/DTO.Api.User.yml new file mode 100644 index 0000000..8df91bd --- /dev/null +++ b/src/Skobkin/Bundle/PointToolsBundle/Resources/config/serializer/DTO.Api.User.yml @@ -0,0 +1,49 @@ +Skobkin\Bundle\PointToolsBundle\DTO\Api\User: + exclusion_policy: none + access_type: public_method + properties: + id: + type: integer + groups: [user_short, user_full] + login: + type: string + groups: [user_short, user_full] + name: + type: string + groups: [user_short, user_full] + about: + type: string + groups: [user_full] + xmpp: + type: string + groups: [user_full] + created: + type: string + groups: [user_full] + gender: + type: boolean + groups: [user_full] + denyAnonymous: + serialized_name: 'deny_anonymous' + type: boolean + groups: [user_full] + private: + type: boolean + groups: [user_full] + birthDate: + serialized_name: 'birthdate' + type: string + groups: [user_full] + homepage: + type: string + groups: [user_full] + email: + type: string + groups: [user_full] + location: + type: string + groups: [user_full] + + # TODO automatically convert string date to DateTime + #callback_methods: + # post_deserialize: [foo, bar] diff --git a/src/Skobkin/Bundle/PointToolsBundle/Resources/config/services.yml b/src/Skobkin/Bundle/PointToolsBundle/Resources/config/services.yml index e2db511..1379f3f 100644 --- a/src/Skobkin/Bundle/PointToolsBundle/Resources/config/services.yml +++ b/src/Skobkin/Bundle/PointToolsBundle/Resources/config/services.yml @@ -20,20 +20,24 @@ services: abstract: true arguments: - '@app.http.point_client' + - '@jms_serializer' - '@logger' - + # User app.point.api_user: - class: Skobkin\Bundle\PointToolsBundle\Service\UserApi + class: Skobkin\Bundle\PointToolsBundle\Service\Api\UserApi parent: app.point.abstract_api arguments: - '@app.point.user_factory' - - '@jms_serializer' - + tags: + - { name: monolog.logger, channel: point_user_api } + # Post app.point.api_post: - class: Skobkin\Bundle\PointToolsBundle\Service\PostApi + class: Skobkin\Bundle\PointToolsBundle\Service\Api\PostApi parent: app.point.abstract_api arguments: - '@app.point.post_factory' + tags: + - { name: monolog.logger, channel: point_post_api } # Point subscription manager @@ -116,44 +120,48 @@ services: # Factories - # User factory + # Abstract factory + app.point.abstract_factory: + abstract: true + arguments: [ '@logger' ] + # User app.point.user_factory: class: Skobkin\Bundle\PointToolsBundle\Service\Factory\UserFactory + parent: app.point.abstract_factory arguments: [ '@app.point.user_repository' ] - - # Comment factory + # Comment app.point.comment_factory: class: Skobkin\Bundle\PointToolsBundle\Service\Factory\Blogs\CommentFactory + parent: app.point.abstract_factory arguments: - '@app.point.comment_repository' - '@app.point.post_repository' - '@app.point.user_factory' - - # Tag factory + # Tag app.point.tag_factory: class: Skobkin\Bundle\PointToolsBundle\Service\Factory\Blogs\TagFactory - arguments: [ '@logger', '@app.point.tag_repository' ] - - # File factory + parent: app.point.abstract_factory + arguments: [ '@app.point.tag_repository' ] + # File app.point.file_factory: class: Skobkin\Bundle\PointToolsBundle\Service\Factory\Blogs\FileFactory - arguments: [ '@logger', '@app.point.file_repository' ] - - # Post factory + parent: app.point.abstract_factory + arguments: [ '@app.point.file_repository' ] + # Post app.point.post_factory: class: Skobkin\Bundle\PointToolsBundle\Service\Factory\Blogs\PostFactory + parent: app.point.abstract_factory arguments: - - '@logger' - '@doctrine.orm.entity_manager' - '@app.point.post_repository' - '@app.point.user_factory' - '@app.point.file_factory' - '@app.point.comment_factory' - '@app.point.tag_factory' - - # Telegram accounts factory + # Telegram account app.telegram.telegram_account_factory: class: Skobkin\Bundle\PointToolsBundle\Service\Factory\Telegram\AccountFactory + parent: app.point.abstract_factory arguments: ['@app.point.telegram_account_repository'] diff --git a/src/Skobkin/Bundle/PointToolsBundle/Service/AbstractApi.php b/src/Skobkin/Bundle/PointToolsBundle/Service/AbstractApi.php deleted file mode 100644 index d1e68eb..0000000 --- a/src/Skobkin/Bundle/PointToolsBundle/Service/AbstractApi.php +++ /dev/null @@ -1,120 +0,0 @@ -client = $httpClient; - $this->logger = $logger; - } - - /** - * @param string $path Request path - * @param array $parameters Key => Value array of query parameters - * - * @return ResponseInterface - */ - public function sendGetRequest(string $path, array $parameters = []): ResponseInterface - { - $this->logger->debug('Sending GET request', ['path' => $path, 'parameters' => $parameters]); - - return $this->client->request('GET', $path, ['query' => $parameters]); - } - - /** - * @param string $path Request path - * @param array $parameters Key => Value array of request data - * - * @return ResponseInterface - */ - public function sendPostRequest(string $path, array $parameters = []): ResponseInterface - { - $this->logger->debug('Sending POST request', ['path' => $path, 'parameters' => $parameters]); - - return $this->client->request('POST', $path, ['form_params' => $parameters]); - } - - /** - * Make GET request and return data from response - * - * @param string $path Path template - * @param array $parameters Parameters array used to fill path template - * @param bool $decodeJsonResponse Decode JSON or return plaintext - * @param bool $decodeJsonToObjects Decode JSON objects to PHP objects instead of arrays - * - * @return mixed - */ - public function getGetRequestData($path, array $parameters = [], bool $decodeJsonResponse = false, bool $decodeJsonToObjects = false) - { - $response = $this->sendGetRequest($path, $parameters); - - return $this->processResponse($response, $decodeJsonResponse, $decodeJsonToObjects); - } - - /** - * Make POST request and return data from response - * - * @param string $path Path template - * @param array $parameters Parameters array used to fill path template - * @param bool $decodeJson Decode JSON or return plaintext - * @param bool $decodeToObjects Decode JSON objects to PHP objects instead of arrays - * - * @return mixed - */ - public function getPostRequestData($path, array $parameters = [], bool $decodeJson = false, bool $decodeToObjects = false) - { - $response = $this->sendPostRequest($path, $parameters); - - return $this->processResponse($response, $decodeJson, $decodeToObjects); - } - - /** - * @param ResponseInterface $response - * @param bool $decodeJson - * @param bool $decodeToObjects - * - * @return string|array|object - */ - private function processResponse(ResponseInterface $response, bool $decodeJson = false, bool $decodeToObjects = false) - { - if ($decodeJson) { - if ($decodeToObjects) { - return json_decode($response->getBody()); - } else { - return json_decode($response->getBody(), true); - } - } else { - return $response->getBody(); - } - } -} diff --git a/src/Skobkin/Bundle/PointToolsBundle/Service/Api/AbstractApi.php b/src/Skobkin/Bundle/PointToolsBundle/Service/Api/AbstractApi.php new file mode 100644 index 0000000..afe8f78 --- /dev/null +++ b/src/Skobkin/Bundle/PointToolsBundle/Service/Api/AbstractApi.php @@ -0,0 +1,176 @@ +client = $httpClient; + $this->serializer = $serializer; + $this->logger = $logger; + } + + /** + * @param string $path Request path + * @param array $parameters Key => Value array of query parameters + * + * @return ResponseInterface + * + * @throws NetworkException + */ + public function sendGetRequest(string $path, array $parameters = []): ResponseInterface + { + $this->logger->debug('Sending GET request', ['path' => $path, 'parameters' => $parameters]); + + try { + return $this->client->request('GET', $path, ['query' => $parameters]); + } catch (TransferException $e) { + throw new NetworkException('Request error', $e->getCode(), $e); + } + } + + /** + * @param string $path Request path + * @param array $parameters Key => Value array of request data + * + * @return ResponseInterface + * + * @throws NetworkException + */ + public function sendPostRequest(string $path, array $parameters = []): ResponseInterface + { + $this->logger->debug('Sending POST request', ['path' => $path, 'parameters' => $parameters]); + + try { + return $this->client->request('POST', $path, ['form_params' => $parameters]); + } catch (TransferException $e) { + throw new NetworkException('Request error', $e->getCode(), $e); + } + } + + /** + * Make GET request and return response body + */ + public function getGetResponseBody($path, array $parameters = []): StreamInterface + { + $response = $this->sendGetRequest($path, $parameters); + + $this->checkResponse($response); + + return $response->getBody(); + } + + /** + * Make POST request and return response body + */ + public function getPostResponseBody(string $path, array $parameters = []): StreamInterface + { + $response = $this->sendPostRequest($path, $parameters); + + $this->checkResponse($response); + + return $response->getBody(); + } + + /** + * Make GET request and return DTO objects + * + * @return array|object + */ + public function getGetJsonData(string $path, array $parameters = [], string $type, DeserializationContext $context = null) + { + return $this->serializer->deserialize( + $this->getGetResponseBody($path, $parameters), + $type, + 'json', + $context + ); + } + + /** + * Make POST request and return DTO objects + * + * @return array|object + */ + public function getPostJsonData(string $path, array $parameters = [], string $type, DeserializationContext $context = null) + { + return $this->serializer->deserialize( + $this->getPostResponseBody($path, $parameters), + $type, + 'json', + $context + ); + } + + /** + * @throws ForbiddenException + * @throws NotFoundException + * @throws ServerProblemException + * @throws UnauthorizedException + */ + private function checkResponse(ResponseInterface $response): void + { + $code = $response->getStatusCode(); + $reason = $response->getReasonPhrase(); + + switch ($code) { + case SymfonyResponse::HTTP_UNAUTHORIZED: + throw new UnauthorizedException($reason, $code); + break; + case SymfonyResponse::HTTP_FORBIDDEN: + throw new ForbiddenException($reason, $code); + break; + case SymfonyResponse::HTTP_NOT_FOUND: + throw new NotFoundException($reason, $code); + break; + case SymfonyResponse::HTTP_INTERNAL_SERVER_ERROR: + case SymfonyResponse::HTTP_NOT_IMPLEMENTED: + case SymfonyResponse::HTTP_BAD_GATEWAY: + case SymfonyResponse::HTTP_SERVICE_UNAVAILABLE: + case SymfonyResponse::HTTP_GATEWAY_TIMEOUT: + throw new ServerProblemException($reason, $code); + break; + } + } +} diff --git a/src/Skobkin/Bundle/PointToolsBundle/Service/PostApi.php b/src/Skobkin/Bundle/PointToolsBundle/Service/Api/PostApi.php similarity index 55% rename from src/Skobkin/Bundle/PointToolsBundle/Service/PostApi.php rename to src/Skobkin/Bundle/PointToolsBundle/Service/Api/PostApi.php index 18374d6..69b5812 100644 --- a/src/Skobkin/Bundle/PointToolsBundle/Service/PostApi.php +++ b/src/Skobkin/Bundle/PointToolsBundle/Service/Api/PostApi.php @@ -1,8 +1,9 @@ postFactory = $postFactory; } diff --git a/src/Skobkin/Bundle/PointToolsBundle/Service/Api/UserApi.php b/src/Skobkin/Bundle/PointToolsBundle/Service/Api/UserApi.php new file mode 100644 index 0000000..e349838 --- /dev/null +++ b/src/Skobkin/Bundle/PointToolsBundle/Service/Api/UserApi.php @@ -0,0 +1,183 @@ +userFactory = $userFactory; + } + + public function isLoginAndPasswordValid(string $login, string $password): bool + { + $this->logger->info('Checking user auth data via point.im API'); + + $auth = $this->authenticate($login, $password); + + if ($auth->isValid()) { + $this->logger->debug('Authentication successfull. Logging out.'); + + $this->logout($auth); + + return true; + } + + return false; + } + + public function authenticate(string $login, string $password): Auth + { + $this->logger->debug('Trying to authenticate user via Point.im API', ['login' => $login]); + + try { + return $this->getPostJsonData( + '/api/login', + [ + 'login' => $login, + 'password' => $password, + ], + Auth::class + ); + } catch (NotFoundException $e) { + throw new InvalidResponseException('API method not found', 0, $e); + } + } + + /** + * @throws InvalidResponseException + */ + public function logout(Auth $auth): bool + { + $this->logger->debug('Trying to log user out via Point.im API'); + + try { + $this->getPostResponseBody('/api/logout', ['csrf_token' => $auth->getCsRfToken()]); + + return true; + } catch (NotFoundException $e) { + throw new InvalidResponseException('API method not found', 0, $e); + } catch (ForbiddenException $e) { + return true; + } + } + + /** + * Get user subscribers by user login + * + * @return User[] + * + * @throws UserNotFoundException + */ + public function getUserSubscribersByLogin(string $login): array + { + $this->logger->debug('Trying to get user subscribers by login', ['login' => $login]); + + try { + $usersList = $this->getGetJsonData( + self::PREFIX.urlencode($login).'/subscribers', + [], + 'array<'.UserDTO::class.'>', + DeserializationContext::create()->setGroups(['user_short']) + ); + } catch (NotFoundException $e) { + throw new UserNotFoundException('User not found', 0, $e, null, $login); + } + + return $this->userFactory->findOrCreateFromDTOArray($usersList); + } + + /** + * Get user subscribers by user id + * + * @return User[] + * + * @throws UserNotFoundException + */ + public function getUserSubscribersById(int $id): array + { + $this->logger->debug('Trying to get user subscribers by id', ['id' => $id]); + + try { + $usersList = $this->getGetJsonData( + self::PREFIX.'id/'.$id.'/subscribers', + [], + 'array<'.UserDTO::class.'>', + DeserializationContext::create()->setGroups(['user_short']) + ); + } catch (NotFoundException $e) { + throw new UserNotFoundException('User not found', 0, $e, $id); + } + + return $this->userFactory->findOrCreateFromDTOArray($usersList); + } + + /** + * Get full user info by login + */ + public function getUserByLogin(string $login): User + { + $this->logger->debug('Trying to get user by login', ['login' => $login]); + + try { + /** @var UserDTO $userInfo */ + $userInfo = $this->getGetJsonData( + self::PREFIX.'login/'.urlencode($login), + [], + UserDTO::class, + DeserializationContext::create()->setGroups(['user_full']) + ); + } catch (NotFoundException $e) { + throw new UserNotFoundException('User not found', 0, $e, null, $login); + } + + return $this->userFactory->findOrCreateFromDTO($userInfo); + } + + /** + * Get full user info by id + */ + public function getUserById(int $id): User + { + $this->logger->debug('Trying to get user by id', ['id' => $id]); + + try { + /** @var UserDTO $userData */ + $userData = $this->getGetJsonData( + self::PREFIX.'id/'.$id, + [], + UserDTO::class, + DeserializationContext::create()->setGroups(['user_full']) + ); + } catch (NotFoundException $e) { + throw new UserNotFoundException('User not found', 0, $e, $id); + } + + return $this->userFactory->findOrCreateFromDTO($userData); + } +} diff --git a/src/Skobkin/Bundle/PointToolsBundle/Service/Exceptions/ApiException.php b/src/Skobkin/Bundle/PointToolsBundle/Service/Exceptions/ApiException.php deleted file mode 100644 index 0eb8fd5..0000000 --- a/src/Skobkin/Bundle/PointToolsBundle/Service/Exceptions/ApiException.php +++ /dev/null @@ -1,9 +0,0 @@ -user = $user; - - parent::__construct($message, $code, $previous); - } - - public function getUser(): User - { - return $this->user; - } -} \ No newline at end of file diff --git a/src/Skobkin/Bundle/PointToolsBundle/Service/Factory/AbstractFactory.php b/src/Skobkin/Bundle/PointToolsBundle/Service/Factory/AbstractFactory.php new file mode 100644 index 0000000..7cb236e --- /dev/null +++ b/src/Skobkin/Bundle/PointToolsBundle/Service/Factory/AbstractFactory.php @@ -0,0 +1,19 @@ +logger = $logger; + } +} \ No newline at end of file diff --git a/src/Skobkin/Bundle/PointToolsBundle/Service/Factory/Blogs/CommentFactory.php b/src/Skobkin/Bundle/PointToolsBundle/Service/Factory/Blogs/CommentFactory.php index 188b290..f15e753 100644 --- a/src/Skobkin/Bundle/PointToolsBundle/Service/Factory/Blogs/CommentFactory.php +++ b/src/Skobkin/Bundle/PointToolsBundle/Service/Factory/Blogs/CommentFactory.php @@ -2,14 +2,13 @@ namespace Skobkin\Bundle\PointToolsBundle\Service\Factory\Blogs; -use Skobkin\Bundle\PointToolsBundle\Entity\Blogs\Comment; +use Psr\Log\LoggerInterface; use Skobkin\Bundle\PointToolsBundle\Repository\Blogs\CommentRepository; use Skobkin\Bundle\PointToolsBundle\Repository\Blogs\PostRepository; -use Skobkin\Bundle\PointToolsBundle\Service\Exceptions\ApiException; -use Skobkin\Bundle\PointToolsBundle\Service\Exceptions\InvalidResponseException; +use Skobkin\Bundle\PointToolsBundle\Service\Factory\AbstractFactory; use Skobkin\Bundle\PointToolsBundle\Service\Factory\UserFactory; -class CommentFactory +class CommentFactory extends AbstractFactory { /** * @var CommentRepository @@ -27,83 +26,11 @@ class CommentFactory private $userFactory; - public function __construct(CommentRepository $commentRepository, PostRepository $postRepository, UserFactory $userFactory) + public function __construct(LoggerInterface $logger, CommentRepository $commentRepository, PostRepository $postRepository, UserFactory $userFactory) { + parent::__construct($logger); $this->userFactory = $userFactory; $this->commentRepository = $commentRepository; $this->postRepository = $postRepository; } - - /** - * @param array $data - * - * @return Comment - * - * @throws ApiException - * @throws InvalidResponseException - */ - public function createFromArray(array $data): Comment - { - $this->validateData($data); - - if (null === ($comment = $this->commentRepository->find(['post' => $data['post_id'], 'id' => $data['id']]))) { - // @fixme rare non-existing post bug - $post = $this->postRepository->find($data['post_id']); - $author = $this->userFactory->createFromArray($data['author']); - if (null !== $data['to_comment_id']) { - $toComment = $this->commentRepository->find(['post' => $data['post_id'], 'id' => $data['to_comment_id']]); - } else { - $toComment = null; - } - $createdAt = new \DateTime($data['created']); - - $comment = new Comment($data['id'], $post, $author, $toComment, $data['text'], $createdAt, $data['is_rec']); - - $this->commentRepository->add($comment); - } - - return $comment; - } - - /** - * @param array $data - * - * @return Comment[] - * - * @throws ApiException - */ - public function createFromListArray(array $data): array - { - $comments = []; - - foreach ($data as $commentData) { - $comments[] = $this->createFromArray($commentData); - } - - return $comments; - } - - /** - * @param array $data - * - * @throws InvalidResponseException - */ - private function validateData(array $data): void - { - if (!array_key_exists('author', $data)) { - throw new InvalidResponseException('Comment author data not found in API response'); - } - - // Post - if (!( - array_key_exists('id', $data) && - array_key_exists('is_rec', $data) && - array_key_exists('to_comment_id', $data) && - array_key_exists('post_id', $data) && - array_key_exists('text', $data) && - array_key_exists('created', $data) - )) { - throw new InvalidResponseException('Comment data not found in API response'); - } - } } \ No newline at end of file diff --git a/src/Skobkin/Bundle/PointToolsBundle/Service/Factory/Blogs/FileFactory.php b/src/Skobkin/Bundle/PointToolsBundle/Service/Factory/Blogs/FileFactory.php index a1261e6..60fff56 100644 --- a/src/Skobkin/Bundle/PointToolsBundle/Service/Factory/Blogs/FileFactory.php +++ b/src/Skobkin/Bundle/PointToolsBundle/Service/Factory/Blogs/FileFactory.php @@ -5,24 +5,20 @@ namespace Skobkin\Bundle\PointToolsBundle\Service\Factory\Blogs; use Psr\Log\LoggerInterface; use Skobkin\Bundle\PointToolsBundle\Entity\Blogs\File; use Skobkin\Bundle\PointToolsBundle\Repository\Blogs\FileRepository; -use Skobkin\Bundle\PointToolsBundle\Service\Exceptions\InvalidResponseException; +use Skobkin\Bundle\PointToolsBundle\Exception\Api\InvalidResponseException; +use Skobkin\Bundle\PointToolsBundle\Service\Factory\AbstractFactory; -class FileFactory +class FileFactory extends AbstractFactory { - /** - * @var LoggerInterface - */ - private $log; - /** * @var FileRepository */ private $fileRepository; - public function __construct(LoggerInterface $log, FileRepository $fileRepository) + public function __construct(LoggerInterface $logger, FileRepository $fileRepository) { - $this->log = $log; + parent::__construct($logger); $this->fileRepository = $fileRepository; } @@ -40,7 +36,7 @@ class FileFactory $file = $this->createFromUrl($url); $files[] = $file; } catch (\Exception $e) { - $this->log->error('Error while creating file from DTO', ['file' => $url, 'message' => $e->getMessage()]); + $this->logger->error('Error while creating file from DTO', ['file' => $url, 'message' => $e->getMessage()]); continue; } } diff --git a/src/Skobkin/Bundle/PointToolsBundle/Service/Factory/Blogs/PostFactory.php b/src/Skobkin/Bundle/PointToolsBundle/Service/Factory/Blogs/PostFactory.php index d217974..d2b8302 100644 --- a/src/Skobkin/Bundle/PointToolsBundle/Service/Factory/Blogs/PostFactory.php +++ b/src/Skobkin/Bundle/PointToolsBundle/Service/Factory/Blogs/PostFactory.php @@ -4,24 +4,19 @@ namespace Skobkin\Bundle\PointToolsBundle\Service\Factory\Blogs; use Doctrine\ORM\EntityManagerInterface; use Psr\Log\LoggerInterface; -use Skobkin\Bundle\PointToolsBundle\DTO\Api\Crawler\MetaPost; -use Skobkin\Bundle\PointToolsBundle\DTO\Api\Crawler\PostsPage; +use Skobkin\Bundle\PointToolsBundle\DTO\Api\MetaPost; +use Skobkin\Bundle\PointToolsBundle\DTO\Api\PostsPage; use Skobkin\Bundle\PointToolsBundle\Entity\Blogs\Post; use Skobkin\Bundle\PointToolsBundle\Entity\Blogs\PostTag; use Skobkin\Bundle\PointToolsBundle\Exception\Factory\Blog\InvalidDataException; use Skobkin\Bundle\PointToolsBundle\Repository\Blogs\PostRepository; -use Skobkin\Bundle\PointToolsBundle\Service\Exceptions\ApiException; use Skobkin\Bundle\PointToolsBundle\Exception\Factory\Blog\InvalidPostDataException; -use Skobkin\Bundle\PointToolsBundle\Service\Exceptions\InvalidResponseException; +use Skobkin\Bundle\PointToolsBundle\Exception\Api\InvalidResponseException; +use Skobkin\Bundle\PointToolsBundle\Service\Factory\AbstractFactory; use Skobkin\Bundle\PointToolsBundle\Service\Factory\UserFactory; -class PostFactory +class PostFactory extends AbstractFactory { - /** - * @var LoggerInterface - */ - private $logger; - /** * @var EntityManagerInterface */ @@ -62,7 +57,7 @@ class PostFactory CommentFactory $commentFactory, TagFactory $tagFactory ) { - $this->logger = $logger; + parent::__construct($logger); $this->em = $em; $this->postRepository = $postRepository; $this->userFactory = $userFactory; @@ -78,7 +73,6 @@ class PostFactory * * @return bool * - * @throws ApiException * @throws InvalidResponseException */ public function createFromPageDTO(PostsPage $page): bool @@ -122,7 +116,6 @@ class PostFactory * * @return Post * - * @throws ApiException * @throws InvalidDataException */ private function createFromDTO(MetaPost $postData): Post @@ -137,7 +130,7 @@ class PostFactory } try { - $user = $this->userFactory->createFromDTO($postData->getPost()->getAuthor()); + $user = $this->userFactory->findOrCreateFromDTO($postData->getPost()->getAuthor()); } catch (\Exception $e) { $this->logger->error('Error while creating user from DTO'); throw $e; diff --git a/src/Skobkin/Bundle/PointToolsBundle/Service/Factory/Blogs/TagFactory.php b/src/Skobkin/Bundle/PointToolsBundle/Service/Factory/Blogs/TagFactory.php index 9337319..6b40b32 100644 --- a/src/Skobkin/Bundle/PointToolsBundle/Service/Factory/Blogs/TagFactory.php +++ b/src/Skobkin/Bundle/PointToolsBundle/Service/Factory/Blogs/TagFactory.php @@ -5,14 +5,10 @@ namespace Skobkin\Bundle\PointToolsBundle\Service\Factory\Blogs; use Psr\Log\LoggerInterface; use Skobkin\Bundle\PointToolsBundle\Entity\Blogs\Tag; use Skobkin\Bundle\PointToolsBundle\Repository\Blogs\TagRepository; +use Skobkin\Bundle\PointToolsBundle\Service\Factory\AbstractFactory; -class TagFactory +class TagFactory extends AbstractFactory { - /** - * @var LoggerInterface - */ - private $logger; - /** * @var TagRepository */ @@ -21,7 +17,7 @@ class TagFactory public function __construct(LoggerInterface $logger, TagRepository $tagRepository) { - $this->logger = $logger; + parent::__construct($logger); $this->tagRepository = $tagRepository; } diff --git a/src/Skobkin/Bundle/PointToolsBundle/Service/Factory/Telegram/AccountFactory.php b/src/Skobkin/Bundle/PointToolsBundle/Service/Factory/Telegram/AccountFactory.php index 7a47505..e0334ae 100644 --- a/src/Skobkin/Bundle/PointToolsBundle/Service/Factory/Telegram/AccountFactory.php +++ b/src/Skobkin/Bundle/PointToolsBundle/Service/Factory/Telegram/AccountFactory.php @@ -2,11 +2,13 @@ namespace Skobkin\Bundle\PointToolsBundle\Service\Factory\Telegram; +use Psr\Log\LoggerInterface; use Skobkin\Bundle\PointToolsBundle\Entity\Telegram\Account; use Skobkin\Bundle\PointToolsBundle\Repository\Telegram\AccountRepository; +use Skobkin\Bundle\PointToolsBundle\Service\Factory\AbstractFactory; use unreal4u\TelegramAPI\Telegram\Types\Message; -class AccountFactory +class AccountFactory extends AbstractFactory { /** * @var AccountRepository @@ -14,8 +16,9 @@ class AccountFactory private $accountRepo; - public function __construct(AccountRepository $accountRepository) + public function __construct(LoggerInterface $logger, AccountRepository $accountRepository) { + parent::__construct($logger); $this->accountRepo = $accountRepository; } diff --git a/src/Skobkin/Bundle/PointToolsBundle/Service/Factory/UserFactory.php b/src/Skobkin/Bundle/PointToolsBundle/Service/Factory/UserFactory.php index 1fc351d..2c7fc2e 100644 --- a/src/Skobkin/Bundle/PointToolsBundle/Service/Factory/UserFactory.php +++ b/src/Skobkin/Bundle/PointToolsBundle/Service/Factory/UserFactory.php @@ -2,67 +2,40 @@ namespace Skobkin\Bundle\PointToolsBundle\Service\Factory; -use Doctrine\ORM\EntityManagerInterface; -use Skobkin\Bundle\PointToolsBundle\DTO\Api\Crawler\User as UserDTO; +use Psr\Log\LoggerInterface; +use Skobkin\Bundle\PointToolsBundle\DTO\Api\User as UserDTO; use Skobkin\Bundle\PointToolsBundle\Entity\User; use Skobkin\Bundle\PointToolsBundle\Repository\UserRepository; -use Skobkin\Bundle\PointToolsBundle\Service\Exceptions\ApiException; -use Skobkin\Bundle\PointToolsBundle\Service\Exceptions\Factory\InvalidUserDataException; -use Skobkin\Bundle\PointToolsBundle\Service\Exceptions\InvalidResponseException; +use Skobkin\Bundle\PointToolsBundle\Exception\Factory\InvalidUserDataException; -class UserFactory +class UserFactory extends AbstractFactory { /** * @var UserRepository */ private $userRepository; - /** - * @param EntityManagerInterface $em - */ - public function __construct(UserRepository $userRepository) + + public function __construct(LoggerInterface $logger, UserRepository $userRepository) { + parent::__construct($logger); $this->userRepository = $userRepository; } - /** - * @param array $data - * - * @return User - * - * @throws InvalidResponseException - */ - public function createFromArray(array $data): User - { - $this->validateArrayData($data); - - /** @var User $user */ - if (null === ($user = $this->userRepository->find($data['id']))) { - // Creating new user - $user = new User($data['id']); - $this->userRepository->add($user); - } - - // Updating data - $user - ->setLogin($data['login']) - ->setName($data['name']) - ; - - return $user; - } - /** * @param UserDTO $userData * * @return User * - * @throws ApiException * @throws InvalidUserDataException */ - public function createFromDTO(UserDTO $userData): User + public function findOrCreateFromDTO(UserDTO $userData): User { - $this->validateDTOData($userData); + // @todo LOG + + if (!$userData->isValid()) { + throw new InvalidUserDataException('Invalid user data', $userData); + } /** @var User $user */ if (null === ($user = $this->userRepository->find($userData->getId()))) { @@ -80,27 +53,16 @@ class UserFactory return $user; } - /** - * @param array $data - * - * @throws InvalidResponseException - */ - private function validateArrayData(array $data): void + public function findOrCreateFromDTOArray(array $usersData): array { - if (!array_key_exists('id', $data) || !array_key_exists('login', $data) || !array_key_exists('name', $data) || !is_numeric($data['id'])) { - throw new InvalidResponseException('Invalid user data'); - } - } + // @todo LOG - /** - * @param UserDTO $data - * - * @throws InvalidResponseException - */ - private function validateDTOData(UserDTO $data): void - { - if (!$data->getId() || !$data->getLogin()) { - throw new InvalidUserDataException('User have no id or login', $data); + $result = []; + + foreach ($usersData as $userData) { + $result[] = $this->findOrCreateFromDTO($userData); } + + return $result; } } \ No newline at end of file diff --git a/src/Skobkin/Bundle/PointToolsBundle/Service/Telegram/PrivateMessageProcessor.php b/src/Skobkin/Bundle/PointToolsBundle/Service/Telegram/PrivateMessageProcessor.php index f0e7d71..7519b6f 100644 --- a/src/Skobkin/Bundle/PointToolsBundle/Service/Telegram/PrivateMessageProcessor.php +++ b/src/Skobkin/Bundle/PointToolsBundle/Service/Telegram/PrivateMessageProcessor.php @@ -11,7 +11,7 @@ use Skobkin\Bundle\PointToolsBundle\Repository\SubscriptionRepository; use Skobkin\Bundle\PointToolsBundle\Repository\Telegram\AccountRepository; use Skobkin\Bundle\PointToolsBundle\Repository\UserRepository; use Skobkin\Bundle\PointToolsBundle\Service\Factory\Telegram\AccountFactory; -use Skobkin\Bundle\PointToolsBundle\Service\UserApi; +use Skobkin\Bundle\PointToolsBundle\Service\Api\UserApi; use unreal4u\TelegramAPI\Telegram\Types\Message; use unreal4u\TelegramAPI\Telegram\Types\ReplyKeyboardMarkup; use unreal4u\TelegramAPI\Telegram\Types\ReplyKeyboardRemove; @@ -174,7 +174,7 @@ class PrivateMessageProcessor throw new CommandProcessingException('User not found in Point Tools database. Please try again later.'); } - if ($this->userApi->isAuthDataValid($login, $password)) { + if ($this->userApi->isLoginAndPasswordValid($login, $password)) { $account->setUser($user); return true; diff --git a/src/Skobkin/Bundle/PointToolsBundle/Service/UserApi.php b/src/Skobkin/Bundle/PointToolsBundle/Service/UserApi.php deleted file mode 100644 index a6bdd9b..0000000 --- a/src/Skobkin/Bundle/PointToolsBundle/Service/UserApi.php +++ /dev/null @@ -1,311 +0,0 @@ -userFactory = $userFactory; - $this->serializer = $serializer; - } - - public function isAuthDataValid(string $login, string $password): bool - { - $this->logger->info('Checking user auth data via point.im API'); - - $auth = $this->authenticate($login, $password); - - if (null === $auth->getError() && null !== $auth->getToken()) { - $this->logger->debug('Authentication successfull. Logging out.'); - - $this->logout($auth); - - return true; - } - - return false; - } - - public function authenticate(string $login, string $password): Auth - { - $this->logger->debug('Trying to authenticate user via Point.im API', ['login' => $login]); - - try { - $authData = $this->getPostRequestData( - '/api/login', - [ - 'login' => $login, - 'password' => $password, - ] - ); - - return $this->serializer->deserialize($authData, Auth::class, 'json'); - } catch (RequestException $e) { - if (Response::HTTP_NOT_FOUND === $e->getResponse()->getStatusCode()) { - throw new InvalidResponseException('API method not found', 0, $e); - } else { - throw $e; - } - } - } - - public function logout(Auth $auth): bool - { - $this->logger->debug('Trying to log user out via Point.im API'); - - try { - $this->getPostRequestData('/api/logout', ['csrf_token' => $auth->getCsRfToken()]); - - return true; - } catch (RequestException $e) { - if (Response::HTTP_NOT_FOUND === $e->getResponse()->getStatusCode()) { - throw new InvalidResponseException('API method not found', 0, $e); - } elseif (Response::HTTP_FORBIDDEN === $e->getResponse()->getStatusCode()) { - return true; - } else { - throw $e; - } - } - } - - /** - * Get user subscribers by user login - * - * @param string $login - * - * @return User[] - * - * @throws ApiException - * @throws InvalidResponseException - * @throws UserNotFoundException - */ - public function getUserSubscribersByLogin(string $login): array - { - $this->logger->debug('Trying to get user subscribers by login', ['login' => $login]); - - try { - $usersList = $this->getGetRequestData('/api/user/'.urlencode($login).'/subscribers', [], true); - } catch (RequestException $e) { - if (Response::HTTP_NOT_FOUND === $e->getResponse()->getStatusCode()) { - throw new UserNotFoundException('User not found', 0, $e, null, $login); - } else { - throw $e; - } - } - - return $this->getUsersFromList($usersList); - } - - /** - * Get user subscribers by user id - * - * @param int $id - * - * @return User[] - * - * @throws ApiException - * @throws InvalidResponseException - * @throws UserNotFoundException - */ - public function getUserSubscribersById(int $id): array - { - $this->logger->debug('Trying to get user subscribers by id', ['id' => $id]); - - try { - $usersList = $this->getGetRequestData('/api/user/id/'.(int) $id.'/subscribers', [], true); - } catch (RequestException $e) { - if (Response::HTTP_NOT_FOUND === $e->getResponse()->getStatusCode()) { - throw new UserNotFoundException('User not found', 0, $e, $id); - } else { - throw $e; - } - } - - return $this->getUsersFromList($usersList); - } - - /** - * Get user subscriptions by user login - * - * @param string $login - * - * @return User[] - * - * @throws ApiException - * @throws InvalidResponseException - * @throws UserNotFoundException - */ - public function getUserSubscriptionsByLogin(string $login): array - { - $this->logger->debug('Trying to get user subscriptions by login', ['login' => $login]); - - try { - $usersList = $this->getGetRequestData('/api/user/'.urlencode($login).'/subscriptions', [], true); - } catch (RequestException $e) { - if (Response::HTTP_NOT_FOUND === $e->getResponse()->getStatusCode()) { - throw new UserNotFoundException('User not found', 0, $e, null, $login); - } else { - throw $e; - } - } - - return $this->getUsersFromList($usersList); - } - - /** - * Get user subscriptions by user id - * - * @param int $id - * - * @return User[] - * - * @throws ApiException - * @throws InvalidResponseException - * @throws UserNotFoundException - */ - public function getUserSubscriptionsById(int $id): array - { - $this->logger->debug('Trying to get user subscriptions by id', ['id' => $id]); - - try { - $usersList = $this->getGetRequestData('/api/user/id/'.(int) $id.'/subscriptions', [], true); - } catch (RequestException $e) { - if (Response::HTTP_NOT_FOUND === $e->getResponse()->getStatusCode()) { - throw new UserNotFoundException('User not found', 0, $e, $id); - } else { - throw $e; - } - } - - return $this->getUsersFromList($usersList); - } - - /** - * Get single user by login - * - * @param string $login - * - * @return User - * - * @throws UserNotFoundException - * @throws RequestException - */ - public function getUserByLogin(string $login): User - { - $this->logger->debug('Trying to get user by login', ['login' => $login]); - - try { - $userInfo = $this->getGetRequestData('/api/user/login/'.urlencode($login), [], true); - } catch (RequestException $e) { - if (Response::HTTP_NOT_FOUND === $e->getResponse()->getStatusCode()) { - throw new UserNotFoundException('User not found', 0, $e, null, $login); - } else { - throw $e; - } - } - - return $this->getUserFromUserInfo($userInfo); - } - - /** - * Get single user by id - * - * @param int $id - * - * @return User - * - * @throws UserNotFoundException - * @throws RequestException - */ - public function getUserById(int $id): User - { - $this->logger->debug('Trying to get user by id', ['id' => $id]); - - try { - $userInfo = $this->getGetRequestData('/api/user/id/'.$id, [], true); - } catch (RequestException $e) { - if (Response::HTTP_NOT_FOUND === $e->getResponse()->getStatusCode()) { - throw new UserNotFoundException('User not found', 0, $e, $id); - } else { - throw $e; - } - } - - return $this->getUserFromUserInfo($userInfo); - } - - /** - * Finds and updates or create new user from API response data - * - * @param array $userInfo - * - * @return User - * - * @throws ApiException - * @throws InvalidResponseException - */ - private function getUserFromUserInfo(array $userInfo): User - { - $this->logger->debug('Trying to create user from array', ['array' => $userInfo]); - - return $this->userFactory->createFromArray($userInfo); - } - - /** - * Get array of User objects from API response containing user list - * - * @param array $users - * - * @return User[] - * - * @throws ApiException - * @throws InvalidResponseException - */ - private function getUsersFromList(array $users = []): array - { - $this->logger->debug('Trying to create multiple users from array', ['array' => $users]); - - if (array_key_exists('error', $users)) { - $this->logger->error('User list contains error object', ['error' => $users['error']]); - - throw new ApiException('User list response contains error object'); - } - - /** @var User[] $resultUsers */ - $resultUsers = []; - - foreach ($users as $userInfo) { - $resultUsers[] = $this->getUserFromUserInfo($userInfo); - } - - return $resultUsers; - } -}