Skip to content

Commit 638f717

Browse files
author
Bjorn Van Acker
authored
Merge pull request #139 from sumocoders/page-title-service
Add page title service to generate pagetitle based on the breadcrumbs
2 parents 1f2e2f4 + 6b1d3bf commit 638f717

File tree

9 files changed

+425
-44
lines changed

9 files changed

+425
-44
lines changed

config/services.php

Lines changed: 68 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
use SumoCoders\FrameworkCoreBundle\Command\SecretsGetCommand;
66
use SumoCoders\FrameworkCoreBundle\Command\TranslateCommand;
7+
use SumoCoders\FrameworkCoreBundle\EventListener\TitleListener;
8+
use SumoCoders\FrameworkCoreBundle\Service\PageTitle;
79
use SumoCoders\FrameworkCoreBundle\Twig\ContentExtension;
810
use Symfony\Component\Form\Extension\Core\Type\TimeType;
911
use SumoCoders\FrameworkCoreBundle\Service\Fallbacks;
@@ -40,71 +42,71 @@
4042
* Services
4143
*/
4244
->set('framework.fallbacks', Fallbacks::class)
43-
->args([
44-
param('fallbacks')
45-
])
45+
->args([
46+
param('fallbacks')
47+
])
4648

4749
/*
4850
* Menu
4951
*/
5052
->set('framework.menu_builder', MenuBuilder::class)
51-
->args([
52-
service('knp_menu.factory'),
53-
service('event_dispatcher')
54-
])
55-
->tag('knp_menu.menu_builder', ['method' => 'createMainMenu', 'alias' => 'side_menu'])
53+
->args([
54+
service('knp_menu.factory'),
55+
service('event_dispatcher')
56+
])
57+
->tag('knp_menu.menu_builder', ['method' => 'createMainMenu', 'alias' => 'side_menu'])
5658

5759
/*
5860
* Forms
5961
*/
6062
->set('framework.date_type_extension', DateTypeExtension::class)
61-
->tag('form.type_extension', ['extended_type' => DateType::class])
63+
->tag('form.type_extension', ['extended_type' => DateType::class])
6264

6365
->set('framework.time_type_extension', TimeTypeExtension::class)
64-
->tag('form.type_extension', ['extended_type' => TimeType::class])
66+
->tag('form.type_extension', ['extended_type' => TimeType::class])
6567

6668
->set('framework.date_time_type_extension', DateTimeTypeExtension::class)
67-
->tag('form.type_extension', ['extended_type' => DateTimeType::class])
69+
->tag('form.type_extension', ['extended_type' => DateTimeType::class])
6870

6971
->set('framework.birthday_type_extension', BirthdayTypeExtension::class)
70-
->tag('form.type_extension', ['extended_type' => BirthdayType::class])
72+
->tag('form.type_extension', ['extended_type' => BirthdayType::class])
7173

7274
->set('framework.collection_type_extension', CollectionTypeExtension::class)
73-
->tag('form.type_extension', ['extended_type' => CollectionType::class])
75+
->tag('form.type_extension', ['extended_type' => CollectionType::class])
7476

7577
->set('framework.image_type', ImageType::class)
76-
->tag('form.type', ['alias' => 'image'])
78+
->tag('form.type', ['alias' => 'image'])
7779

7880
->set('framework.file_type', FileType::class)
79-
->tag('form.type', ['alias' => 'sumoFile'])
81+
->tag('form.type', ['alias' => 'sumoFile'])
8082

8183
/*
8284
* Secure headers
8385
*/
8486
->set('framework.response_securer', ResponseSecurer::class)
85-
->args([
86-
param('kernel.debug'),
87-
param('sumo_coders_framework_core.content_security_policy'),
88-
param('sumo_coders_framework_core.extra_content_security_policy'),
89-
param('sumo_coders_framework_core.x_frame_options'),
90-
param('sumo_coders_framework_core.x_content_type_options'),
91-
])
92-
->tag('kernel.event_listener', ['event' => 'kernel.response', 'method' => 'onKernelResponse'])
87+
->args([
88+
param('kernel.debug'),
89+
param('sumo_coders_framework_core.content_security_policy'),
90+
param('sumo_coders_framework_core.extra_content_security_policy'),
91+
param('sumo_coders_framework_core.x_frame_options'),
92+
param('sumo_coders_framework_core.x_content_type_options'),
93+
])
94+
->tag('kernel.event_listener', ['event' => 'kernel.response', 'method' => 'onKernelResponse'])
9395

9496
/*
9597
* Twig extensions
9698
*/
9799
->set('framework.framework_extension', FrameworkExtension::class)
98-
->tag('twig.extension')
100+
->tag('twig.extension')
99101

100102
->set('framework.paginator_extension', PaginatorExtension::class)
101-
->tag('twig.extension')
103+
->tag('twig.extension')
102104

103105
->set('framework.paginator_runtime', PaginatorRuntime::class)
104-
->tag('twig.runtime')
106+
->tag('twig.runtime')
105107

106108
->set('framework.content_extension', ContentExtension::class)
107-
->tag('twig.extension')
109+
->tag('twig.extension')
108110

