Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions public/app/edit.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

use Solid\App\BlogPost\Application\UseCase\EditBlogPostUseCase;
use Solid\App\BlogPost\Domain\Model\BlogPostNormalizer;
use Solid\App\BlogPost\Infrastructure\Persistence\FileStorage;
use Solid\App\BlogPost\Presentation\Controller\EditAction;
use Solid\App\BlogPost\Presentation\Renderer\HtmlRenderer;
use Solid\App\BlogPost\Presentation\Renderer\JsonRenderer;
use Solid\App\BlogPost\Presentation\Renderer\RenderContainer;

require __DIR__.'/../../vendor/autoload.php';

$normalizer = new BlogPostNormalizer();
$storage = new FileStorage($normalizer, __DIR__.'/../../var/data/blog_post.dat');
$useCase = new EditBlogPostUseCase($storage);
$renderContainer = new RenderContainer([
'html' => new HtmlRenderer(),
'json' => new JsonRenderer($normalizer),
]);
$format = $_GET['format'] ?? 'html';

$action = new EditAction($useCase, $renderContainer->get($format));
$action((int) ($_GET['id'] ?? 0), $_GET['author'] ?? null, $_GET['title'] ?? null, $_GET['content'] ?? null, $format);
25 changes: 25 additions & 0 deletions public/app/list.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

use Solid\App\BlogPost\Application\UseCase\ListBlogPostUseCase;
use Solid\App\BlogPost\Domain\Model\BlogPostNormalizer;
use Solid\App\BlogPost\Infrastructure\Persistence\FileStorage;
use Solid\App\BlogPost\Presentation\Controller\ListAction;
use Solid\App\BlogPost\Presentation\Renderer\HtmlRenderer;
use Solid\App\BlogPost\Presentation\Renderer\JsonRenderer;
use Solid\App\BlogPost\Presentation\Renderer\RenderContainer;

require __DIR__.'/../../vendor/autoload.php';

$normalizer = new BlogPostNormalizer();
$storage = new FileStorage($normalizer, __DIR__.'/../../var/data/blog_post.dat');
$useCase = new ListBlogPostUseCase($storage);
$renderContainer = new RenderContainer([
'html' => new HtmlRenderer(),
'json' => new JsonRenderer($normalizer),
]);
$format = $_GET['format'] ?? 'html';

$action = new ListAction($useCase, $renderContainer->get($format));
$action($format);
25 changes: 25 additions & 0 deletions public/app/new.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

use Solid\App\BlogPost\Application\UseCase\NewBlogPostUseCase;
use Solid\App\BlogPost\Domain\Model\BlogPostNormalizer;
use Solid\App\BlogPost\Infrastructure\Persistence\FileStorage;
use Solid\App\BlogPost\Presentation\Controller\NewAction;
use Solid\App\BlogPost\Presentation\Renderer\HtmlRenderer;
use Solid\App\BlogPost\Presentation\Renderer\JsonRenderer;
use Solid\App\BlogPost\Presentation\Renderer\RenderContainer;

require __DIR__.'/../../vendor/autoload.php';

$normalizer = new BlogPostNormalizer();
$storage = new FileStorage($normalizer, __DIR__.'/../../var/data/blog_post.dat');
$useCase = new NewBlogPostUseCase($storage);
$renderContainer = new RenderContainer([
'html' => new HtmlRenderer(),
'json' => new JsonRenderer($normalizer),
]);
$format = $_GET['format'] ?? 'html';

$action = new NewAction($useCase, $renderContainer->get($format));
$action(random_int(0, 999999), $_GET['author'] ?? null, $_GET['title'] ?? null, $_GET['content'] ?? null, $format);
25 changes: 25 additions & 0 deletions public/app/show.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

