farm-2.x-dev/modules/asset/group/src/Plugin/Validation/Constraint/CircularGroupMembershipConstraintValidator.php
modules/asset/group/src/Plugin/Validation/Constraint/CircularGroupMembershipConstraintValidator.php
<?php
namespace Drupal\farm_group\Plugin\Validation\Constraint;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\farm_group\GroupMembershipInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
/**
* Validates the CircularGroupMembership constraint.
*/
class CircularGroupMembershipConstraintValidator extends ConstraintValidator implements ContainerInjectionInterface {
/**
* Group membership service.
*
* @var \Drupal\farm_group\GroupMembershipInterface
*/
protected $groupMembership;
/**
* CircularGroupMembershipConstraintValidator constructor.
*
* @param \Drupal\farm_group\GroupMembershipInterface $group_membership
* Group membership service.
*/
public function __construct(GroupMembershipInterface $group_membership) {
$this->groupMembership = $group_membership;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('group.membership'),
);
}
/**
* {@inheritdoc}
*/
public function validate($value, Constraint $constraint) {
/** @var \Drupal\Core\Field\EntityReferenceFieldItemList $value */
/** @var \Drupal\farm_group\Plugin\Validation\Constraint\CircularGroupMembershipConstraint $constraint */
// Get the log that this field is on.
$log = $value->getParent()->getValue();
// If the log is not a group assignment, we have nothing to validate.
if (empty($log->get('is_group_assignment')->value)) {
return;
}
// Get the group(s) that asset(s) are being made members of.
$groups = $log->get('group')->referencedEntities();
// If there are no groups, we have nothing to validate.
if (empty($groups)) {
return;
}
// Get the log's timestamp.
$timestamp = $log->get('timestamp')->value;
// Iterate through referenced entities.
foreach ($value->referencedEntities() as $delta => $asset) {
// If this asset is not a group, skip it.
if ($asset->bundle() != 'group') {
continue;
}
// Load members of this group (recursively).
$members = $this->groupMembership->getGroupMembers([$asset], TRUE, $timestamp);
// Iterate through the groups and look for violations.
$violation = FALSE;
foreach ($groups as $group) {
// Make sure that the asset and group are not the same.
if ($group->id() == $asset->id()) {
$violation = TRUE;
}
// Make sure that none of the group(s) are members of this asset.
foreach ($members as $member) {
if ($group->id() == $member->id()) {
$violation = TRUE;
break;
}
}
}
// If a violation was found, flag it.
if ($violation) {
$this->context->buildViolation($constraint->message, ['%asset' => $asset->label()])
->atPath((string) $delta . '.target_id')
->setInvalidValue($asset->id())
->addViolation();
}
}
}
}