109111
/*
110112
* Breadcrumbs
@@ -113,24 +115,50 @@
113115
->alias(BreadcrumbTrail::class, 'framework.breadcrumb_trail')
114116

115117
->set('framework.breadcrumb_listener', BreadcrumbListener::class)
116-
->tag(
117-
'kernel.event_listener',
118-
[
119-
'event' => 'kernel.controller',
120-
'method' => 'onKernelController',
121-
'priority' => -1
122-
]
123-
)
118+
->tag(
119+
'kernel.event_listener',
120+
[
121+
'event' => 'kernel.controller',
122+
'method' => 'onKernelController',
123+
'priority' => -1
124+
]
125+
)
126+
127+
->set('framework.title_listener', TitleListener::class)
128+
->args([
129+
service('framework.page_title'),
130+
service('framework.fallbacks'),
131+
service('router')
132+
])
133+
->tag(
134+
'kernel.event_listener',
135+
[
136+
'event' => 'kernel.controller',
137+
'method' => 'onKernelController',
138+
'priority' => -1
139+
]
140+
)
141+
142+
/*
143+
* Page title
144+
*/
145+
->set('framework.page_title', PageTitle::class)
146+
->args([
147+
service('framework.breadcrumb_trail'),
148+
service('framework.fallbacks'),
149+
service('translator')
150+
])
151+
->alias(PageTitle::class, 'framework.page_title')
124152

125153
/*
126154
* Commands
127155
*/
128156
->set(TranslateCommand::class)
129-
->tag('console.command')
157+
->tag('console.command')
130158

131159
->set(SecretsGetCommand::class)
132-
->args([
133-
service('secrets.vault')
134-
])
135-
->tag('console.command');
160+
->args([
161+
service('secrets.vault')
162+
])
163+
->tag('console.command');
136164
};

docs/development/title.md

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# The page title
2+
By default no page title should be set. This is because by default the `fallback.site_title` is used. This is a configuration value that can be set in the `services.yaml` file.
3+
In case there are breadcrumbs configured, the reverse order of the breadcrumbs will be used as the page title.
4+
5+
## The `Title` attribute
6+
7+
The `Title` attribute is a custom attribute used in the framework. It is used to set the title of a page dynamically based on the controller method that is being executed. Here's a step-by-step guide on how to use it:
8+
9+
1. Import the `Title` attribute at the top of your controller file:
10+
11+
```php
12+
use SumoCoders\FrameworkCoreBundle\Attribute\Title;
13+
```
14+
15+
2. Apply the `Title` attribute to a controller method. The `Title` attribute takes a string as its first argument, which is the title you want to set for the page when this method is executed.
16+
17+
```php
18+
#[Title('My Page Title')]
19+
public function myMethod()
20+
{
21+
// Your code here
22+
}
23+
```
24+
25+
3. If you want the title to be extended with the parent's title, you can pass a second argument to the `Title` attribute. This argument should be an array with a `name` key that corresponds to the route name of the parent.
26+
27+
```php
28+
#[Title('My Page Title', ['name' => 'parent_route'])]
29+
public function myMethod()
30+
{
31+
// Your code here
32+
}
33+
```
34+
35+
4. If you want to prevent the title from being extended with the parent's title, you can pass a third argument to the `Title` attribute. This argument should be a boolean that indicates whether the title should be extended (`true`) or not (`false`).
36+
37+
```php
38+
#[Title('My Page Title', ['name' => 'parent_route'], false)]
39+
public function myMethod()
40+
{
41+
// Your code here
42+
}
43+
```
44+
45+
5. The `Title` attribute can also handle dynamic titles. If you want to include a parameter in the title, you can do so by including it in curly braces `{}` in the title string. The parameter should be available in the request attributes.
46+
47+
```php
48+
#[Title('My Page Title for {id}')]
49+
public function myMethod($id)
50+
{
51+
// Your code here
52+
}
53+
```
54+
55+
6. The `TitleListener` class will automatically handle the `Title` attribute. It listens to the kernel controller event, fetches the `Title` attribute from the controller method being executed, and sets the page title accordingly.
56+
57+
Remember to clear the Symfony cache after adding or changing attributes, as Symfony compiles and caches the attributes when the cache is built. You can clear the cache by running `bin/console cache:clear` in your terminal.

src/Attribute/Title.php

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?php
2+
3+
namespace SumoCoders\FrameworkCoreBundle\Attribute;
4+
5+
use Attribute;
6+
use SumoCoders\FrameworkCoreBundle\ValueObject\Route;
7+
8+
#[Attribute(Attribute::TARGET_METHOD)]
9+
final class Title
10+
{
11+
private string $title;
12+
private ?Route $parent;
13+
14+
private bool $extend = true;
15+
16+
public function __construct(
17+
string $title,
18+
?array $parent = null,
19+
$extend = true,
20+
) {
21+
$this->title = $title;
22+
23+
if ($parent !== null) {
24+
$this->parent = new Route(
25+
$parent['name'],
26+
\array_key_exists('parameters', $parent) ? $parent['parameters'] : null
27+
);
28+
} else {
29+
$this->parent = $parent;
30+
}
31+
}
32+
33+
public function getTitle(): ?string
34+
{
35+
return $this->title;
36+
}
37+
38+
public function isExtend(): bool
39+
{
40+
return $this->extend;
41+
}
42+
43+
public function hasParent(): bool
44+
{
45+
return $this->parent !== null;
46+
}
47+
48+
public function getParent(): ?Route
49+
{
50+
return $this->parent;
51+
}
52+
}

0 commit comments

Comments
 (0)