Skip to content

Commit b6b05c1

Browse files
author
olaru
committed
Migration postDate and status
1 parent 45b7bce commit b6b05c1

8 files changed

Lines changed: 193 additions & 11 deletions

File tree

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Light\App\DBAL\Types;
6+
7+
use BackedEnum;
8+
use Doctrine\DBAL\Platforms\AbstractPlatform;
9+
use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
10+
use Doctrine\DBAL\Platforms\SQLitePlatform;
11+
use Doctrine\DBAL\Types\Type;
12+
13+
use function array_map;
14+
use function implode;
15+
use function sprintf;
16+
17+
abstract class AbstractEnumType extends Type
18+
{
19+
public function getSQLDeclaration(array $column, AbstractPlatform $platform): string
20+
{
21+
if ($platform instanceof PostgreSQLPlatform) {
22+
return $this->getName();
23+
}
24+
25+
if ($platform instanceof SQLitePlatform) {
26+
return 'TEXT';
27+
}
28+
29+
$values = array_map(fn($case) => "'$case->value'", $this->getEnumCases());
30+
31+
return sprintf('ENUM(%s)', implode(', ', $values));
32+
}
33+
34+
public function convertToPHPValue(mixed $value, AbstractPlatform $platform): mixed
35+
{
36+
return $this->getValue($value);
37+
}
38+
39+
public function convertToDatabaseValue(mixed $value, AbstractPlatform $platform): mixed
40+
{
41+
return $this->getValue($value);
42+
}
43+
44+
/**
45+
* @return class-string
46+
*/
47+
abstract public function getEnumClass(): string;
48+
49+
/**
50+
* @return non-empty-string
51+
*/
52+
abstract public function getName(): string;
53+
54+
/**
55+
* @return BackedEnum[]
56+
*/
57+
public function getEnumCases(): array
58+
{
59+
return $this->getEnumClass()::cases();
60+
}
61+
62+
/**
63+
* @return list<non-empty-string>
64+
*/
65+
public function getEnumValues(): array
66+
{
67+
return $this->getEnumClass()::values();
68+
}
69+
70+
public function getValue(mixed $value): mixed
71+
{
72+
if (! $value instanceof BackedEnum) {
73+
return $value;
74+
}
75+
76+
return $value->value;
77+
}
78+
}

src/App/src/Fixture/CategoriesLoader.php

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,29 @@ class CategoriesLoader extends Fixture
1313
public function load(ObjectManager $manager): void
1414
{
1515
$categories = [
16-
['name' => 'Architecture', 'slug' => 'architecture'],
17-
['name' => 'Best Practice', 'slug' => 'best-practice'],
18-
['name' => 'Dotkernel', 'slug' => 'dotkernel'],
19-
['name' => 'Dotkernel API', 'slug' => 'dotkernel-api'],
20-
['name' => 'Middleware', 'slug' => 'middleware'],
21-
['name' => 'Headless Platform', 'slug' => 'headless-platform'],
22-
['name' => 'How to', 'slug' => 'how-to'],
23-
['name' => 'Design Patterns', 'slug' => 'design-pattern'],
24-
['name' => 'PHP Development', 'slug' => 'php-development'],
16+
['name' => 'Uncategorized', 'slug' => 'uncategorized'],
17+
['name' => 'Dotkernel', 'slug' => 'dotkernel'],
18+
['name' => 'Javascript', 'slug' => 'javascript'],
19+
['name' => 'Zend Framework', 'slug' => 'zend-framework'],
20+
['name' => 'PHP Development', 'slug' => 'php-development'],
21+
['name' => 'How to', 'slug' => 'how-to'],
22+
['name' => 'PHP Troubleshooting', 'slug' => 'php-troubleshooting'],
23+
['name' => 'Dotkernel 3', 'slug' => 'dotkernel3'],
24+
['name' => 'Middleware', 'slug' => 'middleware'],
25+
['name' => 'Zend Expressive', 'slug' => 'zend-expressive'],
26+
['name' => 'Best Practice', 'slug' => 'best-practice'],
27+
['name' => 'Version Control', 'slug' => 'version-control'],
28+
['name' => 'Android', 'slug' => 'android'],
29+
['name' => 'ZCE Tips', 'slug' => 'zce-tips'],
30+
['name' => 'Documentation News', 'slug' => 'documentation-news'],
31+
['name' => 'Dotkernel API', 'slug' => 'dotkernel-api'],
32+
['name' => 'Laminas', 'slug' => 'laminas'],
33+
['name' => 'PHPStorm', 'slug' => 'phpstorm'],
34+
['name' => 'Licensing', 'slug' => 'licensing'],
35+
['name' => 'Doctrine', 'slug' => 'doctrine'],
36+
['name' => 'Architecture', 'slug' => 'architecture'],
37+
['name' => 'Design Patterns', 'slug' => 'design-pattern'],
38+
['name' => 'Headless Platform', 'slug' => 'headless-platform'],
2539
];
2640

2741
foreach ($categories as $data) {

src/Blog/src/ConfigProvider.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace Light\Blog;
66

77
use Doctrine\ORM\Mapping\Driver\AttributeDriver;
8+
use Light\Blog\DBAL\Types\ArticleStatusEnumType;
89
use Light\Blog\Factory\Articles\ArticleCollectionHandlerFactory;
910
use Light\Blog\Factory\Articles\ArticleCollectionRepositoryFactory;
1011
use Light\Blog\Factory\Articles\ArticleResourceHandlerFactory;
@@ -64,6 +65,7 @@ private function getDependencies(): array
6465
/**
6566
@return array{
6667
* driver: array<mixed>,
68+
* types: array<mixed>,
6769
* }
6870
*/
6971
private function getDoctrineConfig(): array
@@ -81,6 +83,9 @@ private function getDoctrineConfig(): array
8183
'paths' => [__DIR__ . '/Entity'],
8284
],
8385
],
86+
'types' => [
87+
ArticleStatusEnumType::NAME => ArticleStatusEnumType::class,
88+
],
8489
];
8590
}
8691

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Light\Blog\DBAL\Types;
6+
7+
use Light\App\DBAL\Types\AbstractEnumType;
8+
use Light\Blog\Enum\ArticleStatusEnum;
9+
10+
class ArticleStatusEnumType extends AbstractEnumType
11+
{
12+
public const NAME = 'status';
13+
14+
public function getEnumClass(): string
15+
{
16+
return ArticleStatusEnum::class;
17+
}
18+
19+
public function getName(): string
20+
{
21+
return self::NAME;
22+
}
23+
}