use Solid\App\BlogPost\Application\UseCase\FindBlogPostUseCase;
use Solid\App\BlogPost\Domain\Model\BlogPostNormalizer;
use Solid\App\BlogPost\Infrastructure\Persistence\FileStorage;
use Solid\App\BlogPost\Presentation\Controller\ShowAction;
use Solid\App\BlogPost\Presentation\Renderer\HtmlRenderer;
use Solid\App\BlogPost\Presentation\Renderer\JsonRenderer;
use Solid\App\BlogPost\Presentation\Renderer\RenderContainer;

require __DIR__.'/../../vendor/autoload.php';

$normalizer = new BlogPostNormalizer();
$storage = new FileStorage($normalizer, __DIR__.'/../../var/data/blog_post.dat');
$useCase = new FindBlogPostUseCase($storage);
$renderContainer = new RenderContainer([
'html' => new HtmlRenderer(),
'json' => new JsonRenderer($normalizer),
]);
$format = $_GET['format'] ?? 'html';

$action = new ShowAction($useCase, $renderContainer->get($format));
$action((int) ($_GET['id'] ?? 0), $format);
29 changes: 29 additions & 0 deletions src/App/BlogPost/Application/UseCase/EditBlogPostUseCase.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

namespace Solid\App\BlogPost\Application\UseCase;

use Solid\App\BlogPost\Domain\Model\BlogPost;
use Solid\App\BlogPost\Domain\Model\Storage;

final class EditBlogPostUseCase
{
public function __construct(
private readonly Storage $storage,
private readonly RandomWords $rand = new RandomWords(),
) {
}

public function execute(int $id, ?string $author, ?string $title, ?string $content): BlogPost
{
$blogPost = $this->storage->get($id);
$blogPost->update(
$author ?? $this->rand->get('s'),
$title ?? $this->rand->get('m'),
$content ?? $this->rand->get('l')
);
$this->storage->save($blogPost);

return $blogPost;
}

}
18 changes: 18 additions & 0 deletions src/App/BlogPost/Application/UseCase/FindBlogPostUseCase.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace Solid\App\BlogPost\Application\UseCase;

use Solid\App\BlogPost\Domain\Model\BlogPost;
use Solid\App\BlogPost\Domain\Model\Storage;

final class FindBlogPostUseCase
{
public function __construct(private readonly Storage $storage)
{
}

public function execute(int $id): BlogPost
{
return $this->storage->get($id);
}
}
17 changes: 17 additions & 0 deletions src/App/BlogPost/Application/UseCase/ListBlogPostUseCase.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

namespace Solid\App\BlogPost\Application\UseCase;

use Solid\App\BlogPost\Domain\Model\Storage;

final class ListBlogPostUseCase
{
public function __construct(private readonly Storage $storage)
{
}

public function execute(): iterable
{
return $this->storage->getAll();
}
}
28 changes: 28 additions & 0 deletions src/App/BlogPost/Application/UseCase/NewBlogPostUseCase.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace Solid\App\BlogPost\Application\UseCase;

use Solid\App\BlogPost\Domain\Model\BlogPost;
use Solid\App\BlogPost\Domain\Model\Storage;

final class NewBlogPostUseCase
{
public function __construct(
private readonly Storage $storage,
private readonly RandomWords $rand = new RandomWords(),
) {
}

public function execute(int $id, ?string $author, ?string $title, ?string $content): BlogPost
{
$blogPost = new BlogPost(
$id,
$author ?? $this->rand->get('s'),
$title ?? $this->rand->get('m'),
$content ?? $this->rand->get('l'),
);
$this->storage->save($blogPost);

return $blogPost;
}
}
30 changes: 30 additions & 0 deletions src/App/BlogPost/Application/UseCase/RandomWords.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace Solid\App\BlogPost\Application\UseCase;

final class RandomWords
{
public function get(string $size): string
{
$times = match ($size) {
's' => 2,
'm' => 3,
'l' => 10,
};
$string = '';
for ($i = 0; $i < $times; ++$i) {
$string .= $this->randWord().' ';
}

return trim($string);
}

private function randWord(): string
{
$word = array_merge(range('a', 'z'), range('A', 'Z'));
shuffle($word);
$length = random_int(7, 12);

return substr(implode($word), 0, $length);
}
}
62 changes: 62 additions & 0 deletions src/App/BlogPost/Domain/Model/BlogPost.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

