Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updates "Create custom view matcher" #2281

Merged
merged 5 commits into from
Feb 7, 2024
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
2 changes: 1 addition & 1 deletion code_samples/front/view_matcher/config/packages/views.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ ibexa:
template: '@ibexadesign/full/featured_article.html.twig'
match:
Identifier\ContentType: article
\App\View\Matcher\Owner: [johndoe, janedoe]
App\Owner: [johndoe, janedoe]
5 changes: 5 additions & 0 deletions code_samples/front/view_matcher/config/services.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
services:
App\View\Matcher\Owner:
autowire: true
tags:
- { name: ibexa.view.matcher, identifier: App\Owner }
50 changes: 40 additions & 10 deletions code_samples/front/view_matcher/src/View/Matcher/Owner.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,48 @@

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\MultipleValued;
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 extends MultipleValued
class Owner implements MatcherInterface
{
public function matchLocation(Location $location)
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());
}

public function matchContentInfo(ContentInfo $contentInfo)
/**
* @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
{
$location = null;

if ($view instanceof LocationValueView) {
return $this->matchLocation($view->getLocation());
}
Expand All @@ -36,14 +55,25 @@ public function match(View $view): ?bool
return false;
}

/**
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException
*/
private function hasOwner(ContentInfo $contentInfo): bool
{
$owner = $this->getRepository()->getUserService()->loadUser($contentInfo->ownerId);
$owner = $this->userService->loadUser($contentInfo->ownerId);

return in_array($owner->login, $this->matchingUserLogins, true);
}

if (\array_key_exists($owner->login, $this->values)) {
return 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');
}

return false;
$this->matchingUserLogins = $matchingConfig;
}
}
19 changes: 14 additions & 5 deletions docs/templating/templates/create_custom_view_matcher.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ description: You can create custom view matchers to configure template and contr
In addition to the [built-in view matchers](view_matcher_reference.md),
you can also create custom matchers to use in [template configuration](template_configuration.md#view-rules-and-matching).

To do it, create a matcher class that extends `Ibexa\Core\MVC\Symfony\Matcher\ContentBased\MultipleValued`.
To do it, create a matcher class that implements `Ibexa\Core\MVC\Symfony\Matcher\ContentBased\MatcherInterface`.

## Matcher class

Expand All @@ -16,24 +16,33 @@ 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.

``` php hl_lines="44"
``` php hl_lines="65"
[[= include_file('code_samples/front/view_matcher/src/View/Matcher/Owner.php') =]]
```

The matcher checks whether the owner of the current content (by its ContentInfo or Location)
matches any of the values passed in configuration (line 44).
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:

``` yaml
[[= include_file('code_samples/front/view_matcher/config/services.yaml') =]]
```

## View configuration

To apply the matcher in view configuration, indicate the matcher by its fully qualified class name, preceded by `\`.
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:

``` yaml
``` yaml hl_lines="15"
[[= include_file('code_samples/front/view_matcher/config/packages/views.yaml') =]]
```

Expand Down
Loading