Skip to content

Commit 0ea3d58

Browse files
committed
first
1 parent b574a67 commit 0ea3d58

9 files changed

Lines changed: 195 additions & 126 deletions

File tree

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
}
2727
},
2828
"require": {
29-
"php": "~8.3.0 || ~8.4.0 || ~8.5.0",
29+
"php": "~8.5.0",
3030
"doctrine/data-fixtures": "^2.2",
3131
"doctrine/doctrine-fixtures-bundle": "^4.3",
3232
"dotkernel/dot-errorhandler": "^4.4.0",

src/App/src/RoutesDelegator.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,7 @@ public function __invoke(ContainerInterface $container, string $serviceName, cal
1616
{
1717
$app = $callback();
1818
assert($app instanceof Application);
19-
2019
$app->get('/', [GetIndexViewHandler::class], 'app::index');
21-
2220
return $app;
2321
}
2422
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,4 +130,4 @@
130130
</div>
131131
</div>
132132
</section>
133-
{% endblock %}
133+
{% endblock %}

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

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,53 @@
11
<!DOCTYPE html>
22
<html lang="en">
33
<head>
4-
4+
<meta charset="utf-8" />
55
{{ include('@partial/meta.html.twig') }}
6-
{% block canonical %}<link rel="canonical" href="{{ url(routeName ?? null) }}" />{% endblock %}
7-
<link rel="apple-touch-icon" sizes="180x180" href="{{ asset('images/app/favicon/apple-touch-icon.png') }}">
6+
{% block canonical %}<link rel="canonical" href="{{ url(routeName ?? null) }}" />
7+
{% endblock %}<link rel="apple-touch-icon" sizes="180x180" href="{{ asset('images/app/favicon/apple-touch-icon.png') }}">
88
<link rel="icon" type="image/png" sizes="32x32" href="{{ asset('images/app/favicon/favicon-32x32.png') }}">
99
<link rel="icon" type="image/png" sizes="16x16" href="{{ asset('images/app/favicon/favicon-16x16.png') }}">
1010
<link rel="manifest" href="{{ asset('images/app/favicon/site.webmanifest') }}">
1111
<link href="https://use.fontawesome.com/releases/v5.0.6/css/all.css" rel="stylesheet" />
1212
<link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,500,600" rel="stylesheet">
1313
<link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600" rel="stylesheet">
14-
1514
<link href="{{ asset('css/app.css') }}" rel="stylesheet" />
16-
17-
{% block stylesheets %}{% endblock %}
15+
{% block stylesheets %}
16+
{% endblock %}
1817
</head>
1918
<body class="app d-flex flex-column min-vh-100 bg-light text-secondary {% block body_class %}{% endblock %}">
20-
2119
<header class="app-header sticky-top bg-white border-bottom shadow-sm">
2220
<nav class="navbar navbar-expand-lg navbar-light py-2">
2321
<div class="container-fluid px-4 px-lg-5">
2422
<a href="/" class="navbar-brand d-flex align-items-center">
2523
<img src="{{ asset('images/app/logo.svg') }}"
2624
onerror="this.onerror=null; this.src='{{ asset('images/app/logo.png') }}';"
2725
alt="Dotkernel"
28-
style="height: 35px;" />
26+
style="height: 50px;" />
2927
</a>
30-
3128
<button class="navbar-toggler border-0" type="button" data-bs-toggle="collapse" data-bs-target="#navbarHeader">
3229
<span class="navbar-toggler-icon"></span>
3330
</button>
34-
3531
<div class="collapse navbar-collapse" id="navbarHeader">
3632
<ul class="navbar-nav mx-auto gap-lg-4">
3733
<li class="nav-item">
38-
<a class="nav-link px-3 fw-semibold transition-all" href="{{ url('page::blog') }}">Posts</a>
34+
<a class="nav-link px-3 fw-semibold fs-5 transition-all" target="_blank" href="https://docs.dotkernel.org/">Documentation</a>
3935
</li>
4036
<li class="nav-item">
41-
<a class="nav-link px-3 fw-semibold transition-all" href="{{ url('page::categories') }}">Categories</a>
37+
<a class="nav-link px-3 fw-semibold fs-5 transition-all" href="{{ url('page::dotkernel-packages-oss-lifecycle') }}">Packages Lifecycle</a>
4238
</li>
4339
<li class="nav-item">
44-
<a class="nav-link px-3 fw-semibold transition-all" href="{{ url('page::about') }}">About Us</a>
40+
<a class="nav-link px-3 fw-semibold fs-5 transition-all" href="{{ url('page::category-resource', {slug: 'how-to'}) }}">How to's</a>
41+
</li>
42+
<li class="nav-item">
43+
<a class="nav-link px-3 fw-semibold fs-5 transition-all" href="{{ url('page::blog') }}">Blog</a>
44+
</li>
45+
<li class="nav-item">
46+
<a class="nav-link px-3 fw-semibold fs-5 transition-all" href="{{ url('page::categories') }}">Categories</a>
4547
</li>
4648
</ul>
47-
4849
<div class="d-none d-lg-block">
49-
<a href="#" class="btn btn-primary rounded-pill px-4">Contact</a>
50+
<a href="{{ url('page::contact') }}" class="btn btn-primary rounded-pill px-4">Contact</a>
5051
</div>
5152
</div>
5253
</div>
@@ -57,13 +58,11 @@
5758
<header class="content-header mb-4">
5859
{% block page_title %}{% endblock %}
5960
</header>
60-
6161
<section class="content">
6262
{% block content %}{% endblock %}
6363
</section>
6464
</div>
6565
</main>
66-
6766
<footer class="app-footer bg-white border-top py-4 mt-auto text-muted">
6867
<div class="container d-flex flex-column flex-md-row justify-content-between align-items-center gap-2">
6968
<p class="enjoy text-uppercase tracking-wider small fw-bold text-primary mb-0">
@@ -74,7 +73,6 @@
7473
</p>
7574
</div>
7675
</footer>
77-
7876
<script src="{{ asset('js/app.js') }}"></script>
7977
{% block javascript %}{% endblock %}
8078
</body>
Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,19 @@
1-
<meta charset="utf-8" />
2-
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
3-
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
4-
<meta name="msapplication-TileColor" content="#2d89ef">
5-
<meta name="theme-color" content="#ffffff">
6-
<title>{{ meta.title ?? meta.name ?? app.meta.title }}</title>
1+
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
2+
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
3+
<meta name="msapplication-TileColor" content="#2d89ef">
4+
<meta name="theme-color" content="#ffffff">
5+
<title>{{ meta.title ?? meta.name ?? app.meta.title }}</title>
6+
<meta name="description" content="{{ (meta.description ?? meta.excerpt ?? app.meta.description)|slice(0, 155) }}"/>
7+
<meta property="og:title" content="{{ meta.title ?? app.meta.title }}"/>
8+
<meta property="og:description" content="{{ (meta.description ?? meta.excerpt ?? app.meta.description)|slice(0, 120) }}"/>
9+
<meta property="og:image" content="{{ meta.image ?? app.meta.image }}"/>
10+
<meta property="og:type" content="{{ meta.type ?? app.meta.type }}"/>
11+
<meta property="og:site_name" content="{{ app.meta.siteName }}"/>
12+
<meta property="og:url" content="{{ meta.url ?? app.meta.url }}"/>
13+
<meta property="og:locale" content="{{ app.meta.locale }}"/>
714

8-
<meta name="description" content="{{ (meta.description ?? meta.excerpt ?? app.meta.description)|slice(0, 155) }}"/>
9-
<meta property="og:title" content="{{ meta.title ?? app.meta.title }}"/>
10-
<meta property="og:description" content="{{ (meta.description ?? meta.excerpt ?? app.meta.description)|slice(0, 120) }}"/>
11-
<meta property="og:image" content="{{ meta.image ?? app.meta.image }}"/>
12-
<meta property="og:type" content="{{ meta.type ?? app.meta.type }}"/>
13-
<meta property="og:site_name" content="{{ app.meta.siteName }}"/>
14-
<meta property="og:url" content="{{ meta.url ?? app.meta.url }}"/>
15-
<meta property="og:locale" content="{{ app.meta.locale }}"/>
16-
17-
<meta name="twitter:card" content="{{ app.meta.twitterCard }}"/>
18-
<meta name="twitter:site" content="{{ app.meta.twitterSite }}"/>
19-
<meta name="twitter:title" content="{{ meta.title ?? meta.name ?? app.meta.title }}"/>
20-
<meta name="twitter:description" content="{{ (meta.description ?? meta.excerpt ?? app.meta.description)|slice(0, 155) }}"/>
21-
<meta name="twitter:image" content="{{ meta.image ?? app.meta.image }}"/>
15+
<meta name="twitter:card" content="{{ app.meta.twitterCard }}"/>
16+
<meta name="twitter:site" content="{{ app.meta.twitterSite }}"/>
17+
<meta name="twitter:title" content="{{ meta.title ?? meta.name ?? app.meta.title }}"/>
18+
<meta name="twitter:description" content="{{ (meta.description ?? meta.excerpt ?? app.meta.description)|slice(0, 155) }}"/>
19+
<meta name="twitter:image" content="{{ meta.image ?? app.meta.image }}"/>

src/Blog/src/RoutesDelegator.php

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

55
namespace Light\Blog;
66

7+
use Laminas\Diactoros\Response\RedirectResponse;
78
use Light\Blog\Handler\GetAuthorResourceHandler;
89
use Light\Blog\Handler\GetCategoryCollectionHandler;
910
use Light\Blog\Handler\GetCategoryResourceHandler;
@@ -20,11 +21,37 @@ public function __invoke(ContainerInterface $container, string $serviceName, cal
2021
{
2122
$app = $callback();
2223
assert($app instanceof Application);
23-
$app->get('/blog', [GetPostCollectionHandler::class], 'page::blog');
24-
$app->get('/category/{slug}', [GetCategoryResourceHandler::class], 'page::category-resource');
25-
$app->get('/categories', [GetCategoryCollectionHandler::class], 'page::categories');
26-
$app->get('/author/{slug}', [GetAuthorResourceHandler::class], 'page::author-resource');
27-
$app->get('/{categorySlug}/{slug}', [GetPostResourceHandler::class], 'page::blog-resource');
24+
25+
$app->get('/blog/', [GetPostCollectionHandler::class], 'page::blog');
26+
$app->get('/blog', function ($request) {
27+
$uri = $request->getUri();
28+
return new RedirectResponse((string) $uri . '/', 301);
29+
});
30+
31+
$app->get('/category/{slug}/', [GetCategoryResourceHandler::class], 'page::category-resource');
32+
$app->get('/category/{slug}', function ($request) {
33+
$uri = $request->getUri();
34+
return new RedirectResponse((string) $uri . '/', 301);
35+
});
36+
37+
$app->get('/categories/', [GetCategoryCollectionHandler::class], 'page::categories');
38+
$app->get('/categories', function ($request) {
39+
$uri = $request->getUri();
40+
return new RedirectResponse((string) $uri . '/', 301);
41+
});
42+
43+
$app->get('/author/{slug}/', [GetAuthorResourceHandler::class], 'page::author-resource');
44+
$app->get('/author/{slug}', function ($request) {
45+
$uri = $request->getUri();
46+
return new RedirectResponse((string) $uri . '/', 301);
47+
});
48+
49+
$app->get('/{categorySlug}/{slug}/', [GetPostResourceHandler::class], 'page::blog-resource');
50+
$app->get('/{categorySlug}/{slug}', function ($request) {
51+
$uri = $request->getUri();
52+
return new RedirectResponse((string) $uri . '/', 301);
53+
});
54+
2855
return $app;
2956
}
3057
}

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

Lines changed: 69 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -3,88 +3,78 @@
33
{% block title %}Posts{% endblock %}
44

55
{% block content %}
6-
<header class="mb-4 pb-3 border-bottom">
7-
<span class="text-uppercase text-muted small fw-bold d-block mb-1">Blog</span>
8-
<h1 class="display-6 fw-bold text-dark mb-0">Latest Articles</h1>
9-
</header>
10-
<div class="row g-4 py-4">
11-
12-
{{ include('@partial/left-menu.html.twig') }}
13-
14-
<main class="col-lg-9 col-md-8">
15-
<div class="posts d-flex flex-column gap-3">
16-
{% for article in data.items %}
17-
<article class="card border-0 shadow-sm rounded-3">
18-
<div class="card-body p-4">
19-
<div class="mb-3">
20-
<a href="{{ url('page::category-resource', {slug: article.category.slug}) }}"
21-
class="badge bg-primary-subtle text-primary text-uppercase fw-bold text-decoration-none px-3 py-2 rounded-pill">
22-
{{ article.category.name }}
23-
</a>
24-
</div>
25-
26-
<h2 class="h5 fw-bold mb-2">
27-
<a href="{{ url('page::blog-resource', {categorySlug: article.category.slug, slug: article.slug}) }}" class="link-dark text-decoration-none">
28-
{{ article.title }}
29-
</a>
30-
</h2>
31-
32-
<p class="text-muted small mb-3">{{ article.excerpt }}</p>
33-
34-
<div class="d-flex flex-wrap align-items-center justify-content-between gap-2 pt-3 border-top">
35-
<span class="text-muted small">
36-
By <a href="{{ path('page::author-resource', {slug: article.author.slug}) }}" class="fw-bold link-dark text-decoration-none">{{ article.author.name }}</a>
37-
&nbsp;·&nbsp; {{ article.postDate|date('M d, Y') }}
38-
</span>
39-
40-
<a href="{{ url('page::blog-resource', {categorySlug: article.category.slug, slug: article.slug}) }}"
41-
class="btn btn-outline-primary btn-sm rounded-pill px-3">
42-
Read more <i class="bi bi-arrow-right ms-1"></i>
43-
</a>
44-
</div>
6+
<header class="mb-4 pb-3 border-bottom">
7+
<span class="text-uppercase text-muted small fw-bold d-block mb-1">Blog</span>
8+
<h1 class="display-6 fw-bold text-dark mb-0">Latest Articles</h1>
9+
</header>
10+
<div class="row g-4 py-4">
11+
{{ include('@partial/left-menu.html.twig') }}
12+
<main class="col-lg-9 col-md-8">
13+
<div class="posts d-flex flex-column gap-3">
14+
{% for article in data.items %}
15+
<article class="card border-0 shadow-sm rounded-3">
16+
<div class="card-body p-4">
17+
<div class="mb-3">
18+
<a href="{{ url('page::category-resource', {slug: article.category.slug}) }}"
19+
class="badge bg-primary-subtle text-primary text-uppercase fw-bold text-decoration-none px-3 py-2 rounded-pill">
20+
{{ article.category.name }}
21+
</a>
4522
</div>
46-
</article>
47-
{% else %}
48-
<div class="text-center py-5 bg-white rounded-3 border shadow-sm">
49-
<i class="bi bi-newspaper display-4 text-muted d-block mb-3"></i>
50-
<p class="text-muted mb-0">No articles found.</p>
51-
</div>
52-
{% endfor %}
53-
</div>
54-
55-
{% if data.lastPage > 1 %}
56-
<nav class="mt-4 d-flex justify-content-center">
57-
<ul class="pagination pagination-sm">
5823

59-
<li class="page-item {% if data.isFirstPage %}disabled{% endif %}">
60-
<a class="page-link rounded-start-3" href="?page={{ data.previousPage }}">
61-
<i class="fas fa-chevron-left"></i>
24+
<h2 class="h5 fw-bold mb-2">
25+
<a href="{{ url('page::blog-resource', {categorySlug: article.category.slug, slug: article.slug}) }}" class="link-dark text-decoration-none">
26+
{{ article.title }}
6227
</a>
63-
</li>
64-
65-
{% for p in data.pages %}
66-
<li class="page-item {% if p == data.currentPage %}active{% endif %}">
67-
<a class="page-link" href="?page={{ p }}">{{ p }}</a>
68-
</li>
69-
{% endfor %}
70-
71-
<li class="page-item {% if data.isLastPage %}disabled{% endif %}">
72-
<a class="page-link rounded-end-3" href="?page={{ data.nextPage }}">
73-
<i class="fas fa-chevron-right"></i>
28+
</h2>
29+
<p class="text-muted small mb-3">{{ article.excerpt }}</p>
30+
<div class="d-flex flex-wrap align-items-center justify-content-between gap-2 pt-3 border-top">
31+
<span class="text-muted small">
32+
By <a href="{{ path('page::author-resource', {slug: article.author.slug}) }}" class="fw-bold link-dark text-decoration-none">{{ article.author.name }}</a>
33+
&nbsp;·&nbsp; {{ article.postDate|date('M d, Y') }}
34+
</span>
35+
36+
<a href="{{ url('page::blog-resource', {categorySlug: article.category.slug, slug: article.slug}) }}"
37+
class="btn btn-outline-primary btn-sm rounded-pill px-3">
38+
Read more <i class="bi bi-arrow-right ms-1"></i>
7439
</a>
40+
</div>
41+
</div>
42+
</article>
43+
{% else %}
44+
<div class="text-center py-5 bg-white rounded-3 border shadow-sm">
45+
<i class="bi bi-newspaper display-4 text-muted d-block mb-3"></i>
46+
<p class="text-muted mb-0">No articles found.</p>
47+
</div>
48+
{% endfor %}
49+
</div>
50+
{% if data.lastPage > 1 %}
51+
<nav class="mt-4 d-flex justify-content-center">
52+
<ul class="pagination pagination-sm">
53+
<li class="page-item {% if data.isFirstPage %}disabled{% endif %}">
54+
<a class="page-link rounded-start-3" href="?page={{ data.previousPage }}">
55+
<i class="fas fa-chevron-left"></i>
56+
</a>
57+
</li>
58+
59+
{% for p in data.pages %}
60+
<li class="page-item {% if p == data.currentPage %}active{% endif %}">
61+
<a class="page-link" href="?page={{ p }}">{{ p }}</a>
7562
</li>
76-
77-
</ul>
78-
</nav>
79-
80-
<p class="text-center text-muted small mt-2">
81-
Page {{ data.currentPage }} of {{ data.lastPage }}
82-
&nbsp;·&nbsp;
83-
{{ data.count }} articles total
84-
</p>
85-
{% endif %}
86-
87-
</main>
88-
89-
</div>
63+
{% endfor %}
64+
65+
<li class="page-item {% if data.isLastPage %}disabled{% endif %}">
66+
<a class="page-link rounded-end-3" href="?page={{ data.nextPage }}">
67+
<i class="fas fa-chevron-right"></i>
68+
</a>
69+
</li>
70+
</ul>
71+
</nav>
72+
<p class="text-center text-muted small mt-2">
73+
Page {{ data.currentPage }} of {{ data.lastPage }}
74+
&nbsp;·&nbsp;
75+
{{ data.count }} articles total
76+
</p>
77+
{% endif %}
78+
</main>
79+
</div>
9080
{% endblock %}

0 commit comments

Comments
 (0)