src/Blog/src/Entity/Article.php

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44

55
namespace Light\Blog\Entity;
66

7+
use DateTimeImmutable;
78
use Doctrine\ORM\Mapping as ORM;
89
use Light\App\Entity\AbstractEntity;
10+
use Light\Blog\Enum\ArticleStatusEnum;
911
use Light\Blog\Repository\ArticleRepository;
1012

1113
#[ORM\Entity(repositoryClass: ArticleRepository::class)]
@@ -19,6 +21,17 @@ class Article extends AbstractEntity
1921
#[ORM\Column(name: 'slug', type: 'string', length: 500, unique: true)]
2022
private string $slug;
2123

24+
#[ORM\Column(name: 'post_date', type: 'datetime_immutable', nullable: true)]
25+
private string $postDate;
26+
27+
#[ORM\Column(
28+
name: 'status',
29+
type: 'article_status_enum',
30+
enumType: ArticleStatusEnum::class,
31+
options: ['default' => ArticleStatusEnum::Published]
32+
)]
33+
private ArticleStatusEnum $status;
34+
2235
#[ORM\ManyToOne(targetEntity: Category::class)]
2336
#[ORM\JoinColumn(name: 'category_id', referencedColumnName: 'id', nullable: false)]
2437
private Category $category;
@@ -47,6 +60,26 @@ public function setSlug(string $slug): void
4760
$this->slug = $slug;
4861
}
4962

63+
public function getPostDate(): string
64+
{
65+
return $this->postDate;
66+
}
67+
68+
public function setPostDate(string $postDate): void
69+
{
70+
$this->postDate = $postDate;
71+
}
72+
73+
public function getStatus(): ArticleStatusEnum
74+
{
75+
return $this->status;
76+
}
77+
78+
public function setStatus(ArticleStatusEnum $status): void
79+
{
80+
$this->status = $status;
81+
}
82+
5083
public function getCategory(): Category
5184
{
5285
return $this->category;
@@ -72,6 +105,8 @@ public function setAuthor(Author $author): void
72105
* id: non-empty-string,
73106
* title: string,
74107
* slug: string,
108+
* status: string,
109+
* postDate: string,
75110
* category: array{id: non-empty-string, name: string, slug: string},
76111
* author: array{id: non-empty-string, name: string, slug: string, bio: string|null}
77112
* }
@@ -82,6 +117,8 @@ public function getArrayCopy(): array
82117
'id' => $this->id->toString(),
83118
'title' => $this->title,
84119
'slug' => $this->slug,
120+
'status' => $this->status->value,
121+
'postDate' => $this->postDate,
85122
'category' => $this->category->getArrayCopy(),
86123
'author' => $this->author->getArrayCopy(),
87124
];
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Light\Blog\Enum;
6+
7+
use function array_column;
8+
9+
enum ArticleStatusEnum: string
10+
{
11+
case Draft = 'draft';
12+
case Published = 'published';
13+
case Private = 'private';
14+
15+
/**
16+
* @return non-empty-string[]
17+
*/
18+
public static function values(): array
19+
{
20+
return array_column(self::cases(), 'value');
21+
}
22+
}

src/Blog/src/Handler/GetArticleCollectionHandler.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
use Psr\Http\Message\ServerRequestInterface;
1313
use Psr\Http\Server\RequestHandlerInterface;
1414

15+
use function var_dump;
16+
1517
class GetArticleCollectionHandler implements RequestHandlerInterface
1618
{
1719
public function __construct(
@@ -23,7 +25,7 @@ public function __construct(
2325

2426
public function handle(ServerRequestInterface $request): ResponseInterface
2527
{
26-
$articles = $this->articleRepository->getArticles();
28+
$articles = $this->articleRepository->getArticles();
2729
$categories = $this->categoryRepository->getCategories();
2830
return new HtmlResponse(
2931
$this->template->render('page::blog', [

src/Blog/templates/page/blog.html.twig

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
{{ article.title }}
6363
</a>
6464
</h2>
65+
{# <p class="text-muted small mb-0">Post date {{ article.postDate }}"></p>#}
6566
</div>
6667

6768
<div class="d-flex flex-wrap align-items-center justify-content-between gap-2 mt-2 pt-3 border-top">
@@ -70,7 +71,7 @@
7071
<i class="bi bi-tags me-1"></i> Related posts
7172
</a>
7273

73-
<a href="/blog/{{ article.slug }}" class="text-primary small fw-bold text-decoration-none d-inline-flex align-items-center gap-1">
74+
<a href="{{ url('page::blog-resource', {slug: article.slug}) }}" class="text-primary small fw-bold text-decoration-none d-inline-flex align-items-center gap-1">
7475
Read more <i class="bi bi-arrow-right"></i>
7576
</a>
7677
</div>

0 commit comments

Comments
 (0)