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
28 changes: 24 additions & 4 deletions config/autoload/local.php.dist
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,36 @@

declare(strict_types=1);

$baseUrl = 'http://light.dotkernel.localhost';

$baseUrl = 'light-blog.localhost';
$databases = [
'default' => [
'host' => 'db_host',
'dbname' => 'db_name',
'user' => 'db_user',
'password' => 'db_password',
'port' => 3306,
'driver' => 'pdo_mysql',
'collate' => 'utf8mb4_general_ci',
],
];
return [
'application' => [
'url' => $baseUrl,
],
'databases' => $databases,
'doctrine' => [
'connection' => [
'orm_default' => [
'params' => $databases['default'],
],
],
],
'routes' => [
'page' => [
'about' => 'about',
'who-we-are' => 'who-we-are',
'about' => 'about',
'who-we-are' => 'who-we-are',
'contact' => 'contact',
'dotkernel-packages-oss-lifecycle' => 'dotkernel-packages-oss-lifecycle',
],
],
];
2 changes: 1 addition & 1 deletion public/css/app.css

Large diffs are not rendered by default.

7 changes: 1 addition & 6 deletions src/App/assets/scss/components/_general.scss
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,6 @@ label {
background: var(--color-bg);
}

#push,
.app-footer {
height: 115px;
}

