3
0
Fork 0
mirror of https://github.com/farmOS/farmOS.git synced 2024-02-23 11:37:38 +01:00

Validate that only one birth log can reference an asset.

This commit is contained in:
Michael Stenta 2021-09-21 16:56:53 -04:00
parent 3a649a8b42
commit 92cef7f8f8
4 changed files with 162 additions and 0 deletions

View file

@ -7,6 +7,7 @@
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Form\FormStateInterface;
/**
@ -38,3 +39,15 @@ function farm_birth_log_view_alter(array &$build, EntityInterface $entity, Entit
$build['asset']['#title'] = t('Children');
}
}
/**
* Implements hook_entity_base_field_info_alter().
*/
function farm_birth_entity_base_field_info_alter(&$fields, EntityTypeInterface $entity_type) {
/** @var \Drupal\field\Entity\FieldConfig[] $fields */
// Validate that only one birth log references an asset.
if ($entity_type->id() == 'log' && !empty($fields['asset'])) {
$fields['asset']->addConstraint('UniqueBirthLog');
}
}

View file

@ -0,0 +1,24 @@
<?php
namespace Drupal\farm_birth\Plugin\Validation\Constraint;
use Symfony\Component\Validator\Constraint;
/**
* Checks that only one birth log references an asset.
*
* @Constraint(
* id = "UniqueBirthLog",
* label = @Translation("Unique birth log", context = "Validation"),
* )
*/
class UniqueBirthLogConstraint extends Constraint {
/**
* The default violation message.
*
* @var string
*/
public $message = '%child already has a birth log. More than one birth log cannot reference the same child.';
}

View file

@ -0,0 +1,73 @@
<?php
namespace Drupal\farm_birth\Plugin\Validation\Constraint;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
/**
* Validates the UniqueBirthLog constraint.
*/
class UniqueBirthLogConstraintValidator extends ConstraintValidator implements ContainerInjectionInterface {
/**
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* Constructs a UniqueBirthLogConstraintValidator object.
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
*/
public function __construct(EntityTypeManagerInterface $entity_type_manager) {
$this->entityTypeManager = $entity_type_manager;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('entity_type.manager')
);
}
/**
* {@inheritdoc}
*/
public function validate($value, Constraint $constraint) {
/** @var \Drupal\Core\Field\FieldItemListInterface[] $value */
/** @var \Drupal\farm_birth\Plugin\Validation\Constraint\UniqueBirthLogConstraint $constraint */
foreach ($value as $item) {
// Get the referenced asset ID.
$item_value = $item->getValue();
$asset_id = $item_value['target_id'] ?? FALSE;
// If there is no asset, skip.
if (empty($asset_id)) {
continue;
}
// Perform an entity field query to find logs that reference the asset.
$query = $this->entityTypeManager->getStorage('log')->getQuery();
$ids = $query->condition('type', 'birth')
->condition('asset', $asset_id)
->execute();
// If more than 1 birth logs reference the asset, add a violation.
if (count($ids) > 1) {
$asset = $this->entityTypeManager->getStorage('asset')->load($asset_id);
$this->context->addViolation($constraint->message, ['%child' => $asset->label()]);
}
}
}
}

View file

@ -3,6 +3,7 @@
namespace Drupal\Tests\farm_birth\Kernel;
use Drupal\asset\Entity\Asset;
use Drupal\Component\Render\FormattableMarkup;
use Drupal\KernelTests\KernelTestBase;
use Drupal\log\Entity\Log;
use Drupal\taxonomy\Entity\Term;
@ -36,6 +37,7 @@ class BirthTest extends KernelTestBase {
'user',
'taxonomy',
'text',
'views',
];
/**
@ -130,4 +132,54 @@ class BirthTest extends KernelTestBase {
$this->assertEquals($timestamp, $child2->get('birthdate')->value);
}
/**
* Test that only one birth log can reference an asset.
*/
public function testUniqueBirthLogConstraint() {
// Create a Cow animal type term.
/** @var \Drupal\taxonomy\TermInterface $cow */
$cow = Term::create([
'name' => 'Cow',
'vid' => 'animal_type',
]);
$cow->save();
// Create an asset.
/** @var \Drupal\asset\Entity\AssetInterface $animal */
$asset = Asset::create([
'name' => $this->randomMachineName(),
'type' => 'animal',
'animal_type' => ['tid' => $cow->id()],
'status' => 'active',
]);
$asset->save();
// Create a birth log that references the asset.
$log1 = Log::create([
'type' => 'birth',
'timestamp' => \Drupal::time()->getRequestTime(),
'asset' => [['target_id' => $asset->id()]],
]);
$log1->save();
// Confirm that there were no validation errors.
$errors = $log1->validate();
$this->assertCount(0, $errors);
// Create a second birth log that references the asset.
$log2 = Log::create([
'type' => 'birth',
'timestamp' => \Drupal::time()->getRequestTime(),
'asset' => [['target_id' => $asset->id()]],
]);
$log2->save();
// Confirm that validation fails.
$errors = $log2->validate();
$this->assertCount(1, $errors);
$this->assertEquals(new FormattableMarkup('%child already has a birth log. More than one birth log cannot reference the same child.', ['%child' => $asset->label()]), $errors[0]->getMessage());
$this->assertEquals('asset', $errors[0]->getPropertyPath());
}
}