Skip to content
Merged
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
16 changes: 12 additions & 4 deletions config/autoload/local.php.dist
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,20 @@ return [
],
],
'contact' => [
'notification_receivers' => [],
'message_receivers' => [
'to' => [
'subject' => 'Dotkernel Contact',
'message_sender' => [
'from_name' => '',
'from_email' => '',
],
'message_recipients' => [
'name' => 'Dotkernel Team',
'to' => [
'[email protected]',
],
'cc' => [
'[email protected]',
],
'cc' => [
'bcc' => [
'[email protected]',
],
],
Expand Down
169 changes: 169 additions & 0 deletions config/autoload/navigation.global.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
<?php

declare(strict_types=1);

return [
'dot_navigation' => [
//enable menu item active if any child is active
'active_recursion' => true,
'containers' => [
'left_menu' => [
'type' => 'ArrayProvider',
'options' => [
'items' => [
[
'options' => [
'label' => 'Pages',
'route' => [],
],
'attributes' => [
'class' => 'nav-link dropdown-toggle',
'href' => '#',
],
'pages' => [
[
'options' => [
'label' => 'Home',
'uri' => '/home',
],
'attributes' => [
'class' => 'dropdown-item',
],
],
[
'options' => [
'label' => 'About Us',
'uri' => '/page/about-us',
],
'attributes' => [
'class' => 'dropdown-item',
],
],
[
'options' => [
'label' => 'Who We Are',
'uri' => '/page/who-we-are',
],
'attributes' => [
'class' => 'dropdown-item',
],
],
[
'options' => [
'label' => 'Premium content',
'uri' => '/page/premium-content',
],
'attributes' => [
'class' => 'dropdown-item',
],
],
],
],
[
'options' => [
'label' => 'Contribute',
'uri' => 'https://github.com/dotkernel',
],
'attributes' => [
'class' => 'nav-link',
'target' => '_blank',
],
],
[
'options' => [
'label' => 'Contact Us',
'uri' => '/contact/form',
],
'attributes' => [
'class' => 'nav-link',
],
],
[
'options' => [
'label' => 'Disabled',
'uri' => '/',
],
'attributes' => [
'class' => 'nav-link disabled',
],
],
],
],
],
'guest_menu' => [
'type' => 'ArrayProvider',
'options' => [
'items' => [
[
'options' => [
'label' => 'Log in',
'uri' => '/user/login',
],
'attributes' => [
'class' => 'nav-link',
],
],
],
],
],
'user_menu' => [
'type' => 'ArrayProvider',
'options' => [
'items' => [
[
'options' => [
'label' => 'Profile',
'uri' => '/account/details',
],
'attributes' => [
'class' => 'nav-link',
],
],
[
'options' => [
'label' => 'Log out',
'uri' => '/user/logout',
],
'attributes' => [
'class' => 'nav-link',
],
],
],
],
],
'user_profile_menu' => [
'type' => 'ArrayProvider',
'options' => [
'items' => [
[
'options' => [
'label' => 'Avatar',
'uri' => '/account/avatar',
],
],
[
'options' => [
'label' => 'Details',
'uri' => '/account/details',
],
],
[
'options' => [
'label' => 'Change password',
'uri' => '/account/change-password',
],
],
[
'options' => [
'label' => 'Delete account',
'uri' => '/account/delete-account',
],
],
],
],
],
],
//register custom providers here
'provider_manager' => [],
],
];
4 changes: 3 additions & 1 deletion config/autoload/templates.global.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
declare(strict_types=1);

use Dot\Twig\Extension\DateExtension;
use Frontend\App\Twig\Extension\RouteExtension;
use Laminas\ServiceManager\Factory\InvokableFactory;
use Mezzio\Template\TemplateRendererInterface;
use Mezzio\Twig\TwigEnvironmentFactory;
Expand All @@ -29,12 +30,13 @@
'cache_dir' => 'data/cache/twig',
'extensions' => [
DateExtension::class,
RouteExtension::class,
],
'optimizations' => -1,
'runtime_loaders' => [],
//'timezone' => '',
'globals' => [
'appName' => $app['name'],
'appName' => $app['name'] ?? '',
],
],
];
2 changes: 2 additions & 0 deletions config/config.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ class_exists(\Mezzio\Swoole\ConfigProvider::class)
\Dot\ResponseHeader\ConfigProvider::class,
\Dot\DataFixtures\ConfigProvider::class,
\Dot\Cache\ConfigProvider::class,
\Dot\Helpers\ConfigProvider::class,
\Dot\Navigation\ConfigProvider::class,

// Default App module config
\Frontend\App\ConfigProvider::class,
Expand Down
2 changes: 2 additions & 0 deletions config/pipeline.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
declare(strict_types=1);

use Dot\ErrorHandler\ErrorHandlerInterface;
use Dot\Navigation\NavigationMiddleware;
use Dot\Rbac\Guard\Middleware\ForbiddenHandler;
use Dot\Rbac\Guard\Middleware\RbacGuardMiddleware;
use Dot\ResponseHeader\Middleware\ResponseHeaderMiddleware;
Expand Down Expand Up @@ -77,6 +78,7 @@
$app->pipe(AuthMiddleware::class);
$app->pipe(ForbiddenHandler::class);
$app->pipe(RbacGuardMiddleware::class);
$app->pipe(NavigationMiddleware::class);

// Register the dispatch middleware in the middleware pipeline
$app->pipe(DispatchMiddleware::class);
Expand Down
1 change: 1 addition & 0 deletions src/App/src/ConfigProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public function getDependencies(): array
RecaptchaService::class => AttributedServiceFactory::class,
CookieService::class => AttributedServiceFactory::class,
RememberMeMiddleware::class => AttributedServiceFactory::class,
Twig\Extension\RouteExtension::class => AttributedServiceFactory::class,
],
'aliases' => [
EntityManager::class => 'doctrine.entity_manager.orm_default',
Expand Down
46 changes: 46 additions & 0 deletions src/App/src/Twig/Extension/RouteExtension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

declare(strict_types=1);

namespace Frontend\App\Twig\Extension;

use Dot\DependencyInjection\Attribute\Inject;
use Mezzio\Helper\UrlHelper;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;

class RouteExtension extends AbstractExtension
{
#[Inject(UrlHelper::class)]
public function __construct(
private readonly UrlHelper $urlHelper,
) {
}

public function getFunctions(): array
{
return [
new TwigFunction('getCurrentRoute', [$this, 'getCurrentRoute']),
new TwigFunction('isRoute', [$this, 'isRoute']),
];
}

public function getCurrentRoute(): ?string
{
return $this->urlHelper->getRequest()?->getUri()?->getPath();
}

public function isRoute(?string $route): bool
{
if (null === $route) {
return false;
}

$currentRoute = $this->getCurrentRoute();
if (null === $currentRoute) {
return false;
}

return $currentRoute === $route;
}
}
31 changes: 4 additions & 27 deletions src/App/templates/layout/default.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -42,37 +42,14 @@

<div class="collapse navbar-collapse" id="navbarHeader">
<ul class="navbar-nav mr-auto">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="pageDropdown" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Pages</a>
<div class="dropdown-menu" aria-labelledby="pageDropdown">
<a class="dropdown-item" href="{{ url('page', {action: 'home'}) }}">Home</a>
<a class="dropdown-item" href="{{ url('page', {action: 'about-us'}) }}">About Us</a>
<a class="dropdown-item" href="{{ url('page', {action: 'who-we-are'}) }}">Who We Are</a>
<a class="dropdown-item" href="{{ url('page', {action: 'premium-content'}) }}">Protected Content</a>
</div>
</li>
<li class="nav-item">
<a class="nav-link" href="https://github.com/dotkernel" target="_blank">Contribute</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ url('contact', {action: 'form'}) }}">Contact Us</a>
</li>
<li class="nav-item">
<a class="nav-link disabled" href="{{ url('page', {action: 'index'}) }}">Disabled</a>
</li>
{{ navigationPartial('left_menu', 'partial::menu') }}
</ul>

