More factories to the God of Factories! Entities update.

This commit is contained in:
Alexey Skobkin 2015-10-26 05:57:53 +03:00
parent 41960f21c7
commit 3b25afd6aa
8 changed files with 589 additions and 87 deletions

View file

@ -8,7 +8,9 @@ use Skobkin\Bundle\PointToolsBundle\Entity\User;
/**
* Comment
*
* @ORM\Table(name="posts.comments")
* @ORM\Table(name="posts.comments", schema="posts", indexes={
* @ORM\Index(name="idx_comment_created_at", columns={"created_at"})
* })
* @ORM\Entity
*/
class Comment
@ -18,7 +20,6 @@ class Comment
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
@ -32,27 +33,28 @@ class Comment
/**
* @var \DateTime
*
* @ORM\Column(name="createdAt", type="datetime")
* @ORM\Column(name="created_at", type="datetime")
*/
private $createdAt;
/**
* @var boolean
*
* @ORM\Column(name="isRec", type="boolean")
* @ORM\Column(name="is_rec", type="boolean")
*/
private $isRec;
private $rec;
/**
* @var int
* @var bool
*
* @ORM\Column(name="number", type="integer")
* @ORM\Column(name="is_deleted", type="boolean")
*/
private $number;
private $deleted = false;
/**
* @var Post
*
* @ORM\Id
* @ORM\ManyToOne(targetEntity="Skobkin\Bundle\PointToolsBundle\Entity\Blogs\Post")
* @ORM\JoinColumn(name="post_id")
*/
@ -67,13 +69,42 @@ class Comment
private $author;
/**
* @var Comment
* @var Comment|null
*
* @ORM\ManyToOne(targetEntity="Skobkin\Bundle\PointToolsBundle\Entity\Blogs\Comment")
* @ORM\JoinColumn(name="to_comment_id", nullable=true)
*/
private $toComment;
/**
* @param int $id
* @param Post $post
* @param User $author
* @param Comment|null $toComment
* @param string $text
* @param \DateTime $createdAt
* @param bool $isRec
*/
public function __construct($id, Post $post, User $author, Comment $toComment = null, $text, \DateTime $createdAt, $isRec)
{
if (!is_numeric($id)) {
throw new \InvalidArgumentException('$id must be an integer');
}
if (!is_bool($isRec)) {
throw new \InvalidArgumentException('$isRec must be boolean');
}
if (!is_string($text)) {
throw new \InvalidArgumentException('$text must be a string');
}
$this->id = (int)$id;
$this->post = $post;
$this->author = $author;
$this->toComment = $toComment;
$this->text = $text;
$this->createdAt = $createdAt;
$this->rec = $isRec;
}
/**
* Get id
@ -134,12 +165,12 @@ class Comment
/**
* Set isRec
*
* @param boolean $isRec
* @param boolean $rec
* @return Comment
*/
public function setIsRec($isRec)
public function setRec($rec)
{
$this->isRec = $isRec;
$this->rec = $rec;
return $this;
}
@ -151,26 +182,17 @@ class Comment
*/
public function isRec()
{
return $this->isRec;
return $this->rec;
}
/**
* @return int
* Get isRec
*
* @return boolean
*/
public function getNumber()
public function getRec()
{
return $this->number;
}
/**
* @param int $number
* @return Comment
*/
public function setNumber($number)
{
$this->number = $number;
return $this;
return $this->rec;
}
/**
@ -230,5 +252,36 @@ class Comment
return $this;
}
/**
* Set deleted
*
* @param boolean $deleted
* @return Comment
*/
public function setDeleted($deleted)
{
$this->deleted = $deleted;
return $this;
}
/**
* Get deleted
*
* @return boolean
*/
public function getDeleted()
{
return $this->deleted;
}
/**
* Get deleted
*
* @return boolean
*/
public function isDeleted()
{
return $this->deleted;
}
}

View file

@ -3,14 +3,15 @@
namespace Skobkin\Bundle\PointToolsBundle\Entity\Blogs;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Skobkin\Bundle\PointToolsBundle\Entity\User;
/**
* Post
*
* @ORM\Table(name="posts.posts")
* @ORM\Table(name="posts.posts", schema="posts", indexes={
* @ORM\Index(name="idx_post_created_at", columns={"created_at"})
* })
* @ORM\Entity
*/
class Post
@ -23,13 +24,6 @@ class Post
*/
private $id;
/**
* @var integer
*
* @ORM\Column(name="uid", type="integer")
*/
private $uid;
/**
* @var string
*
@ -40,7 +34,7 @@ class Post
/**
* @var \DateTime
*
* @ORM\Column(name="createdAt", type="datetime")
* @ORM\Column(name="created_at", type="datetime")
*/
private $createdAt;
@ -51,6 +45,13 @@ class Post
*/
private $type;
/**
* @var bool
*
* @ORM\Column(name="is_deleted", type="boolean")
*/
private $deleted = false;
/**
* @var User
*
@ -60,7 +61,7 @@ class Post
private $author;
/**
* @var Tag[]|Collection
* @var Tag[]|ArrayCollection
*
* @ORM\ManyToMany(targetEntity="Skobkin\Bundle\PointToolsBundle\Entity\Blogs\Tag", fetch="EXTRA_LAZY")
* @ORM\JoinTable(name="posts.posts_tags",
@ -71,13 +72,19 @@ class Post
private $tags;
/**
* @var Comment[]|Collection
* @var Comment[]|ArrayCollection
*/
private $comments;
public function __construct()
public function __construct($id, $type, $text, \DateTime $createdAt, User $author = null)
{
$this->id = $id;
$this->type = $type;
$this->createdAt = $createdAt;
$this->text = $text;
$this->author = $author;
$this->tags = new ArrayCollection();
$this->comments = new ArrayCollection();
}
@ -92,29 +99,6 @@ class Post
return $this->id;
}
/**
* Set uid
*
* @param integer $uid
* @return Post
*/
public function setUid($uid)
{
$this->uid = $uid;
return $this;
}
/**
* Get uid
*
* @return integer
*/
public function getUid()
{
return $this->uid;
}
/**
* Set text
*
@ -202,29 +186,15 @@ class Post
return $this;
}
/**
* Set id
*
* @param string $id
* @return Post
*/
public function setId($id)
{
$this->id = $id;
return $this;
}
/**
* Add tags
*
* @param Tag $tags
* @param Tag $tag
* @return Post
*/
public function addTag(Tag $tags)
public function addTag(Tag $tag)
{
$this->tags[] = $tags;
$this->tags[] = $tag;
return $this;
}
@ -232,20 +202,53 @@ class Post
/**
* Remove tags
*
* @param Tag $tags
* @param Tag $tag
*/
public function removeTag(Tag $tags)
public function removeTag(Tag $tag)
{
$this->tags->removeElement($tags);
$this->tags->removeElement($tag);
}
/**
* Get tags
*
* @return Collection
* @return ArrayCollection
*/
public function getTags()
{
return $this->tags;
}
/**
* Set deleted
*
* @param boolean $deleted
* @return Post
*/
public function setDeleted($deleted)
{
$this->deleted = $deleted;
return $this;
}
/**
* Get deleted
*
* @return boolean
*/
public function getDeleted()
{
return $this->deleted;
}
/**
* Get deleted
*
* @return boolean
*/
public function isDeleted()
{
return $this->deleted;
}
}

View file

