Skip to content

Commit

Permalink
Added attributes support for generating name schema
Browse files Browse the repository at this point in the history
x

Fixed
  • Loading branch information
kisztof committed Aug 7, 2023
1 parent 3adc2af commit baee7f7
Show file tree
Hide file tree
Showing 11 changed files with 405 additions and 117 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,48 +6,37 @@
*/
declare(strict_types=1);

namespace Ibexa\Contracts\Core\Event;
namespace Ibexa\Contracts\Core\Event\NameSchema;

use Ibexa\Contracts\Core\Repository\Values\Content\Content;
use Symfony\Contracts\EventDispatcher\Event;

final class ResolveUrlAliasSchemaEvent extends Event
abstract class AbstractNameSchemaEvent extends Event
{
/** @var array<string, array> */
private array $schemaIdentifiers;

private Content $content;

/**
* @var array<string, array<string>>
*/
private array $names = [];

public function __construct(
array $schemaIdentifiers,
Content $content
) {
$this->schemaIdentifiers = $schemaIdentifiers;
$this->content = $content;
}
private array $tokenValues = [];

public function getSchemaIdentifiers(): array
public function __construct(array $schemaIdentifiers)
{
return $this->schemaIdentifiers;
$this->schemaIdentifiers = $schemaIdentifiers;
}

public function getContent(): Content
public function getTokenValues(): array
{
return $this->content;
return $this->tokenValues;
}

public function getTokenValues(): array
public function setTokenValues(array $names): void
{
return $this->names;
$this->tokenValues = $names;
}

public function setTokenValues(array $names): void
public function getSchemaIdentifiers(): array
{
$this->names = $names;
return $this->schemaIdentifiers;
}
}
29 changes: 29 additions & 0 deletions src/contracts/Event/NameSchema/ResolveContentNameSchemaEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