<ul class="navbar-nav ms-auto">
{% if hasIdentity() %}
<li class="nav-item">
<a class="nav-link" href="{{ url('account', {action: 'details'}) }}">Profile</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ url('user', {action: 'logout'}) }}">Log out</a>
</li>
{{ navigationPartial('user_menu', 'partial::menu') }}
{% else %}
<li class="nav-item">
<a class="nav-link" href="{{ url('user', {action: 'login'}) }}">Log in</a>
</li>
{{ navigationPartial('guest_menu', 'partial::menu') }}
{% endif %}
</ul>
</div>
Expand Down
27 changes: 27 additions & 0 deletions src/App/templates/partial/menu.html.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{% set extraAttributes = '' %}
{% if page is defined %}
<ul class="navbar-nav mr-auto">
{% endif %}
{% for page in container %}
{% if navigation.isAllowed(page) %}
{% if page.hasChildren() %}
<li class="nav-item dropdown">
<a {% autoescape false %}{{ pageAttributes(page) ~ extraAttributes }}{% endautoescape %} id="pageDropdown" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">{{ page.getOption('label') }}</a>
<div class="dropdown-menu" aria-labelledby="pageDropdown">
{{ navigationPartial(page, 'partial::menu') }}
</div>
</li>
{% else %}
{% if page.hasParent() %}
<a {% autoescape false %}{{ pageAttributes(page) ~ extraAttributes }}{% endautoescape %} href="{{ navigation.getHref(page) }}" {% autoescape false %}{{ pageAttributes(page) ~ extraAttributes }}{% endautoescape %}>{{ page.getOption('label') }}</a>
{% else %}
<li class="nav-item">
<a {% autoescape false %}{{ pageAttributes(page) ~ extraAttributes }}{% endautoescape %} href="{{ navigation.getHref(page) }}" {% autoescape false %}{{ pageAttributes(page) ~ extraAttributes }}{% endautoescape %}>{{ page.getOption('label') }}</a>
</li>
{% endif %}
{% endif %}
{% endif %}
{% endfor %}
{% if page is defined %}
</ul>
{% endif %}
8 changes: 8 additions & 0 deletions src/App/templates/partial/user_profile_menu.html.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{% set extraAttributes = '' %}
{% for page in container %}
{% if navigation.isAllowed(page) %}
<li class="{% if isRoute(page.getOption('uri')) %}active{% endif %}">
<a href="{{ navigation.getHref(page) }}" class="text-decoration-none" {% autoescape false %}{{ pageAttributes(page) ~ extraAttributes }}{% endautoescape %}>{{ page.getOption('label') }}</a>
</li>
{% endif %}
{% endfor %}
2 changes: 1 addition & 1 deletion src/Contact/src/Controller/ContactController.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public function formAction(): ResponseInterface
$this->messenger->addError('Missing recaptcha');
return new RedirectResponse($request->getUri(), 303);
}
$data['subject'] = $data['subject'] ?: $this->config['application']['name'] . ' Contact';

$form->setData($data);
if ($form->isValid()) {
/** @var array $dataForm */
Expand Down
Loading