Skip to main content
Version: 2023.3

Custom Rule Definition

To create a custom rule definition, you need to follow four steps:

  1. Create a new PHP class for your new rule definition;
  2. Register the class as a service;
  3. Create the user interface for your new rule definition;
  4. Register the new rule definition itself.

Create a Custom Rule Definition PHP Class​

Let's start by adding a Sample Check rule definition in PHP. Your new rule definition class has to extend the AbstractRuleDefinition:

<?php
declare(strict_types=1);

namespace Foo\Bar;

use Pimcore\Bundle\DataQualityManagementBundle\Installer;
use Pimcore\Bundle\DataQualityManagementBundle\Model\RuleDefinition\AbstractRuleDefinition;
use Pimcore\Bundle\DataQualityManagementBundle\Model\ValidatorResponse;
use Pimcore\Model\DataObject;
use Symfony\Contracts\Translation\TranslatorInterface;

class SampleCheck extends AbstractRuleDefinition
{
protected const FIELD_TYPE = 'sampleCheck';

public function __construct(
private readonly TranslatorInterface $translator
) {
}

public function getType(): string
{
return self::FIELD_TYPE;
}

public function supports(string $type): bool
{
return $type === $this->getType();
}

public function getSuggestion(
array $rule, //the rule definition
string $locale,
array $objectData, //the data of the object passed from the UI
array $ruleData //the data stored in the Data Object which are related to the current rule
): ?string
{
//you can return a string suggestion which will be displayed in the UI:
if (!isset($rule['yourSuggestionField'])) {
return null;
}

return $this->translator->trans(
$rule['yourSuggestionField'],
[],
Installer::TRANSLATION_DOMAIN,
$locale
);

//you can also append additional data to your message:
$message = $this->translator->trans(
'plugin_pimcore_dataqualitymanagement_fixed_suggestion',
[],
Installer::TRANSLATION_DOMAIN,
$locale
);
$message .= ' ' . implode(', ', $ruleData['invalidFields']);

return $message;
}

public function forceRecalculation(): bool
{
return false;
//if true:
//the rule definition will be recalculated for every saved Data Objects (and children)
//every time you save the class definition, even if the data has not changed.
//else:
//the rule definition will be recalculated for every saved Data Objects (and children)
//only if there is a modification in the configuration.
//(behaves like for recommended fields check)
}

public function calculateScore(DataObject\Concrete $dataObject, array $ruleDefinition): ValidatorResponse
{
//your logic here...
return new ValidatorResponse(
true, //true if the rule definition is valid, false otherwise
[], //array of invalid fields
[] //array of additional data (to be used for example in the suggestion)
);
}
}
info

The FIELD_TYPE constant has to match the type in the JS file.

Register the New Class as a Service​

After creating the class, it is important to register it as a service and to tag it as pimcore.data_quality_management.rule_definition:

    ...

Foo\Bar\SampleCheck:
tags:
- { name: pimcore.data_quality_management.rule_definition }

...

Create a User Interface for the New Rule Definition​

You can then compose a user interface for the new rule definition by creating a JS class that extends pimcore.bundle.dataqualitymanagement.ruleDefinitions.abstractDefinition.

For example:

pimcore.registerNS('foo.bar.sampleCheck');

foo.bar.sampleCheck = Class.create(
pimcore.bundle.dataqualitymanagement.ruleDefinitions.abstractDefinition, {
type: 'sampleCheck',
label: 'sample_check',

//this reflects the default configuration of your fields:
configuration: {
title: '', //mandatory
weight: 1, //mandatory
},
fieldsToCheck: ['title', 'weight'],
fieldsToTranslate: ['title'],

getLayoutFields: function () {
return [
{
xtype: 'textfield',
fieldLabel: t('title'),
name: 'title',
allowBlank: false,
width: 600,
bind: '{title}'
},
{
xtype: 'numberfield',
fieldLabel: t('weight'),
name: 'weight',
allowBlank: false,
bind: '{weight}',
}
]
},
});

foo.bar.sampleCheck.panelName = t('custom sample check');
foo.bar.sampleCheck.type = 'sampleCheck';
caution

As shown in the example above, the title and weight properties are mandatory.

Fields to Translate​

You can use fieldsToTranslate to add a translation for the title and/or suggestion labels (fieldLabel) available in your rule definition configuration. The translations will be displayed in the Data Quality Details tab in the Data Object editor.

Suggestion Configuration​

You can add a suggestion field to your new rule definition with the following layout:

{
xtype: 'textfield',
fieldLabel: t('suggestion'),
name: 'yourSuggestionField',
allowBlank: false,
width: 600,
bind: '{yourSuggestionField}'
}

This field is optional and should also be called in your rule definition PHP class with the getSuggestion() function.

Data Store​

To use the data store, your sampleCheck JS class needs to implement the following function:

//if additional data loading is needed:
initDataStore: function() {
return new Ext.Promise(function (resolve, reject) {
//Whatever you want to do here...
});
}
caution

This function is optional and should be implemented only if the data store is effectively used.

Register the New Rule Definition​

After creating the rule definition itself, you can register it via the prepareRuleDefinitionsMenu event. For example, in the startup.js file:

document.addEventListener(pimcore.events.prepareRuleDefinitionsMenu, function (e) {
const definitions = e.detail.definitions;
definitions.push(foo.bar.sampleCheck);
});