Semantic MediaWiki and related extensions
register

The following example shows how to register a custom constraint using the custom_constraint property.

Register a custom constraint

The custom_constraint property is an object in the schema and is reserved for custom defined constraints using above outlined invocation and hook. The interpretation of what custom_constraint should contain and how those values of the schema are interpret are in the solely hand of the implementor.

{
"type": "PROPERTY_CONSTRAINT_SCHEMA",
"constraints": {
"custom_constraint": {
"foo_constraint": true
}
},
"tags": [
"property constraint",
"custom constraint"
]
}

The validation schema only checks whether custom_constraint is an object or not, any further validation of what and how the object is structured is not part of the schema validation, the assigned Constraint class should handle any inconsistencies with an invalid constraint definition.

Hook registration

use Hooks;
use Foo\FooConstraint;
Hooks::register( 'SMW::Constraint::initConstraints', function ( $constraintRegistry ) {
// Declares the constraint identifier and assigns a class that interprets the
// content of it
$constraintRegistry->registerConstraint( 'foo_constraint', FooConstraint::class );
return true;
} );

Assigning a non Constraint class or a callable that doesn't return a Constraint instance will throw an exception.

Constraint representation

class FooConstraint implements Constraint {
private $hasViolation = false;
public function hasViolation() {
return $this->hasViolation;
}
public function getType() {
return Constraint::TYPE_INSTANT;
}
public function checkConstraint( array $constraint, $dataValue ) {
$this->hasViolation = false;
// Do the necessary checks
// `$constraint` contains the details of what the schema has defined
// and should be used to interpret the data available and identify any
// violations
...
// Found a violation and report the error
$this->reportError( $dataValue );
}
private function reportError( $dataValue ) {
$this->hasViolation = true;
$error = [
'foo-violation-message-key'
];
$dataValue->addError(
new ConstraintError( $error )
);
}
}

Other examples

For example, when implementing custom_constraint with a start_end_constraint that contains greater_than condition, the greater_than property may expect an array and the registered class for start_end_constraint has to interpret what greater_than means in the context of the given array. It could be defined as "the first element (e.g. property `Event end`) needs to be greater than the second element (e.g. property `Event start`)" but that is up to the implementing class to decide and has nothing to do with Semantic MediaWiki.

{
"type": "CLASS_CONSTRAINT_SCHEMA",
"constraints": {
"mandatory_properties": [
"Event start",
"Event end"
],
"custom_constraint": {
"start_end_constraint": {
"greater_than": ["Event end", "Event start"]
}
}
},
"tags": [
"class constraint",
"custom constraint"
]
}
use Hooks;
use Custom\StartEndConstraint;
Hooks::register( 'SMW::Constraint::initConstraints', function ( $constraintRegistry ) {
$constraintRegistry->registerConstraint( 'start_end_constraint', StartEndConstraint::class );
return true;
} );
class StartEndConstraint implements Constraint {
private $hasViolation;
public function hasViolation() {
return $this->hasViolation;
}
public function getType() {
return Constraint::TYPE_INSTANT;
}
public function checkConstraint( array $constraint, $dataValue ) {
$this->hasViolation = false;
if ( !$dataValue instanceof \SMWDataValue ) {
throw new RuntimeException( "Expected a DataValue instance!" );
}
foreach ( $constraint as $key => $v ) {
if ( $key === 'start_end_constraint' ) {
$this->start_end_constraint( $v, $dataValue );
}
}
}
private function start_end_constraint( $constraint, $dataValue ) {
if ( !isset( $constraint['greater_than'] ) ) {
return;
}
// Interpret the array structure
$end = $constraint['greater_than'][0];
$start = $constraint['greater_than'][1];
$semanticData = $dataValue->getCallable( SemanticData::class )();
$s = $semanticData->getPropertyValues(
DIProperty::newFromUserLabel( $start )
);
$e = $semanticData->getPropertyValues(
DIProperty::newFromUserLabel( $end )
);
// Compare $s and $e and issue an error on case of
// a violation
...
}

See also


About | General disclaimer | Privacy policy