namespace Solid\App\BlogPost\Domain\Model;

use DateTimeImmutable;

final class BlogPost
{
private DateTimeImmutable $createdAt;
private ?DateTimeImmutable $updatedAt = null;

public function __construct(
private int $id,
private string $author,
private string $title,
private string $content,
) {
$this->createdAt = new DateTimeImmutable();
}

public function update(
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$blogPost->update(content: 'new content');

vs

$blogPost->changeContent('new content');

[SRP] It looks simple but in my opinion, is not a good thing when your logic starts growing or you have to do something specific for each value (like domain validations).

?string $author = null,
?string $title = null,
?string $content = null,
): void {
$this->author = $author ?? $this->author;
$this->title = $title ?? $this->title;
$this->content = $content ?? $this->content;
$this->updatedAt = new DateTimeImmutable();
}

public function getId(): int
{
return $this->id;
}

public function getAuthor(): string
{
return $this->author;
}

public function getTitle(): string
{
return $this->title;
}

public function getContent(): string
{
return $this->content;
}

public function getCreatedAt(): DateTimeImmutable
{
return $this->createdAt;
}

public function getUpdatedAt(): ?DateTimeImmutable
{
return $this->updatedAt;
}
}

40 changes: 40 additions & 0 deletions src/App/BlogPost/Domain/Model/BlogPostNormalizer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

namespace Solid\App\BlogPost\Domain\Model;

use DateTimeImmutable;

final class BlogPostNormalizer implements Normalizer
{
public function normalize(BlogPost $blogPost): array
{
return [
'id' => $blogPost->getId(),
'author' => $blogPost->getAuthor(),
'title' => $blogPost->getTitle(),
'content' => $blogPost->getContent(),
'created_at' => $blogPost->getCreatedAt()->format('Y-m-d H:i:s'),
'updated_at' => $blogPost->getUpdatedAt()?->format('Y-m-d H:i:s'),
];
}

public function denormalize(array $data): BlogPost
{
$blogPost = new BlogPost($data['id'], $data['author'], $data['title'], $data['content']);
$this->setTimestampProperties($blogPost, $data['created_at'], $data['updated_at']);

return $blogPost;
}

private function setTimestampProperties(BlogPost $blogPost, string $created, ?string $updated): void
{
$createdAt = new \ReflectionProperty($blogPost, 'createdAt');
$createdAt->setAccessible(true);
$createdAt->setValue($blogPost, new DateTimeImmutable($created));
if (null !== $updated) {
$updatedAt = new \ReflectionProperty($blogPost, 'updatedAt');
$updatedAt->setAccessible(true);
$updatedAt->setValue($blogPost, new DateTimeImmutable($updated));
}
}
}
18 changes: 18 additions & 0 deletions src/App/BlogPost/Domain/Model/Normalizer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace Solid\App\BlogPost\Domain\Model;

use DateTimeImmutable;

interface Normalizer
{
/**
* @return array{id: int, title: string, content: string, author: string, createdAt: DateTimeImmutable, updatedAt: ?DateTimeImmutable}
*/
public function normalize(BlogPost $blogPost): array;

/**
* @param array{id: int, title: string, content: string, author: string, createdAt: DateTimeImmutable, updatedAt: ?DateTimeImmutable} $data
*/
public function denormalize(array $data): BlogPost;
}
15 changes: 15 additions & 0 deletions src/App/BlogPost/Domain/Model/Storage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

namespace Solid\App\BlogPost\Domain\Model;

interface Storage
{
public function get(int $id): BlogPost;

/**
* @return iterable<int, BlogPost>
*/
public function getAll(): iterable;

public function save(BlogPost $blogPost): void;
}
Loading