Skip to content

Instantly share code, notes, and snippets.

@l3l0
Created December 1, 2017 11:49
Show Gist options
  • Select an option

  • Save l3l0/a7984c1b020f3234adb06a1a3fb20523 to your computer and use it in GitHub Desktop.

Select an option

Save l3l0/a7984c1b020f3234adb06a1a3fb20523 to your computer and use it in GitHub Desktop.
<?php
declare(strict_types=1);
namespace Cocoders\Application\View\Blog;
class AdminPost
{
private $id;
private $name;
private $tagsNames;
public function __construct(int $id, string $name, array $tagsNames)
{
$this->id = $id;
$this->name = $name;
$this->tagsNames = $tagsNames;
}
public function id(): int
{
return $this->id;
}
public function name(): string
{
return $this->name;
}
public function tagsNames(): array
{
return $this->tagsNames;
}
}
<?php
declare(strict_types=1);
namespace Cocoders\Application\View\Blog
interface AdminPostView
{
/**
* @return AdminPost[]
*/
public function all(): array;
}
<?php
declare(strict_types=1);
namespace Cocoders\Adapter\Doctrine\Application\View;
use Cocoders\Application\View\Blog\AdminPostView as AdminPostViewInterface;
use Cocoders\Application\View\Blog\AdminPost;
final class DoctrineAdminPostView implements AdminPostViewInterface
{
private $manager;
public function __construct(EntityManager $manager)
{
$this->manager = $manager;
}
public function all(): array
{
$results = $this->manager->getConnection()->fetchAll('SELECT FROM posts p ORDER BY id DESC');
return array_map(function ($result) {
return new AdminPost((int) $result['id'], $result['name'], json_decode($result['tags'], true));
}, $results);
}
}
<?php
declare(strict_types=1);
namespace Cocoders\Adapter\Doctrine\Domain\Blog;
use Cocoders\Domain\Blog\Posts as PostsInterface;
use Cocoders\Domain\Blog\Post;
use Cocoders\Domain\Blog\Exception\PostNotFound;
use Doctrine\ORM\EntityManager;
final class DoctrinePosts implements PostsInterface
{
private $manager;
public function __construct(EntityManager $manager)
{
$this->manager = $manager;
}
/**
* @throws Cocoders\Domain\Blog\Exception\PostNotFound
*/
public function get(int $postId): Post
{
$post = $this->manager->getRepository(Post::class)->find($postId);
if (!$post) {
throw PostNotFound::fromPostId($postId);
}
return $post;
}
}
<?php
declare(strict_types=1);
namespace Cocoders\Adapter\Doctrine\Application;
use Cocoders\Application\TransactionManager as TransactionManagerInterface;
use Doctrine\ORM\EntityManager;
final class DoctrineTransactionManager implements TransactionManagerInterface
{
private $manager;
public function __construct(EntityManager $manager)
{
$this->manager = $manager;
}
public function begin()
{
$this->manager->beginTransaction()
}
public function rollback()
{
$this->manager->rollback();
}
public function commit()
{
$this->manager->flush();
$this->manager->commit();
}
}
<?php
declare(strict_types=1);
namespace Cocoders\Domain\Blog;
class Post
{
private $id;
private $name;
private $tags = [];
public function __construct(int $id, string $name, array $tags = [])
{
if ($id < 1) {
throw new \InvalidArgumentException('Id is not valid');
}
if (!trim($name)) {
throw new \InvalidArgumentException('Name cannot be empty');
}
array_map(function ($tag) {
if (!$tag instanceof Tag)
{
throw new \InvalidArgumentException('All elements in $tags array needs to be Tag instance');
}
}, $tags);
$this->id = $id;
$this->name = $name;
$this->tags = $tags;
}
public function update(string $name, array $tags)
{
if (!trim($name)) {
throw new \InvalidArgumentException('Name cannot be empty');
}
array_map(function ($tag) {
if (!$tag instanceof Tag)
{
throw new \InvalidArgumentException('All elements in $tags array needs to be Tag instance');
}
}, $tags);
$removedTags = array_diff($this->tags, $tags);
$newTags = array_diff($tags, $this->tags);
$isTagsChanged = $newTags || $removedTags;
if ($isTagsChanged) {
$this->tags = $tags;
}
$this->name = $name;
}
}
<?php
declare(strict_types=1);
namespace App\Controller;
use App\Form\PostType;
use Cocoders\Application\UseCase\UpdatePost;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
class PostController extends Controller
{
/**
* @Route("/post/{id}", name="app_update_post", methods={"GET", "PUT"})
*/
public function updatePost(int $id, Request $request, UpdatePost $updatePost): Response
{
$form = $form = $this->createForm(PostType::class, $task);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$updatePost->execute(new UpdatePost\Command(
$id,
$form->get('name')->getData(),
$form->get('tagsNames')->getData()
));
return $this->redirectToRoute('app_update_post', ['id' => $id]);
}
return $this->render('post/edit.html.twig', array(
'form' => $form->createView(),
));
}
}
<?php
declare(strict_types=1);
namespace Cocoders\Domain\Blog;
interface Posts
{
/**
* @throws Cocoders\Domain\Blog\Exception\PostNotFound
*/
public function get(int $postId): Post;
}
<?php
declare(strict_types=1);
namespace Cocoders\Domain\Blog;
class Tag
{
private $name;
public function __construct(string $name)
{
$this->name = $name;
}
public function __toString(): string
{
return $this->name;
}
}
<?php
declare(strict_types=1);
namespace Cocoders\Application;
interface TransactionManager
{
public function begin();
public function rollback();
public function commit();
}
<?php
declare(strict_types=1);
namespace Cocoders\Application\UseCase;
use Cocoders\Application\TransactionManager;
use Cocoders\Domain\Blog\Posts;
use Cocoders\Domain\Blog\Tag;
final class UpdatePost
{
private $posts;
private $transactionManager;
public function __construct(TransactionManager $transactionManager, Posts $posts)
{
$this->transactionManager = $transactionManager;
$this->posts = $posts;
}
public function execute(UpdatePost\Command $command)
{
$this->transactionManager->begin();
try {
$post = $this->posts->get($command->id());
$post->update(
$command->name(),
array_map(function (string $tagName) {
return new Tag($tagName);
}, $command->tagsNames());
);
$this->transactionManager->commit();
} catch (\Throwable $e) {
$this->transactionManager->rollback();
throw $e;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment