Skip to content

Commit 0e4bddf

Browse files
committed
Remove Claude markers and resolve html errors. Add pagination to category page. New style for blog/category pages.
1 parent 0f23403 commit 0e4bddf

173 files changed

Lines changed: 395 additions & 347 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

public/css/app.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/App/assets/scss/components/_blog.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// ============================================================
2-
// Blog post page styles extracted & converted to SCSS
2+
// Blog post page styles - extracted & converted to SCSS
33
// Relies on the global CSS custom properties (--bg, --text, etc.)
44
// defined in :root / [data-theme="light"].
55
// ============================================================

src/App/assets/scss/components/_custom.scss

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -813,6 +813,11 @@ details.acc {
813813
gap: 20px;
814814
}
815815

816+
.posts-grid-2-col {
817+
display: grid;
818+
grid-template-columns: repeat(2, 1fr);
819+
gap: 20px;
820+
}
816821
.post-card {
817822
background: var(--surface);
818823
border: 1px solid var(--border);

src/App/templates/app/index.html.twig

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77
<section class="hero">
88
<div class="wrap hero-grid">
99
<div>
10-
<span class="eyebrow">PSR-15 · middleware-first architecture</span>
10+
<span class="eyebrow">PSR-15 . middleware-first architecture</span>
1111
<h1>A headless platform for building modern web applications</h1>
12-
<p class="sub">Dotkernel is a collection of open-source application skeletons built on Mezzio and Laminas pre-configured and ready for anything from a presentation site to an enterprise-grade API.</p>
12+
<p class="sub">Dotkernel is a collection of open-source application skeletons built on Mezzio and Laminas - pre-configured and ready for anything from a presentation site to an enterprise-grade API.</p>
1313
<div class="hero-ctas">
1414
<a class="btn btn-primary" href="https://docs.dotkernel.org" target="_blank" rel="noopener">
1515
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/></svg>
@@ -22,7 +22,7 @@
2222
</div>
2323
<div class="hero-stack-note">
2424
<div><span>Runtime</span> Mezzio + Laminas</div>
25-
<div><span>Standards</span> PSR-7 · PSR-11 · PSR-15</div>
25+
<div><span>Standards</span> PSR-7 . PSR-11 . PSR-15</div>
2626
<div><span>License</span> BSD-3-Clause</div>
2727
</div>
2828
</div>
@@ -87,7 +87,7 @@
8787
<div class="section-head">
8888
<span class="eyebrow">Headless Platform</span>
8989
<h2>Three applications, one platform</h2>
90-
<p>API, Admin, and Queue are designed to integrate into a single, unified headless platform better together than the sum of their parts.</p>
90+
<p>API, Admin, and Queue are designed to integrate into a single, unified headless platform - better together than the sum of their parts.</p>
9191
</div>
9292

9393
<div class="products-grid">
@@ -120,7 +120,7 @@
120120
<img alt="License" src="https://img.shields.io/github/license/dotkernel/admin?style=flat&label=&color=D6D2CC">
121121
<img alt="Stars" src="https://img.shields.io/github/stars/dotkernel/admin?style=flat&label=%E2%98%85&color=D6D2CC">
122122
</div>
123-
<p class="desc">A ready-to-go admin skeleton for managing your platform's records with a simple, table-based approach plus the tools to build reports and dashboards.</p>
123+
<p class="desc">A ready-to-go admin skeleton for managing your platform's records with a simple, table-based approach - plus the tools to build reports and dashboards.</p>
124124
<div class="card-btns">
125125
<a class="btn btn-ghost btn-sm" href="https://github.com/dotkernel/admin" target="_blank" rel="noopener">GitHub</a>
126126
<a class="btn btn-ghost btn-sm" href="https://admin7.dotkernel.net/" target="_blank" rel="noopener">Demo</a>
@@ -161,15 +161,15 @@
161161

162162
<div class="card" style="--accent:var(--rose)">
163163
<div class="card-top">
164-
<div><span class="kicker">Skeleton · Didactic</span><h3>Light</h3></div>
164+
<div><span class="kicker">Skeleton . Didactic</span><h3>Light</h3></div>
165165
</div>
166166
<div class="badges">
167167
<img alt="PHP" src="https://img.shields.io/packagist/php-v/dotkernel/light?style=flat&label=php&color=F6D6DA">
168168
<img alt="Packagist" src="https://img.shields.io/packagist/v/dotkernel/light?style=flat&label=&color=F6D6DA">
169169
<img alt="License" src="https://img.shields.io/github/license/dotkernel/light?style=flat&label=&color=F6D6DA">
170170
<img alt="Stars" src="https://img.shields.io/github/stars/dotkernel/light?style=flat&label=%E2%98%85&color=F6D6DA">
171171
</div>
172-
<p class="desc">A minimal, PSR-15 compliant skeleton built for learning purposes a simple, didactic example of how to put together a basic website, not a Headless Platform component.</p>
172+
<p class="desc">A minimal, PSR-15 compliant skeleton built for learning purposes - a simple, didactic example of how to put together a basic website, not a Headless Platform component.</p>
173173
<div class="card-btns">
174174
<a class="btn btn-ghost btn-sm" href="https://github.com/dotkernel/light" target="_blank" rel="noopener">GitHub</a>
175175
<a class="btn btn-ghost btn-sm" href="https://light.dotkernel.net/" target="_blank" rel="noopener">Demo</a>
@@ -179,15 +179,15 @@
179179

180180
<div class="card" style="--accent:var(--sage)">
181181
<div class="card-top">
182-
<div><span class="kicker">Skeleton · Standalone</span><h3>Frontend</h3></div>
182+
<div><span class="kicker">Skeleton . Standalone</span><h3>Frontend</h3></div>
183183
</div>
184184
<div class="badges">
185185
<img alt="PHP" src="https://img.shields.io/packagist/php-v/dotkernel/frontend?style=flat&label=php&color=E39AA8">
186186
<img alt="Packagist" src="https://img.shields.io/packagist/v/dotkernel/frontend?style=flat&label=&color=E39AA8">
187187
<img alt="License" src="https://img.shields.io/github/license/dotkernel/frontend?style=flat&label=&color=E39AA8">
188188
<img alt="Stars" src="https://img.shields.io/github/stars/dotkernel/frontend?style=flat&label=%E2%98%85&color=E39AA8">
189189
</div>
190-
<p class="desc">A web starter skeleton for building frontend applications on Mezzio and Laminas a standalone alternative, separate from the Headless Platform.</p>
190+
<p class="desc">A web starter skeleton for building frontend applications on Mezzio and Laminas - a standalone alternative, separate from the Headless Platform.</p>
191191
<div class="card-btns">
192192
<a class="btn btn-ghost btn-sm" href="https://github.com/dotkernel/frontend" target="_blank" rel="noopener">GitHub</a>
193193
<a class="btn btn-ghost btn-sm" href="https://v5.dotkernel.net/" target="_blank" rel="noopener">Demo</a>
@@ -204,7 +204,7 @@
204204
<div class="section-head">
205205
<span class="eyebrow">Components</span>
206206
<h2>Every layer, on its own</h2>
207-
<p>Small, independent dot-* packages pull in what you need. Lifecycle status for each lives on the <a href="https://www.dotkernel.com/dotkernel-packages-oss-lifecycle/" style="color:var(--teal);">Packages Lifecycle</a> page.</p>
207+
<p>Small, independent dot-* packages - pull in what you need. Lifecycle status for each lives on the <a href="https://www.dotkernel.com/dotkernel-packages-oss-lifecycle/" style="color:var(--teal);">Packages Lifecycle</a> page.</p>
208208
</div>
209209
<div class="components-grid">
210210
<div>
@@ -331,7 +331,7 @@
331331
<h2>Control, scalability &amp; performance you can build on.</h2>
332332
</div>
333333
<div>
334-
<p class="about-text">Dotkernel is an open-source project created and led by the dev team at Apidemia built first as an internal tool for handling complex architectures, now freely shared as our way of giving back to the community.</p>
334+
<p class="about-text">Dotkernel is an open-source project created and led by the dev team at Apidemia - built first as an internal tool for handling complex architectures, now freely shared as our way of giving back to the community.</p>
335335
<div class="about-cta">
336336
<a class="btn btn-ghost" href="{{ url('page::contact') }}">See more about us →</a>
337337
</div>

src/App/templates/layout/default.html.twig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@
9696
<img class="icon icon-jetbrains mt-1" src="{{ asset('images/app/icon/jetbrains-mono.svg') }}" alt="JetBrains">
9797
</a>
9898
</span>
99-
<span class="sponsor">Built with Mezzio, Laminas &amp; Doctrine for PHP developers, by PHP developers.</span>
99+
<span class="sponsor">Built with Mezzio, Laminas &amp; Doctrine - for PHP developers, by PHP developers.</span>
100100
</div>
101101
</div>
102102
</footer>

src/Blog/src/Handler/GetCategoryResourceHandler.php

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use Fig\Http\Message\StatusCodeInterface;
88
use Laminas\Diactoros\Response\HtmlResponse;
9+
use Light\App\Helper\Paginator;
910
use Light\Blog\Entity\Category;
1011
use Light\Blog\Repository\CategoryRepository;
1112
use Mezzio\Template\TemplateRendererInterface;
@@ -30,17 +31,23 @@ public function handle(ServerRequestInterface $request): ResponseInterface
3031
if ($category === null) {
3132
return $this->notFound($categories);
3233
}
33-
$meta = $category;
34-
$categoryArticles = $this->categoryRepository->getCategoryPost($category);
34+
$meta = $category;
35+
36+
$queryParams = $request->getQueryParams();
37+
$params = Paginator::getParams($queryParams, 'articles.id');
38+
$data = Paginator::wrapper(
39+
$this->categoryRepository->getCategoryPost($category, $params),
40+
$params
41+
);
3542

3643
try {
3744
$html = $this->template->render(
3845
'page::category-resource',
3946
[
40-
'categories' => $categories,
41-
'category' => $category,
42-
'meta' => $meta,
43-
'categoryArticles' => $categoryArticles,
47+
'categories' => $categories,
48+
'category' => $category,
49+
'meta' => $meta,
50+
'data' => $data,
4451
]
4552
);
4653
return new HtmlResponse($html);

src/Blog/src/Repository/CategoryRepository.php

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace Light\Blog\Repository;
66

7+
use Doctrine\ORM\Tools\Pagination\Paginator as DoctrinePaginator;
78
use Light\App\Repository\AbstractRepository;
89
use Light\Blog\Entity\Category;
910
use Light\Blog\Entity\Post;
@@ -37,19 +38,22 @@ public function getCategoryResource(string $slug): ?Category
3738
}
3839

3940
/**
40-
* @return array<Post>
41+
* @param array<string, mixed> $params
42+
* @return DoctrinePaginator<Post>
4143
*/
42-
public function getCategoryPost(Category $category): array
44+
public function getCategoryPost(Category $category, array $params): DoctrinePaginator
4345
{
4446
$qb = $this->getQueryBuilder()
4547
->select('articles')
4648
->from(Post::class, 'articles')
4749
->where('articles.category = :category')
4850
->andWhere('articles.status = :published')
49-
->orderBy('articles.postDate', 'DESC')
51+
->setParameter('category', $category)
5052
->setParameter('published', PostStatusEnum::Published)
51-
->setParameter('category', $category);
53+
->orderBy('articles.postDate', $params['dir'])
54+
->setFirstResult($params['offset'])
55+
->setMaxResults($params['limit']);
5256

53-
return $qb->getQuery()->getResult();
57+
return new DoctrinePaginator($qb->getQuery());
5458
}
5559
}

src/Blog/templates/page/author-resource.html.twig

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -31,26 +31,21 @@
3131
{{ include('@partial/left-menu.html.twig') }}
3232

3333
<main class="article">
34-
<div class="posts-list">
34+
<div class="posts-grid-2-col">
3535
{% for post in data.items %}
36-
<article class="card my-3">
37-
<h3>
38-
<a href="{{ url('page::blog-resource', {categorySlug: post.category.slug, slug: post.slug}) }}">
39-
{{ post.title }}
40-
</a>
41-
</h3>
42-
43-
<p class="desc">{{ post.excerpt }}</p>
44-
45-
<div class="card-btns">
46-
<span class="post-date">{{ post.postDate|date('Y-m-d') }}</span>
47-
48-
<a href="{{ url('page::blog-resource', {categorySlug: post.category.slug, slug: post.slug}) }}"
49-
class="btn btn-ghost btn-sm">
50-
Read more →
51-
</a>
52-
</div>
53-
</article>
36+
<a class="post-card"
37+
href="{{ url('page::blog-resource', {categorySlug: post.category.slug, slug: post.slug}) }}">
38+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"
39+
style="width:20px;height:20px;color:var(--teal);" aria-hidden="true">
40+
<path d="M4 4h11l5 5v11a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1z"/>
41+
<path d="M14 4v6h6"/>
42+
</svg>
43+
<span class="post-card-kicker">{{ post.category.name }}</span>
44+
<h4>{{ post.title }}</h4>
45+
<p>{{ post.excerpt|length > 200 ? post.excerpt|slice(0, 200)|trim ~ '' : post.excerpt }}</p>
46+
<span class="post-card-meta">{{ post.postDate|date('M d, Y') }}</span>
47+
<span class="read-more">Read more →</span>
48+
</a>
5449
{% else %}
5550
<div class="card posts-empty">
5651
<p class="desc">No posts found.</p>
@@ -59,7 +54,7 @@
5954
</div>
6055

