Initial commit: CloudOps infrastructure platform
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\EmailBundle\Validator;
|
||||
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
|
||||
class Dsn extends Constraint
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\EmailBundle\Validator;
|
||||
|
||||
use Mautic\EmailBundle\Mailer\Transport\TransportFactory;
|
||||
use Mautic\EmailBundle\Validator\Dsn as DsnConstraint;
|
||||
use Symfony\Component\Mailer\Exception\ExceptionInterface;
|
||||
use Symfony\Component\Mailer\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Mailer\Exception\UnsupportedSchemeException;
|
||||
use Symfony\Component\Mailer\Transport\Dsn as MailerDsn;
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
use Symfony\Component\Validator\ConstraintValidator;
|
||||
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
|
||||
|
||||
class DsnValidator extends ConstraintValidator
|
||||
{
|
||||
public function __construct(
|
||||
private TransportFactory $transportFactory,
|
||||
) {
|
||||
}
|
||||
|
||||
public function validate(mixed $value, Constraint $constraint): void
|
||||
{
|
||||
if (!is_string($value)) {
|
||||
throw new UnexpectedTypeException($value, 'string');
|
||||
}
|
||||
|
||||
if (!$constraint instanceof DsnConstraint) {
|
||||
throw new UnexpectedTypeException($constraint, DsnConstraint::class);
|
||||
}
|
||||
|
||||
if (!$value) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$dsn = MailerDsn::fromString($value);
|
||||
} catch (InvalidArgumentException $e) {
|
||||
$this->context->addViolation($e->getMessage() ?: 'mautic.email.dsn.invalid_dsn');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$this->transportFactory->fromDsnObject($dsn);
|
||||
} catch (UnsupportedSchemeException $e) {
|
||||
$this->context->addViolation($e->getMessage() ?: 'mautic.email.dsn.unsupported_scheme');
|
||||
} catch (ExceptionInterface $e) {
|
||||
$this->context->addViolation($e->getMessage() ?: 'mautic.email.dsn.invalid_dsn');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\EmailBundle\Validator;
|
||||
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
|
||||
final class EmailLists extends Constraint
|
||||
{
|
||||
public function getTargets(): string
|
||||
{
|
||||
return self::CLASS_CONSTRAINT;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\EmailBundle\Validator;
|
||||
|
||||
use Mautic\EmailBundle\Entity\Email;
|
||||
use Mautic\LeadBundle\Entity\LeadList;
|
||||
use Mautic\LeadBundle\Form\Validator\Constraints\LeadListAccess;
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
use Symfony\Component\Validator\Constraints\NotBlank;
|
||||
use Symfony\Component\Validator\ConstraintValidator;
|
||||
use Symfony\Component\Validator\ConstraintViolationInterface;
|
||||
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
|
||||
|
||||
final class EmailListsValidator extends ConstraintValidator
|
||||
{
|
||||
public function validate(mixed $value, Constraint $constraint): void
|
||||
{
|
||||
if (!$value instanceof Email) {
|
||||
throw new UnexpectedTypeException($value, Email::class);
|
||||
}
|
||||
|
||||
if ('list' !== $value->getEmailType() || $value->getTranslationParent()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->validateLists($value);
|
||||
$this->validateExcludedLists($value);
|
||||
$this->validateConflictingLists($value);
|
||||
}
|
||||
|
||||
private function validateLists(Email $email): void
|
||||
{
|
||||
$violations = $this->context->getValidator()->validate(
|
||||
$email->getLists(),
|
||||
[
|
||||
new LeadListAccess(),
|
||||
new NotBlank(
|
||||
[
|
||||
'message' => 'mautic.lead.lists.required',
|
||||
]
|
||||
),
|
||||
]
|
||||
);
|
||||
$this->addViolationsAtPath($violations, 'lists');
|
||||
}
|
||||
|
||||
private function validateExcludedLists(Email $email): void
|
||||
{
|
||||
$violations = $this->context->getValidator()->validate(
|
||||
$email->getExcludedLists(),
|
||||
[
|
||||
new LeadListAccess(['allowEmpty' => true]),
|
||||
]
|
||||
);
|
||||
$this->addViolationsAtPath($violations, 'excludedLists');
|
||||
}
|
||||
|
||||
private function validateConflictingLists(Email $email): void
|
||||
{
|
||||
$listsIds = $this->getListsIds($email->getLists());
|
||||
$excludedListsIds = $this->getListsIds($email->getExcludedLists());
|
||||
$isConflicting = (bool) array_intersect($listsIds, $excludedListsIds);
|
||||
|
||||
if ($isConflicting) {
|
||||
$this->context->buildViolation('mautic.lead.excluded_lists.conflicting')
|
||||
->atPath('excludedLists')
|
||||
->addViolation();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param LeadList[] $lists
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
private function getListsIds(iterable $lists): array
|
||||
{
|
||||
$ids = [];
|
||||
|
||||
foreach ($lists as $list) {
|
||||
$ids[] = (string) $list->getId();
|
||||
}
|
||||
|
||||
return $ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ConstraintViolationInterface[] $violations
|
||||
*/
|
||||
private function addViolationsAtPath(iterable $violations, string $path): void
|
||||
{
|
||||
foreach ($violations as $violation) {
|
||||
$this->context->buildViolation($violation->getMessage())
|
||||
->atPath($path)
|
||||
->addViolation();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\EmailBundle\Validator;
|
||||
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
|
||||
final class EmailOrEmailTokenList extends Constraint
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\EmailBundle\Validator;
|
||||
|
||||
use Mautic\CoreBundle\Exception\InvalidValueException;
|
||||
use Mautic\CoreBundle\Exception\RecordException;
|
||||
use Mautic\CoreBundle\Form\DataTransformer\ArrayStringTransformer;
|
||||
use Mautic\EmailBundle\Exception\InvalidEmailException;
|
||||
use Mautic\EmailBundle\Helper\EmailValidator;
|
||||
use Mautic\LeadBundle\DataObject\ContactFieldToken;
|
||||
use Mautic\LeadBundle\Exception\InvalidContactFieldTokenException;
|
||||
use Mautic\LeadBundle\Validator\CustomFieldValidator;
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
use Symfony\Component\Validator\ConstraintValidator;
|
||||
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
|
||||
|
||||
final class EmailOrEmailTokenListValidator extends ConstraintValidator
|
||||
{
|
||||
private ArrayStringTransformer $transformer;
|
||||
|
||||
public function __construct(
|
||||
private EmailValidator $emailValidator,
|
||||
private CustomFieldValidator $customFieldValidator,
|
||||
) {
|
||||
$this->transformer = new ArrayStringTransformer();
|
||||
}
|
||||
|
||||
public function validate(mixed $csv, Constraint $constraint): void
|
||||
{
|
||||
if (!$constraint instanceof EmailOrEmailTokenList) {
|
||||
throw new UnexpectedTypeException($constraint, EmailOrEmailTokenList::class);
|
||||
}
|
||||
|
||||
if (null === $csv || '' === $csv) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!is_string($csv)) {
|
||||
throw new UnexpectedTypeException($csv, 'string');
|
||||
}
|
||||
|
||||
array_map(
|
||||
$this->makeEmailOrEmailTokenValidator(),
|
||||
$this->transformer->reverseTransform($csv)
|
||||
);
|
||||
}
|
||||
|
||||
private function makeEmailOrEmailTokenValidator(): callable
|
||||
{
|
||||
return function (string $emailOrToken): void {
|
||||
try {
|
||||
// Try to validate if the value is an email address.
|
||||
$this->emailValidator->validate($emailOrToken);
|
||||
} catch (InvalidEmailException) {
|
||||
try {
|
||||
// The token syntax is validated during creation of new ContactFieldToken object.
|
||||
$contactFieldToken = new ContactFieldToken($emailOrToken);
|
||||
|
||||
// Validate that the token default value is a valid email address if set.
|
||||
if ($contactFieldToken->getDefaultValue()) {
|
||||
$this->emailValidator->validate($contactFieldToken->getDefaultValue());
|
||||
}
|
||||
|
||||
// Validate that the contact field exists and is type of email.
|
||||
$this->customFieldValidator->validateFieldType($contactFieldToken->getFieldAlias(), 'email');
|
||||
} catch (RecordException|InvalidValueException|InvalidContactFieldTokenException $tokenException) {
|
||||
$this->context->addViolation(
|
||||
'mautic.email.email_or_token.not_valid',
|
||||
['%value%' => $emailOrToken, '%details%' => $tokenException->getMessage()]
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\EmailBundle\Validator;
|
||||
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
|
||||
class MultipleEmailsValid extends Constraint
|
||||
{
|
||||
public function getTargets(): string|array
|
||||
{
|
||||
return self::PROPERTY_CONSTRAINT;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\EmailBundle\Validator;
|
||||
|
||||
use Mautic\CoreBundle\Form\DataTransformer\ArrayStringTransformer;
|
||||
use Mautic\EmailBundle\Exception\InvalidEmailException;
|
||||
use Mautic\EmailBundle\Helper\EmailValidator;
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
use Symfony\Component\Validator\ConstraintValidator;
|
||||
|
||||
class MultipleEmailsValidValidator extends ConstraintValidator
|
||||
{
|
||||
public function __construct(
|
||||
private EmailValidator $emailValidator,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $emailsInString
|
||||
*/
|
||||
public function validate($emailsInString, Constraint $constraint): void
|
||||
{
|
||||
if (!$emailsInString) {
|
||||
return;
|
||||
}
|
||||
|
||||
$transformer = new ArrayStringTransformer();
|
||||
$emails = $transformer->reverseTransform($emailsInString);
|
||||
|
||||
foreach ($emails as $email) {
|
||||
try {
|
||||
$this->emailValidator->validate($email);
|
||||
} catch (InvalidEmailException $e) {
|
||||
$this->context->buildViolation('mautic.email.multiple_emails.not_valid', ['%email%' => $e->getMessage()])
|
||||
->addViolation();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\EmailBundle\Validator;
|
||||
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
|
||||
class ScheduleDateRange extends Constraint
|
||||
{
|
||||
public string $message = 'mautic.form.date_time_range.invalid_range';
|
||||
|
||||
public function getTargets(): string
|
||||
{
|
||||
return self::CLASS_CONSTRAINT;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\EmailBundle\Validator;
|
||||
|
||||
use Mautic\EmailBundle\Entity\Email;
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
use Symfony\Component\Validator\ConstraintValidator;
|
||||
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
|
||||
|
||||
class ScheduleDateRangeValidator extends ConstraintValidator
|
||||
{
|
||||
public function validate(mixed $value, Constraint $constraint): void
|
||||
{
|
||||
if (!$constraint instanceof ScheduleDateRange) {
|
||||
throw new UnexpectedTypeException($constraint, ScheduleDateRange::class);
|
||||
}
|
||||
|
||||
// Handle Email entity validation
|
||||
if ($value instanceof Email) {
|
||||
// Skip validation if continueSending is false
|
||||
if (!$value->getContinueSending()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$publishUp = $value->getPublishUp();
|
||||
$publishDown = $value->getPublishDown();
|
||||
$pathPrefix = '';
|
||||
}
|
||||
// Handle form data validation
|
||||
elseif (is_array($value)) {
|
||||
// Skip validation if continueSending is false
|
||||
if (!($value['continueSending'] ?? true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$publishUp = $value['publishUp'] ?? null;
|
||||
$publishDown = $value['publishDown'] ?? null;
|
||||
$pathPrefix = '[publishDown]';
|
||||
}
|
||||
|
||||
if ($publishUp && $publishDown && $publishDown <= $publishUp) {
|
||||
$this->context->buildViolation($constraint->message)
|
||||
->atPath($pathPrefix ?: 'publishDown')
|
||||
->addViolation();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\EmailBundle\Validator;
|
||||
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
|
||||
final class TextOnlyDynamicContent extends Constraint
|
||||
{
|
||||
public string $message = 'mautic.email.subject.dynamic_content.text_only';
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\EmailBundle\Validator;
|
||||
|
||||
use Mautic\DynamicContentBundle\DynamicContent\TypeList;
|
||||
use Mautic\DynamicContentBundle\Model\DynamicContentModel;
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
use Symfony\Component\Validator\ConstraintValidator;
|
||||
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
|
||||
|
||||
final class TextOnlyDynamicContentValidator extends ConstraintValidator
|
||||
{
|
||||
public function __construct(private DynamicContentModel $dynamicContentModel)
|
||||
{
|
||||
}
|
||||
|
||||
public function validate(mixed $value, Constraint $constraint): void
|
||||
{
|
||||
// Skip validation for null or empty values
|
||||
if (null === $value || '' === $value) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!is_string($value)) {
|
||||
throw new UnexpectedTypeException($value, 'string');
|
||||
}
|
||||
|
||||
if (!$constraint instanceof TextOnlyDynamicContent) {
|
||||
throw new UnexpectedTypeException($constraint, TextOnlyDynamicContent::class);
|
||||
}
|
||||
|
||||
// Pattern to match DWC tokens in the format {dwc=slotname}
|
||||
preg_match_all('/{dwc=([^}]*)}/', $value, $matches);
|
||||
|
||||
foreach ($matches[1] as $slotName) {
|
||||
// Retrieve DWC item by slot name
|
||||
$dwcItem = $this->dynamicContentModel->checkEntityBySlotName($slotName, TypeList::HTML);
|
||||
|
||||
// Perform the validation against the type
|
||||
if ($dwcItem) {
|
||||
$this->context->buildViolation(
|
||||
$constraint->message, ['%slotName%' => $slotName])
|
||||
->addViolation();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user