Skip to content

Create custom Field Type comparison

In the Back Office, you can compare the contents of Fields. Comparing is possible only between two versions of the same Field that are in the same language.

You can add the possibility to compare custom and other unsupported Field Types.

Note

The following task uses the custom "Hello World" Field Type. The configuration is based on the comparison mechanism created for the ezstring Field Type.

Create Comparable class

First, create a Comparable.php class in src/FieldType/HelloWorld/Comparison.

This class implements the Ibexa\Contracts\VersionComparison\FieldType\Comparable interface with the getDataToCompare() method:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php

declare(strict_types=1);

namespace App\FieldType\HelloWorld\Comparison;

use Ibexa\Contracts\Core\FieldType\Value as SPIValue;
use Ibexa\Contracts\VersionComparison\FieldType\Comparable as ComparableInterface;
use Ibexa\Contracts\VersionComparison\FieldType\FieldTypeComparisonValue;
use Ibexa\VersionComparison\ComparisonValue\StringComparisonValue;

final class Comparable implements ComparableInterface
{
    public function getDataToCompare(SPIValue $value): FieldTypeComparisonValue
    {
        return new Value([
            'name' => new StringComparisonValue([
                'value' => $value->getName(),
            ]),
        ]);
    }
}

The getDataToCompare() fetches the data to compare and determines which comparison engines should be used.

Register this class as a service:

1
2
3
4
services:
    App\FieldType\HelloWorld\Comparison\Comparable:
        tags:
            - { name: ibexa.field_type.comparable, alias: hello_world }

Create comparison value

Next, create a src/FieldType/HelloWorld/Comparison/Value.php file that holds the comparison value:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<?php

declare(strict_types=1);

namespace App\FieldType\HelloWorld\Comparison;

use Ibexa\Contracts\VersionComparison\FieldType\FieldTypeComparisonValue;

class Value extends FieldTypeComparisonValue
{
    /** @var \Ibexa\VersionComparison\ComparisonValue\StringComparisonValue */
    public \Ibexa\VersionComparison\ComparisonValue\StringComparisonValue $name;
}

Create comparison engine

The comparison engine handles the operations required for comparing the contents of Fields. Each Field Type requires a separate comparison engine, which implements the Ibexa\Contracts\VersionComparison\Engine\FieldTypeComparisonEngine interface.

For the "Hello World" Field Type, create the following comparison engine based on the engine for the TextLine Field Type. Place it in src/FieldType/HelloWorld/Comparison/HelloWorldComparisonEngine.php:

 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
<?php

declare(strict_types=1);

namespace App\FieldType\HelloWorld\Comparison;

use Ibexa\Contracts\VersionComparison\Engine\FieldTypeComparisonEngine;
use Ibexa\Contracts\VersionComparison\FieldType\FieldTypeComparisonValue;
use Ibexa\Contracts\VersionComparison\Result\ComparisonResult;
use Ibexa\VersionComparison\Engine\Value\StringComparisonEngine;

final class HelloWorldComparisonEngine implements FieldTypeComparisonEngine
{
    /** @var \Ibexa\VersionComparison\Engine\Value\StringComparisonEngine */
    private \Ibexa\VersionComparison\Engine\Value\StringComparisonEngine $stringValueComparisonEngine;

    public function __construct(StringComparisonEngine $stringValueComparisonEngine)
    {
        $this->stringValueComparisonEngine = $stringValueComparisonEngine;
    }

    /**
     * @param \Ibexa\VersionComparison\FieldType\TextLine\Value $comparisonDataA
     * @param \Ibexa\VersionComparison\FieldType\TextLine\Value $comparisonDataB
     */
    public function compareFieldsTypeValues(FieldTypeComparisonValue $comparisonDataA, FieldTypeComparisonValue $comparisonDataB): ComparisonResult
    {
        return new HelloWorldComparisonResult(
            $this->stringValueComparisonEngine->compareValues($comparisonDataA->name, $comparisonDataB->name)
        );
    }

    public function shouldRunComparison(FieldTypeComparisonValue $comparisonDataA, FieldTypeComparisonValue $comparisonDataB): bool
    {
        return $comparisonDataA->name->value !== $comparisonDataB->name->value;
    }
}

Register the comparison engine as a service:

1
2
3
4
services:
    App\FieldType\HelloWorld\Comparison\HelloWorldComparisonEngine:
        tags:
            - { name: ibexa.field_type.comparable.engine, supported_type: App\FieldType\HelloWorld\Comparison\Value }

Add comparison result

Next, create a comparison result class in src/FieldType/HelloWorld/Comparison/HelloWorldComparisonResult.php.

 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
<?php

declare(strict_types=1);

namespace App\FieldType\HelloWorld\Comparison;

use Ibexa\Contracts\VersionComparison\Result\ComparisonResult;
use Ibexa\VersionComparison\Result\Value\StringComparisonResult;

final class HelloWorldComparisonResult implements ComparisonResult
{
    /** @var \Ibexa\VersionComparison\Result\Value\StringComparisonResult */
    private \Ibexa\VersionComparison\Result\Value\StringComparisonResult $stringDiff;

    public function __construct(StringComparisonResult $stringDiff)
    {
        $this->stringDiff = $stringDiff;
    }

    public function getHelloWorldDiff(): StringComparisonResult
    {
        return $this->stringDiff;
    }

    public function isChanged(): bool
    {
        return $this->stringDiff->isChanged();
    }
}

Provide templates

Finally, create a template for the new comparison view in templates/themes/admin/field_types/field_type_comparison.html.twig:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
{% extends '@ibexadesign/version_comparison/comparison_result_blocks.html.twig' %}

{% block hello_world_field_comparison %}
    {% apply spaceless %}
        <span {{ block( 'field_attributes' ) }}>
            {% with {
                'comparison_result': comparison_result.getHelloWorldDiff()
                } %}
                {{ block('string_diff_render') }}
            {% endwith %}
        </span>
    {% endapply %}
{% endblock %}

Add configuration for this template under the ibexa.system.<scope>.field_comparison_templates configuration key:

1
2
3
4
5
ibexa:
    system:
        default:
            field_comparison_templates:
                - { template: '@ibexadesign/field_types/field_type_comparison.html.twig', priority: 10 }