- Documentation >
- Templating >
- Templates >
- Create custom view matcher
Create custom view matcher
In addition to the built-in view matchers,
you can also create custom matchers to use in template configuration.
To do it, create a matcher class that implements Ibexa\Core\MVC\Symfony\Matcher\ContentBased\MatcherInterface
.
Matcher class
The matcher class must implement the following methods:
matchLocation
- checks if a Location object matches.
matchContentInfo
- checks if a ContentInfo object matches.
match
- checks if the View object matches.
setMatchingConfig
- receives the matcher's config from the view rule.
The following example shows how to implement an Owner
matcher.
This matcher identifies content items that have the provided owner or owners.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79 | <?php declare(strict_types=1);
namespace App\View\Matcher;
use Ibexa\Contracts\Core\Repository\UserService;
use Ibexa\Contracts\Core\Repository\Values\Content\ContentInfo;
use Ibexa\Contracts\Core\Repository\Values\Content\Location;
use Ibexa\Core\MVC\Symfony\Matcher\ContentBased\MatcherInterface;
use Ibexa\Core\MVC\Symfony\View\ContentValueView;
use Ibexa\Core\MVC\Symfony\View\LocationValueView;
use Ibexa\Core\MVC\Symfony\View\View;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
class Owner implements MatcherInterface
{
private UserService $userService;
/** @var string[] */
private array $matchingUserLogins;
public function __construct(UserService $userService)
{
$this->userService = $userService;
}
/**
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException
*/
public function matchLocation(Location $location): bool
{
return $this->hasOwner($location->getContentInfo());
}
/**
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException
*/
public function matchContentInfo(ContentInfo $contentInfo): bool
{
return $this->hasOwner($contentInfo);
}
/**
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException
*/
public function match(View $view): ?bool
{
if ($view instanceof LocationValueView) {
return $this->matchLocation($view->getLocation());
}
if ($view instanceof ContentValueView) {
return $this->matchContentInfo($view->getContent()->contentInfo);
}
return false;
}
/**
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException
*/
private function hasOwner(ContentInfo $contentInfo): bool
{
$owner = $this->userService->loadUser($contentInfo->ownerId);
return in_array($owner->login, $this->matchingUserLogins, true);
}
/**
* @param array<string> $matchingConfig
*/
public function setMatchingConfig($matchingConfig): void
{
if (!is_array($matchingConfig)) {
throw new InvalidArgumentException('App\Owner view matcher configuration has to be an array');
}
$this->matchingUserLogins = $matchingConfig;
}
}
|
The matcher checks whether the owner of the current content (by its ContentInfo or Location)
matches any of the values passed in configuration.
Matcher service
You configure your matcher as a service, tag it ibexa.view.matcher
, and associate it with the identifier to use in view rules:
| services:
App\View\Matcher\Owner:
autowire: true
tags:
- { name: ibexa.view.matcher, identifier: App\Owner }
|
View configuration
To apply the matcher in view configuration, indicate the matcher by its identifier.
The following configuration uses a special template to render articles owned by the users with provided logins:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 | ibexa_design_engine:
design_list:
my_design: [ my_theme ]
ibexa:
system:
site_group:
design: my_design
content_view:
full:
editor_articles:
template: '@ibexadesign/full/featured_article.html.twig'
match:
Identifier\ContentType: article
App\Owner: [johndoe, janedoe]
|
Note
If you use a matcher that is a service instead of a simple class,
tag the service with ibexa.view.matcher
.