addValidator(RequiredFields::create(['MyRequiredField'])); * * return $compositeValidator * } * * Or by implementing the updateCMSCompositeValidator() method in a DataExtension: * * public function updateCMSCompositeValidator(CompositeValidator $compositeValidator): void * { * $compositeValidator->addValidator(RequiredFields::create(['AdditionalContent'])); * } * * Class CompositeValidator * * @package SilverStripe\Forms */ class CompositeValidator extends Validator { /** * @var array|Validator[] */ private $validators; /** * CompositeValidator constructor. * * @param array|Validator[] $validators */ public function __construct(array $validators = []) { $this->validators = array_values($validators ?? []); parent::__construct(); } /** * Set the provided Form to the CompositeValidator and each Validator that has been added. * * @param Form $form * @return Validator */ public function setForm($form) { foreach ($this->getValidators() as $validator) { $validator->setForm($form); } return parent::setForm($form); } /** * @param Validator $validator * @return CompositeValidator */ public function addValidator(Validator $validator): CompositeValidator { $this->validators[] = $validator; return $this; } /** * Returns any errors there may be. This method considers the enabled status of the CompositeValidator as a whole * (exiting early if the Composite is disabled), as well as the enabled status of each individual Validator. * * @return ValidationResult */ public function validate() { $this->resetResult(); // This CompositeValidator has been disabled in full if (!$this->getEnabled()) { return $this->result; } foreach ($this->getValidators() as $validator) { // validate() will return a ValidationResult, and we will combine this with the result we already have $this->getResult()->combineAnd($validator->validate()); } return $this->result; } /** * Note: The existing implementations for the php() method (@see RequiredFields) does not check whether the * Validator is enabled or not, and it also does not reset the validation result - so, neither does this. * * @param array $data * @return bool */ public function php($data) { foreach ($this->getValidators() as $validator) { // Run validation, and exit early if it's valid if ($validator->php($data)) { continue; } // Validation result was invalid. Combine our ValidationResult messages $this->getResult()->combineAnd($validator->getResult()); } // After collating results, return whether or not everything was valid return $this->getResult()->isValid(); } /** * Returns whether the field in question is required. This will usually display '*' next to the * field. * * @param string $fieldName * * @return bool */ public function fieldIsRequired($fieldName) { foreach ($this->getValidators() as $validator) { if ($validator->fieldIsRequired($fieldName)) { return true; } } return false; } /** * @return array|Validator[] */ public function getValidators(): array { return $this->validators; } /** * Return all Validators that match a certain class name. EG: RequiredFields::class * * The keys for the return array match the keys in the unfiltered array. You cannot assume the keys will be * sequential or that the first key will be ZERO. * * @param string $className * @return array|Validator[] */ public function getValidatorsByType(string $className): array { $validators = []; foreach ($this->getValidators() as $key => $validator) { if (!$validator instanceof $className) { continue; } $validators[$key] = $validator; } return $validators; } /** * Remove all Validators that match a certain class name. EG: RequiredFields::class * * @param string $className * @return CompositeValidator */ public function removeValidatorsByType(string $className): CompositeValidator { foreach ($this->getValidatorsByType($className) as $key => $validator) { $this->removeValidatorByKey($key); } return $this; } /** * Each Validator is aware of whether or not it can be cached. If even one Validator cannot be cached, then the * CompositeValidator as a whole also cannot be cached. * * @return bool */ public function canBeCached(): bool { foreach ($this->getValidators() as $validator) { if (!$validator->canBeCached()) { return false; } } return true; } /** * @internal This method may be updated to public in the future. Let us know if you feel there's a use case for it * @param int $key * @return CompositeValidator */ protected function removeValidatorByKey(int $key): CompositeValidator { if (!array_key_exists($key, $this->validators ?? [])) { throw new InvalidArgumentException( sprintf('Key "%s" does not exist in $validators array', $key) ); } unset($this->validators[$key]); return $this; } }