@ -7,7 +7,9 @@ use Doctrine\ORM\Mapping as ORM;
/**
* Tag
*
* @ORM\Table(name="posts.tags")
* @ORM\Table(name="posts.tags", schema="posts", indexes={
* @ORM\Index(name="idx_tag_text", columns={"text"})
* })
* @ORM\Entity
*/
class Tag
@ -24,11 +26,19 @@ class Tag
/**
* @var string
*
* @ORM\Column(name="text", type="string", length=128, unique=true)
* @ORM\Column(name="text", type="text", unique=true)
*/
private $text;
/**
* @param string $text
*/
public function __construct($text)
{
$this->text = $text;
}
/**
* Get id
*

View file

@ -13,6 +13,30 @@ services:
- "%point_api_base_url%"
- @doctrine.orm.entity_manager
skobkin_point_tools.api_post:
class: Skobkin\Bundle\PointToolsBundle\Service\PostApi
arguments:
- @skobkin_point_tools.http_client
- "%point_use_https%"
- "%point_api_base_url%"
- @doctrine.orm.entity_manager
skobkin_point_tools.subscriptions_manager:
class: Skobkin\Bundle\PointToolsBundle\Service\SubscriptionsManager
arguments: [ @doctrine.orm.entity_manager ]
skobkin__point_tools.service_factory.user_factory:
class: Skobkin\Bundle\PointToolsBundle\Service\Factory\UserFactory
arguments: [ @doctrine.orm.entity_manager ]
skobkin__point_tools.service_factory.comment_factory:
class: Skobkin\Bundle\PointToolsBundle\Service\Factory\CommentFactory
arguments: [ @doctrine.orm.entity_manager, @skobkin__point_tools.service_factory.user_factory ]
skobkin__point_tools.service_factory.tag_factory:
class: Skobkin\Bundle\PointToolsBundle\Service\Factory\TagFactory
arguments: [ @doctrine.orm.entity_manager ]
skobkin__point_tools.service_factory.post_factory:
class: Skobkin\Bundle\PointToolsBundle\Service\Factory\PostFactory
arguments: [ @doctrine.orm.entity_manager, @skobkin__point_tools.service_factory.user_factory, @skobkin__point_tools.service_factory.comment_factory, @skobkin__point_tools.service_factory.tag_factory ]

View file

@ -0,0 +1,124 @@
<?php
namespace Skobkin\Bundle\PointToolsBundle\Service\Factory;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use Skobkin\Bundle\PointToolsBundle\Entity\Blogs\Comment;
use Skobkin\Bundle\PointToolsBundle\Entity\Blogs\Post;
use Skobkin\Bundle\PointToolsBundle\Service\Exceptions\ApiException;
use Skobkin\Bundle\PointToolsBundle\Service\Exceptions\InvalidResponseException;
class CommentFactory
{
/**
* @var EntityManager
*/
private $em;
/**
* @var EntityRepository
*/
private $commentRepository;
/**
* @var EntityRepository
*/
private $postRepository;
/**
* @var UserFactory
*/
private $userFactory;
/**
* @param EntityManagerInterface $em
* @param UserFactory $userFactory
*/
public function __construct(EntityManagerInterface $em, UserFactory $userFactory)
{
$this->em = $em;
$this->userFactory = $userFactory;
$this->commentRepository = $em->getRepository('SkobkinPointToolsBundle:Blogs\Comment');
$this->postRepository = $em->getRepository('SkobkinPointToolsBundle:Blogs\Post');
}
/**
* @param array $data
*
* @return Comment
* @throws ApiException
* @throws InvalidResponseException
*/
public function createFromArray(array $data)
{
$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->em->persist($comment);
}
try {
$this->em->flush($comment);
} catch (\Exception $e) {
throw new ApiException(sprintf('Error while flushing changes for #%s/%d: %s', $data['post_id'], $data['id'], $e->getMessage()), 0, $e);
}
return $comment;
}
/**
* @param array $data
*
* @return Comment[]
* @throws ApiException
*/
public function createFromListArray(array $data)
{
$comments = [];
foreach ($data as $commentData) {
$comments[] = $this->createFromArray($commentData);
}
return $comments;
}
/**
* @param array $data
*
* @throws InvalidResponseException
*/
private function validateData(array $data)
{
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');
}
}
}

View file

@ -0,0 +1,113 @@
<?php
namespace Skobkin\Bundle\PointToolsBundle\Service\Factory;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use Skobkin\Bundle\PointToolsBundle\Entity\Blogs\Post;
use Skobkin\Bundle\PointToolsBundle\Service\Exceptions\InvalidResponseException;
use Skobkin\Bundle\PointToolsBundle\Service\Factory\UserFactory;
use Skobkin\Bundle\PointToolsBundle\Service\Factory\CommentFactory;
use Skobkin\Bundle\PointToolsBundle\Service\Factory\TagFactory;
class PostFactory
{
/**
* @var EntityManager
*/
private $em;
/**
* @var EntityRepository
*/
private $postRepository;
/**
* @var UserFactory
*/
private $userFactory;
/**
* @var CommentFactory
*/
private $commentFactory;
/**
* @var TagFactory
*/
private $tagFactory;
/**
* @param EntityManager $em
*/
public function __construct(EntityManagerInterface $em, UserFactory $userFactory, CommentFactory $commentFactory, TagFactory $tagFactory)
{
$this->userFactory = $userFactory;
$this->commentFactory = $commentFactory;
$this->tagFactory = $tagFactory;
$this->em = $em;
$this->postRepository = $em->getRepository('SkobkinPointToolsBundle:Blogs\Post');
}
public function createFromArray(array $data)
{
$this->validateData($data);
if (null === ($post = $this->postRepository->find($data['post']['id']))) {
$createdAt = new \DateTime($data['post']['created']);
$author = $this->userFactory->createFromArray($data['post']['author']);
$post = new Post($data['post']['id'], $data['post']['type'], $data['post']['text'], $createdAt, $author);
$this->em->persist($post);
}
$post->setText($data['post']['text']);
// Tags
$tags = $this->tagFactory->createFromListArray($data['post']['tags']);
// Removing deleted tags
foreach ($post->getTags() as $tag) {
if (false === in_array($tag, $tags, true)) {
$post->removeTag($tag);
}
}
// Adding new tags
foreach ($tags as $tag) {
if (!$post->getTags()->contains($tag)) {
$post->addTag($tag);
}
}
// Comments
$comments = $this->commentFactory->createFromListArray($data['comments']);
// Marking removed comments
return $post;
}
private function validateData(array $data)
{
if (!array_key_exists('post', $data)) {
throw new InvalidResponseException('Post data not found in API response');
}
if (!array_key_exists('comments', $data)) {
throw new InvalidResponseException('Comments data not found in API response');
}
if (!(
array_key_exists('id', $data['post']) &&
array_key_exists('type', $data['post']) &&
array_key_exists('text', $data['post']) &&
array_key_exists('tags', $data['post']) &&
array_key_exists('author', $data['post'])
)) {
throw new InvalidResponseException('Post content not found in API response');
}
}
}