.navbar {
margin-bottom: 0;
background-color: var(--color-surface);
Expand Down Expand Up @@ -111,7 +106,7 @@ label {

.app-footer {
padding: 30px 50px;
background: var(--color-surface);
background-color: #1c1f2b;
border-top: 1px solid var(--color-border);
}

Expand Down
6 changes: 4 additions & 2 deletions src/App/src/Factory/GetIndexViewHandlerFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Light\App\Factory;

use Light\App\Handler\GetIndexViewHandler;
use Light\Blog\Repository\PostRepository;
use Mezzio\Template\TemplateRendererInterface;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\ContainerInterface;
Expand All @@ -21,9 +22,10 @@ class GetIndexViewHandlerFactory
*/
public function __invoke(ContainerInterface $container, string $requestedName): GetIndexViewHandler
{
$template = $container->get(TemplateRendererInterface::class);
$postRepository = $container->get(PostRepository::class);
$template = $container->get(TemplateRendererInterface::class);
assert($template instanceof TemplateRendererInterface);

return new GetIndexViewHandler($template);
return new GetIndexViewHandler($template, $postRepository);
}
}
7 changes: 5 additions & 2 deletions src/App/src/Handler/GetIndexViewHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Light\App\Handler;

use Laminas\Diactoros\Response\HtmlResponse;
use Light\Blog\Repository\PostRepository;
use Mezzio\Template\TemplateRendererInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
Expand All @@ -13,14 +14,16 @@
class GetIndexViewHandler implements RequestHandlerInterface
{
public function __construct(
protected TemplateRendererInterface $template
protected TemplateRendererInterface $template,
protected PostRepository $postRepository,
) {
}

public function handle(ServerRequestInterface $request): ResponseInterface
{
$posts = $this->postRepository->getRecentPosts(3);
return new HtmlResponse(
$this->template->render('app::index')
$this->template->render('app::index', ['posts' => $posts])
);
}
}
385 changes: 378 additions & 7 deletions src/App/templates/app/index.html.twig

Large diffs are not rendered by default.

48 changes: 40 additions & 8 deletions src/App/templates/layout/default.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,46 @@
</section>
</div>
</main>
<footer class="app-footer bg-white border-top py-4 mt-auto text-muted">
<div class="container d-flex flex-column flex-md-row justify-content-between align-items-center gap-2">
<p class="enjoy text-uppercase tracking-wider small fw-bold text-primary mb-0">
enjoy dotkernel
</p>
<p class="mb-0 small">
&copy; 2024 - {{ 'now'|date('Y') }} Dotkernel by Apidemia
</p>
<footer class="app-footer border-top py-4 mt-auto text-muted">
<div class="container">
<div class="d-flex flex-column flex-md-row justify-content-between align-items-center gap-2 mb-3">
<p class="enjoy text-uppercase tracking-wider small fw-bold text-primary mb-0">
enjoy dotkernel
</p>
<p class="mb-0 small">
&copy; 2024 - {{ 'now'|date('Y') }} Dotkernel by Apidemia
</p>
</div>

<hr class="my-3">

<div class="row gy-3 align-items-center">
<div class="col-md-6">
<p class="small mb-2">
&copy; 2009 - 2016 Dotboost Technologies Inc.<br>
&copy; 2017 - {{ 'now'|date('Y') }} Apidemia Inc.<br>
The Laminas logo is copyright of the
<a href="https://getlaminas.org/about/foundation" target="_blank" rel="noopener" class="text-primary">Laminas Foundation</a>
</p>
<div class="d-flex align-items-center gap-3">
<a href="https://github.com/dotkernel" target="_blank" rel="noopener">
<img src="https://www.dotkernel.com/wp-content/uploads/2025/01/icon_git.svg" alt="GitHub" style="height: 24px; width: auto;">
</a>
<a href="https://dotkernel.slack.com/" target="_blank" rel="noopener">
<img src="https://www.dotkernel.com/wp-content/uploads/2025/01/icon_slack.svg" alt="Slack" style="height: 24px; width: auto;">
</a>
<a href="https://www.dotkernel.com/feed/" target="_blank" rel="noopener">
<img src="https://www.dotkernel.com/wp-content/uploads/2025/01/icon_feed.svg" alt="RSS Feed" style="height: 24px; width: auto;">
</a>
</div>
</div>

<div class="col-md-6 text-md-end">
<a href="https://jb.gg/OpenSourceSupport" target="_blank" rel="noopener" class="d-inline-block">
<img src="https://www.dotkernel.com/wp-content/uploads/2025/03/jetbrains-mono-white.svg" alt="JetBrains" style="width: 150px; height: auto;">
</a>
</div>
</div>
</div>
</footer>
<script src="{{ asset('js/app.js') }}"></script>
Expand Down
30 changes: 26 additions & 4 deletions src/App/templates/partial/left-menu.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
</div>
</div>
</div>
{% if data is defined %}
{% if data is defined and data is iterable %}
<div class="card border-0 shadow-sm rounded-3 my-2">
<div class="card-body p-3">
<h6 class="fw-bold text-uppercase text-muted small px-1 mb-2">Recent Articles</h6>
Expand All @@ -23,8 +23,8 @@
class="list-group-item list-group-item-action border-0 px-1 py-2 rounded">
<p class="mb-1 small fw-semibold text-dark lh-sm">{{ article.title }}</p>
<span class="text-muted" >
<i class="bi bi-calendar3 me-1"></i>{{ article.postDate|date('M d, Y') }}
</span>
<i class="bi bi-calendar3 me-1"></i>{{ article.postDate|date('M d, Y') }}
</span>
</a>
{% else %}
<p class="text-muted small mb-0">No recent articles.</p>
Expand Down Expand Up @@ -52,9 +52,31 @@
See all categories <i class="bi bi-arrow-right fs-7"></i>
</a>
</div>
</div>
</div>
{% if posts is defined and posts is iterable %}
<div class="card border-0 shadow-sm rounded-3 my-2">
<div class="card-body p-3">
<h6 class="fw-bold text-uppercase text-muted small px-1 mb-2">Recent Articles</h6>

<div class="list-group list-group-flush">

{% for post in posts %}
<a href="{{ url('page::blog-resource', {categorySlug: post.category.slug, slug: post.slug}) }}"
class="list-group-item list-group-item-action border-0 px-1 py-2 rounded">
<p class="mb-1 small fw-semibold text-dark lh-sm">{{ post.title }}</p>
<span class="text-muted">
<i class="bi bi-calendar3 me-1"></i>{{ post.postDate|date('M d, Y') }}
</span>
</a>
{% else %}
<p class="text-muted small mb-0">No recent articles.</p>
{% endfor %}

</div>
</div>
</div>
{% endif %}

</div>
</div>
</aside>
44 changes: 33 additions & 11 deletions src/Blog/src/Handler/GetCategoryResourceHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@

namespace Light\Blog\Handler;

use Fig\Http\Message\StatusCodeInterface;
use Laminas\Diactoros\Response\HtmlResponse;
use Light\Blog\Entity\Category;
use Light\Blog\Repository\CategoryRepository;
use Mezzio\Template\TemplateRendererInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Throwable;

class GetCategoryResourceHandler implements RequestHandlerInterface
{
Expand All @@ -22,21 +25,40 @@ public function __construct(
public function handle(ServerRequestInterface $request): ResponseInterface
{
$categorySlug = $request->getAttribute('slug');
$categories = $this->categoryRepository->getCategories();
$category = $this->categoryRepository->getCategoryResource($categorySlug);
$meta = $category;

if (! $category) {
return new HtmlResponse('Category not found', 404);
if ($category === null) {
return $this->notFound($categories);
}
$categories = $this->categoryRepository->getCategories();
$meta = $category;
$categoryArticles = $this->categoryRepository->getCategoryPost($category);

try {
$html = $this->template->render(
'page::category-resource',
[
'categories' => $categories,
'category' => $category,
'meta' => $meta,
'categoryArticles' => $categoryArticles,
]
);
} catch (Throwable $e) {
return $this->notFound($categories);
}
return new HtmlResponse($html);
}

/**
* @param Category[] $categories
*/
private function notFound(array $categories): HtmlResponse
{
return new HtmlResponse(
$this->template->render('page::category-resource', [
'categories' => $categories,
'category' => $category,
'meta' => $meta,
'categoryArticles' => $categoryArticles,
])
$this->template->render('error::404', [
'categories' => $categories,
]),
StatusCodeInterface::STATUS_NOT_FOUND
);
}
}
21 changes: 11 additions & 10 deletions src/Blog/src/Handler/GetPostResourceHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

namespace Light\Blog\Handler;

use Fig\Http\Message\StatusCodeInterface;
use Laminas\Diactoros\Response\HtmlResponse;
use Light\Blog\Entity\Category;
use Light\Blog\Repository\CategoryRepository;
use Light\Blog\Repository\PostRepository;
use Mezzio\Template\TemplateRendererInterface;
Expand All @@ -26,15 +28,12 @@ public function handle(ServerRequestInterface $request): ResponseInterface
{
$slug = $request->getAttribute('slug');
$categorySlug = $request->getAttribute('categorySlug');
$categories = $this->categoryRepository->getCategories();
$article = $this->articleRepository->getArticleResource($slug, $categorySlug);

if ($article === null) {
return $this->notFound($categorySlug);
return $this->notFound($categories);
}

$categories = $this->categoryRepository->getCategories();
$meta = $article;

$meta = $article;
try {
$html = $this->template->render(
'page::blog-resource/' . $article->getCategory()->getSlug() . '/' . $slug,
Expand All @@ -45,20 +44,22 @@ public function handle(ServerRequestInterface $request): ResponseInterface
]
);
} catch (Throwable $e) {
return $this->notFound($categorySlug);
return $this->notFound($categories);
}

return new HtmlResponse($html);
}

private function notFound(?string $categorySlug): HtmlResponse
/**
* @param Category[] $categories
*/
private function notFound(array $categories): HtmlResponse
{
$categories = $this->categoryRepository->getCategories();
return new HtmlResponse(
$this->template->render('error::404', [
'categories' => $categories,
]),
404
StatusCodeInterface::STATUS_NOT_FOUND
);
}
}
16 changes: 16 additions & 0 deletions src/Blog/src/Repository/PostRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,20 @@ public function getArticleByAuthor(Author $author, array $params): DoctrinePagin

return new DoctrinePaginator($qb->getQuery());
}

/**
* @return array<int, Post>
*/
public function getRecentPosts(int $limit = 5): array
{
$qb = $this->getQueryBuilder()
->select('articles')
->from(Post::class, 'articles')
->where('articles.status = :published')
->setParameter('published', PostStatusEnum::Published)
->orderBy('articles.postDate', 'DESC')
->setMaxResults($limit);

return $qb->getQuery()->getResult();
}
}
Loading