- 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.