View file

@ -0,0 +1,95 @@
<?php
namespace Skobkin\Bundle\PointToolsBundle\Service\Factory;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use Skobkin\Bundle\PointToolsBundle\Entity\Blogs\Tag;
use Skobkin\Bundle\PointToolsBundle\Service\Exceptions\ApiException;
use Skobkin\Bundle\PointToolsBundle\Service\Exceptions\InvalidResponseException;
class TagFactory
{
/**
* @var EntityManager
*/
private $em;
/**
* @var EntityRepository
*/
private $tagRepository;
/**
* @param EntityManager $em
*/
public function __construct(EntityManagerInterface $em)
{
$this->em = $em;
$this->tagRepository = $em->getRepository('SkobkinPointToolsBundle:Blogs\Tag');
}
/**
* @param $data
*
* @return Tag
* @throws ApiException
* @throws InvalidResponseException
* @throws \Doctrine\ORM\NonUniqueResultException
*/
public function createFromArray($data)
{
$this->validateData($data);
$qb = $this->tagRepository->createQueryBuilder('t');
$qb
->select()
->where($qb->expr()->eq('lower(t.text)', 'lower(:text)'))
->setParameter('text', $data)
;
if (null === ($tag = $qb->getQuery()->getOneOrNullResult())) {
$tag = new Tag($data);
$this->em->persist($tag);
}
try {
$this->em->flush($tag);
} catch (\Exception $e) {
throw new ApiException(sprintf('Error while flushing changes for [%d] %s: %s', $tag->getId(), $tag->getText(), $e->getMessage()), 0, $e);
}
return $tag;
}
/**
* @param array $data
*
* @return Tag[]
* @throws ApiException
*/
public function createFromListArray(array $data)
{
$tags = [];
foreach ($data as $text) {
$tags[] = $this->createFromArray($text);
}
return $tags;
}
/**
* @param $data
*
* @throws InvalidResponseException
*/
private function validateData($data)
{
if (!is_string($data)) {
throw new InvalidResponseException('Tag data must be a string');
}
}
}

View file

@ -0,0 +1,80 @@
<?php
namespace Skobkin\Bundle\PointToolsBundle\Service\Factory;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use Skobkin\Bundle\PointToolsBundle\Entity\Blogs\Post;
use Skobkin\Bundle\PointToolsBundle\Entity\User;
use Skobkin\Bundle\PointToolsBundle\Service\Exceptions\ApiException;
use Skobkin\Bundle\PointToolsBundle\Service\Exceptions\InvalidResponseException;
class UserFactory
{
/**
* @var EntityManager
*/
private $em;
/**
* @var EntityRepository
*/
private $userRepository;
/**
* @param EntityManager $em
*/
public function __construct(EntityManagerInterface $em)
{
$this->em = $em;
$this->userRepository = $em->getRepository('SkobkinPointToolsBundle:User');
}
/**
* @param array $data
*
* @return User
* @throws ApiException
* @throws InvalidResponseException
*/
public function createFromArray(array $data)
{
$this->validateData($data);
// @todo Return ID existance check when @ap-Codkelden will fix this API behaviour
/** @var User $user */
if (null === ($user = $this->userRepository->find($data['id']))) {
// Creating new user
$user = new User($data['id']);
$this->em->persist($user);
}
// Updating data
$user
->setLogin($data['login'])
->setName($data['name'])
;
try {
$this->em->flush($user);
} catch (\Exception $e) {
throw new ApiException(sprintf('Error while flushing changes for [%d] %s: %s', $user->getId(), $user->getLogin(), $e->getMessage()), 0, $e);
}
return $user;
}
/**
* @param array $data
*
* @throws InvalidResponseException
*/
private function validateData(array $data)
{
if (!(array_key_exists('id', $data) && array_key_exists('login', $data) && array_key_exists('name', $data))) {
throw new InvalidResponseException('Invalid user data');
}
}
}