/**
* @copyright Copyright (C) Ibexa AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);

namespace Ibexa\Contracts\Core\Event\NameSchema;

use Ibexa\Contracts\Core\Repository\Values\Content\Content;

final class ResolveContentNameSchemaEvent extends AbstractNameSchemaEvent
{
private Content $content;

public function __construct(
array $schemaIdentifiers,
Content $content
) {
parent::__construct($schemaIdentifiers);
$this->content = $content;
}

public function getContent(): Content
{
return $this->content;
}
}
47 changes: 47 additions & 0 deletions src/contracts/Event/NameSchema/ResolveNameSchemaEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

/**
* @copyright Copyright (C) Ibexa AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);

namespace Ibexa\Contracts\Core\Event\NameSchema;

use Ibexa\Contracts\Core\Repository\Values\ContentType\ContentType;

final class ResolveNameSchemaEvent extends AbstractNameSchemaEvent
{
private ContentType $contentType;

private array $fieldMap;

private array $languageCodes;

public function __construct(
array $schemaIdentifiers,
ContentType $contentType,
array $fieldMap,
array $languageCodes
) {
parent::__construct($schemaIdentifiers);
$this->contentType = $contentType;
$this->fieldMap = $fieldMap;
$this->languageCodes = $languageCodes;
}

public function getContentType(): ContentType
{
return $this->contentType;
}

public function getFieldMap(): array
{
return $this->fieldMap;
}

public function getLanguageCodes(): array
{
return $this->languageCodes;
}
}
29 changes: 29 additions & 0 deletions src/contracts/Event/NameSchema/ResolveUrlAliasSchemaEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

/**
* @copyright Copyright (C) Ibexa AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);

namespace Ibexa\Contracts\Core\Event\NameSchema;

use Ibexa\Contracts\Core\Repository\Values\Content\Content;

final class ResolveUrlAliasSchemaEvent extends AbstractNameSchemaEvent
{
private Content $content;

public function __construct(
array $schemaIdentifiers,
Content $content
) {
parent::__construct($schemaIdentifiers);
$this->content = $content;
}

public function getContent(): Content
{
return $this->content;
}
}
107 changes: 96 additions & 11 deletions src/lib/Repository/EventSubscriber/NameSchemaSubscriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@

namespace Ibexa\Core\Repository\EventSubscriber;

use Ibexa\Contracts\Core\Event\ResolveUrlAliasSchemaEvent;
use Ibexa\Contracts\Core\Event\NameSchema\AbstractNameSchemaEvent;
use Ibexa\Contracts\Core\Event\NameSchema\ResolveContentNameSchemaEvent;
use Ibexa\Contracts\Core\Event\NameSchema\ResolveNameSchemaEvent;
use Ibexa\Contracts\Core\Event\NameSchema\ResolveUrlAliasSchemaEvent;
use Ibexa\Contracts\Core\Repository\Values\Content\Content;
use Ibexa\Contracts\Core\Repository\Values\ContentType\ContentType;
use Ibexa\Core\FieldType\FieldTypeRegistry;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

Expand All @@ -27,29 +32,109 @@ public function __construct(FieldTypeRegistry $fieldTypeRegistry)
public static function getSubscribedEvents(): array
{
return [
ResolveNameSchemaEvent::class => [
['onResolveNameSchema', -100],
],
ResolveContentNameSchemaEvent::class => [
['onResolveContentNameSchema', -100],
],
ResolveUrlAliasSchemaEvent::class => [
['onResolveUrlAliasSchema', -100],
],
];
}

/**
* Resolves the URL alias schema by setting token values for specified field identifiers and languages.
*
* @param \Ibexa\Contracts\Core\Event\ResolveUrlAliasSchemaEvent $event
*/
public function onResolveUrlAliasSchema(ResolveUrlAliasSchemaEvent $event): void
public function onResolveNameSchema(ResolveNameSchemaEvent $event): void
{
if (!array_key_exists('field', $event->getSchemaIdentifiers())) {
if (!$this->isValid($event)) {
return;
}

$content = $event->getContent();
$identifiers = $event->getSchemaIdentifiers()['field'];
$languages = $event->getContent()->getVersionInfo()->getLanguages();
$tokenValues = $event->getTokenValues();
$fieldMap = $event->getFieldMap();

$contentType = $event->getContentType();
foreach ($event->getLanguageCodes() as $languageCode) {
foreach ($identifiers as $identifier) {
$fieldDefinition = $contentType->getFieldDefinition($identifier);
if (null === $fieldDefinition) {
continue;
}
$persistenceFieldType = $this->fieldTypeRegistry->getFieldType($fieldDefinition->fieldTypeIdentifier);

$fieldValue = $fieldMap[$identifier][$languageCode] ?? '';
$fieldValue = $persistenceFieldType->getName(
$fieldValue,
$fieldDefinition,
$languageCode
);

$tokenValues[$languageCode][$identifier] = $fieldValue;
}
}

$event->setTokenValues($tokenValues);
}

public function onResolveContentNameSchema(ResolveContentNameSchemaEvent $event): void
{
if (!$this->isValid($event)) {
return;
}

$content = $event->getContent();
$contentType = $content->getContentType();
$tokenValues = $this->processEvent(
$event->getContent()->getVersionInfo()->getLanguages(),
$event->getSchemaIdentifiers()['field'],
$contentType,
$content,
$event->getTokenValues()
);

$event->setTokenValues($tokenValues);
}

public function onResolveUrlAliasSchema(ResolveUrlAliasSchemaEvent $event): void
{
if (!$this->isValid($event)) {
return;
}

$content = $event->getContent();
$contentType = $content->getContentType();
$tokenValues = $this->processEvent(
$event->getContent()->getVersionInfo()->getLanguages(),
$event->getSchemaIdentifiers()['field'],
$contentType,
$content,
$event->getTokenValues()
);

$event->setTokenValues($tokenValues);
}

public function isValid(AbstractNameSchemaEvent $event): bool
{
return array_key_exists('field', $event->getSchemaIdentifiers());
}

/**
* @param array<string, string> $tokens
* @param array<string> $languageCodes
* @param array<int, mixed> $attributes
* @param array<string, mixed> $tokenValues
*
* @return array
*/
public function processEvent(
$languages,
$identifiers,
ContentType $contentType,
Content $content,
array $tokenValues
): array {
foreach ($languages as $language) {
$languageCode = $language->getLanguageCode();
foreach ($identifiers as $identifier) {
Expand All @@ -70,6 +155,6 @@ public function onResolveUrlAliasSchema(ResolveUrlAliasSchemaEvent $event): void
}
}

$event->setTokenValues($tokenValues);
return $tokenValues;
}
}
52 changes: 52 additions & 0 deletions src/lib/Repository/NameSchema/NameSchemaFilter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

/**
* @copyright Copyright (C) Ibexa AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);

namespace Ibexa\Core\Repository\NameSchema;

final class NameSchemaFilter
{
public const META_STRING = 'EZMETAGROUP_';

/**
* Builds a lookup / translation table for groups in the $namePattern.
* The groups are referenced with a generated meta-token in the original
* name pattern.
*
* Returns intermediate name pattern where groups are replaced with meta-tokens.
*
* @param string $nameSchema
*
* @return array{string, array<string, string>}
*/
public function filterNameSchema(string $nameSchema): array
{
$retNamePattern = $nameSchema;
$foundGroups = preg_match_all('/\((.+)\)/U', $nameSchema, $groupArray);
$groupLookupTable = [];

if ($foundGroups) {
$i = 0;
foreach ($groupArray[1] as $group) {
// Create meta-token for group
$metaToken = self::META_STRING . $i;

// Insert the group with its placeholder token
$retNamePattern = str_replace($group, $metaToken, $retNamePattern);

// Remove the pattern "(" ")" from the tokens
$group = str_replace(['(', ')'], '', $group);

$groupLookupTable[$metaToken] = $group;
++$i;
}
$nameSchema = $retNamePattern;
}

return [$nameSchema, $groupLookupTable];
}
}
Loading

0 comments on commit baee7f7

Please sign in to comment.