Initial commit: CloudOps infrastructure platform
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\LeadBundle\Validator\Constraints;
|
||||
|
||||
use Symfony\Component\Validator\Constraints\Length as SymfonyLength;
|
||||
|
||||
#[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::TARGET_METHOD | \Attribute::TARGET_CLASS)]
|
||||
class Length extends SymfonyLength
|
||||
{
|
||||
public function validatedBy(): string
|
||||
{
|
||||
return static::class.'Validator';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\LeadBundle\Validator\Constraints;
|
||||
|
||||
use Mautic\LeadBundle\Helper\FormFieldHelper;
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
use Symfony\Component\Validator\Constraints\LengthValidator as SymfonyLengthValidator;
|
||||
|
||||
class LengthValidator extends SymfonyLengthValidator
|
||||
{
|
||||
public function validate(mixed $value, Constraint $constraint): void
|
||||
{
|
||||
if (is_array($value)) {
|
||||
$value = FormFieldHelper::formatList(FormFieldHelper::FORMAT_BAR, $value);
|
||||
}
|
||||
|
||||
parent::validate($value, $constraint);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\LeadBundle\Validator\Constraints;
|
||||
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
|
||||
class SegmentDate extends Constraint
|
||||
{
|
||||
public string $message;
|
||||
|
||||
public function validatedBy(): string
|
||||
{
|
||||
return SegmentDateValidator::class;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\LeadBundle\Validator\Constraints;
|
||||
|
||||
use Mautic\LeadBundle\Segment\ContactSegmentFilterFactory;
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
use Symfony\Component\Validator\ConstraintValidator;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
final class SegmentDateValidator extends ConstraintValidator
|
||||
{
|
||||
public function __construct(
|
||||
private ContactSegmentFilterFactory $contactSegmentFilterFactory,
|
||||
private TranslatorInterface $translator,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<mixed> $filters
|
||||
*/
|
||||
public function validate($filters, Constraint $constraint): void
|
||||
{
|
||||
foreach ($filters as $filter) {
|
||||
if (isset($filter['type']) && in_array($filter['type'], ['date', 'datetime'])) {
|
||||
$segmentFilter = $this->contactSegmentFilterFactory->factorSegmentFilter($filter);
|
||||
$parameterValue = $segmentFilter->getParameterValue();
|
||||
|
||||
if (is_array($parameterValue)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (in_array($filter['operator'] ?? '', ['regexp', '!regexp', 'like', '!like', 'startsWith', 'endsWith', 'contains'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (null === $parameterValue) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (str_contains($parameterValue, '%')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$formats = ['Y-m-d', 'Y-m-d H:i', 'Y-m-d H:i:s'];
|
||||
|
||||
foreach ($formats as $fmt) {
|
||||
$dateTime = \DateTime::createFromFormat($fmt, $parameterValue);
|
||||
if (false !== $dateTime) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (false === $dateTime) {
|
||||
$this->context->addViolation($this->translator->trans('mautic.lead.segment.date_invalid', ['%value%' => $parameterValue], 'validators'));
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\LeadBundle\Validator\Constraints;
|
||||
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
|
||||
class SegmentUsedInCampaigns extends Constraint
|
||||
{
|
||||
public function getTargets(): string|array
|
||||
{
|
||||
return static::CLASS_CONSTRAINT;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\LeadBundle\Validator\Constraints;
|
||||
|
||||
use Mautic\CoreBundle\Exception\RecordNotUnpublishedException;
|
||||
use Mautic\LeadBundle\Entity\LeadList;
|
||||
use Mautic\LeadBundle\Validator\SegmentUsedInCampaignsValidator as InternalValidator;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
use Symfony\Component\Validator\ConstraintValidator;
|
||||
|
||||
class SegmentUsedInCampaignsValidator extends ConstraintValidator
|
||||
{
|
||||
public function __construct(private InternalValidator $internalValidator)
|
||||
{
|
||||
}
|
||||
|
||||
public function validate(mixed $segment, Constraint $constraint): void
|
||||
{
|
||||
try {
|
||||
/** @var LeadList $segment */
|
||||
if ($segment->getIsPublished()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->internalValidator->validate($segment);
|
||||
} catch (RecordNotUnpublishedException $exception) {
|
||||
$this->context->buildViolation($exception->getMessage())
|
||||
->atPath('isPublished')
|
||||
->setCode((string) Response::HTTP_UNPROCESSABLE_ENTITY)
|
||||
->addViolation();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\LeadBundle\Validator;
|
||||
|
||||
use Mautic\CoreBundle\Exception\InvalidValueException;
|
||||
use Mautic\CoreBundle\Exception\RecordNotFoundException;
|
||||
use Mautic\CoreBundle\Exception\RecordNotPublishedException;
|
||||
use Mautic\LeadBundle\Entity\LeadField;
|
||||
use Mautic\LeadBundle\Model\FieldModel;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
class CustomFieldValidator
|
||||
{
|
||||
public function __construct(
|
||||
private FieldModel $fieldModel,
|
||||
private TranslatorInterface $translator,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws RecordNotFoundException
|
||||
* @throws RecordNotPublishedException
|
||||
* @throws InvalidValueException
|
||||
*/
|
||||
public function validateFieldType(string $alias, string $fieldType): void
|
||||
{
|
||||
$field = $this->getPublishedFieldByAlias($alias);
|
||||
|
||||
if ($field->getType() !== $fieldType) {
|
||||
throw new InvalidValueException($this->translator->trans('mautic.lead.contact.wrong.field.type', ['%alias%' => $alias, '%fieldType%' => $field->getType(), '%expectedType%' => $fieldType], 'validators'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws RecordNotFoundException
|
||||
* @throws RecordNotPublishedException
|
||||
*/
|
||||
private function getPublishedFieldByAlias(string $alias): LeadField
|
||||
{
|
||||
$field = $this->getFieldByAlias($alias);
|
||||
|
||||
if (!$field->getIsPublished()) {
|
||||
throw new RecordNotPublishedException($this->translator->trans('mautic.lead.contact.field.not.published', ['%alias%' => $alias], 'validators'));
|
||||
}
|
||||
|
||||
return $field;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws RecordNotFoundException
|
||||
*/
|
||||
private function getFieldByAlias(string $alias): LeadField
|
||||
{
|
||||
$field = $this->fieldModel->getEntityByAlias($alias);
|
||||
|
||||
if (!$field instanceof LeadField) {
|
||||
throw new RecordNotFoundException($this->translator->trans('mautic.lead.contact.field.not.found', ['%alias%' => $alias], 'validators'));
|
||||
}
|
||||
|
||||
return $field;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\LeadBundle\Validator;
|
||||
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
|
||||
final class LeadFieldMinimumLength extends Constraint
|
||||
{
|
||||
public string $message = 'mautic.lead.field.char_length_limit.too_short';
|
||||
|
||||
public function getTargets(): string
|
||||
{
|
||||
return self::CLASS_CONSTRAINT;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\LeadBundle\Validator;
|
||||
|
||||
use Doctrine\DBAL\Connection;
|
||||
use Doctrine\DBAL\Exception\InvalidFieldNameException;
|
||||
use Mautic\LeadBundle\Entity\LeadField;
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
use Symfony\Component\Validator\ConstraintValidator;
|
||||
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
|
||||
|
||||
final class LeadFieldMinimumLengthValidator extends ConstraintValidator
|
||||
{
|
||||
public function __construct(private Connection $connection)
|
||||
{
|
||||
}
|
||||
|
||||
public function validate(mixed $value, Constraint $constraint): void
|
||||
{
|
||||
if (!$value instanceof LeadField) {
|
||||
throw new UnexpectedTypeException($value, LeadField::class);
|
||||
}
|
||||
|
||||
if (!$constraint instanceof LeadFieldMinimumLength) {
|
||||
throw new UnexpectedTypeException($constraint, LeadFieldMinimumLength::class);
|
||||
}
|
||||
|
||||
if ($value->isNew() || !$value->supportsLength() || !$value->getCharLengthLimit()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$maxCharacterLengthInUse = $this->getMaxCharacterLengthInUse($value);
|
||||
|
||||
if ($value->getCharLengthLimit() >= $maxCharacterLengthInUse) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->context->buildViolation($constraint->message, ['%length%' => $maxCharacterLengthInUse])
|
||||
->atPath('charLengthLimit')
|
||||
->addViolation();
|
||||
}
|
||||
|
||||
private function getMaxCharacterLengthInUse(LeadField $leadField): int
|
||||
{
|
||||
try {
|
||||
return (int) $this->connection->createQueryBuilder()
|
||||
->select('MAX(CHAR_LENGTH('.$leadField->getAlias().'))')
|
||||
->from(MAUTIC_TABLE_PREFIX.$leadField->getCustomFieldObject())
|
||||
->executeQuery()
|
||||
->fetchOne();
|
||||
} catch (InvalidFieldNameException) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\LeadBundle\Validator;
|
||||
|
||||
use Mautic\CoreBundle\Exception\RecordNotUnpublishedException;
|
||||
use Mautic\LeadBundle\Entity\LeadList;
|
||||
use Mautic\LeadBundle\Entity\LeadListRepository;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
class SegmentUsedInCampaignsValidator
|
||||
{
|
||||
public function __construct(private LeadListRepository $leadListRepository, private TranslatorInterface $translator)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws RecordNotUnpublishedException
|
||||
*/
|
||||
public function validate(LeadList $segment): void
|
||||
{
|
||||
if (!$segment->getId()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$campaignNames = $this->leadListRepository->getSegmentCampaigns($segment->getId());
|
||||
|
||||
if (1 > count($campaignNames)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$campaignNames = array_map(fn (string $segmentName): string => sprintf('"%s"', $segmentName), $campaignNames);
|
||||
$errorMessage = $this->translator->trans(
|
||||
'mautic.lead.lists.used_in_campaigns',
|
||||
[
|
||||
'%count%' => count($campaignNames),
|
||||
'%campaignNames%' => implode(', ', $campaignNames),
|
||||
],
|
||||
'validators'
|
||||
);
|
||||
|
||||
throw new RecordNotUnpublishedException($errorMessage);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user