6156
{% if data.lastPage > 1 %}
62-
<nav class="pagination-row" aria-label="Author posts pagination">
57+
<nav class="pagination-row mt-3" aria-label="Author posts pagination">
6358
<a class="btn btn-ghost btn-sm {% if data.isFirstPage %}disabled{% endif %}"
6459
href="?page={{ data.previousPage }}" aria-label="Previous page">←</a>
6560

@@ -74,7 +69,7 @@
7469

7570
<p class="post-date pagination-summary">
7671
Page {{ data.currentPage }} of {{ data.lastPage }}
77-
&nbsp;·&nbsp; {{ data.count }} articles total
72+
&nbsp;.&nbsp; {{ data.count }} articles total
7873
</p>
7974
{% endif %}
8075
</main>

src/Blog/templates/page/blog-resource/android/listen-for-android-install-referrer.html.twig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
<div class="post-meta">
1515
<span class="text-muted small">
1616
By <a href="{{ path('page::author-resource', {slug: article.author.slug}) }}" class="fw-bold link-dark text-decoration-none">{{ article.author.name }}</a>
17-
&nbsp;·&nbsp; {{ article.postDate|date('M d, Y') }}
17+
&nbsp;.&nbsp; {{ article.postDate|date('M d, Y') }}
1818
</span>
1919
</div>
2020
</div>

src/Blog/templates/page/blog-resource/android/multiple-broadcast-receivers-in-the-same-app-for-the-same-action.html.twig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
<div class="post-meta">
1515
<span class="text-muted small">
1616
By <a href="{{ path('page::author-resource', {slug: article.author.slug}) }}" class="fw-bold link-dark text-decoration-none">{{ article.author.name }}</a>
17-
&nbsp;·&nbsp; {{ article.postDate|date('M d, Y') }}
17+
&nbsp;.&nbsp; {{ article.postDate|date('M d, Y') }}
1818
</span>
1919
</div>
2020
</div>

0 commit comments

Comments
 (0)