Initial commit: CloudOps infrastructure platform
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\PointBundle\Entity;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Mautic\ApiBundle\Serializer\Driver\ApiMetadataDriver;
|
||||
use Mautic\CoreBundle\Doctrine\Mapping\ClassMetadataBuilder;
|
||||
use Mautic\CoreBundle\Entity\FormEntity;
|
||||
use Mautic\CoreBundle\Entity\UuidInterface;
|
||||
use Mautic\CoreBundle\Entity\UuidTrait;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
use Symfony\Component\Validator\Mapping\ClassMetadata;
|
||||
|
||||
class Group extends FormEntity implements UuidInterface
|
||||
{
|
||||
use UuidTrait;
|
||||
|
||||
public const TABLE_NAME = 'point_groups';
|
||||
public const ENTITY_NAME = 'point_group';
|
||||
|
||||
private ?int $id = null;
|
||||
|
||||
private ?string $name = '';
|
||||
|
||||
private ?string $description = '';
|
||||
|
||||
/**
|
||||
* @param ORM\ClassMetadata<Group> $metadata
|
||||
*/
|
||||
public static function loadMetadata(ORM\ClassMetadata $metadata): void
|
||||
{
|
||||
$builder = new ClassMetadataBuilder($metadata);
|
||||
|
||||
$builder->setTable(self::TABLE_NAME)
|
||||
->setCustomRepositoryClass(GroupRepository::class);
|
||||
|
||||
static::addUuidField($builder);
|
||||
|
||||
$builder->addIdColumns();
|
||||
}
|
||||
|
||||
public static function loadValidatorMetadata(ClassMetadata $metadata): void
|
||||
{
|
||||
$metadata->addPropertyConstraint('name', new Assert\NotBlank([
|
||||
'message' => 'mautic.core.name.required',
|
||||
]));
|
||||
}
|
||||
|
||||
public static function loadApiMetadata(ApiMetadataDriver $metadata): void
|
||||
{
|
||||
$metadata->setGroupPrefix('pointGroup')
|
||||
->addListProperties(
|
||||
[
|
||||
'id',
|
||||
'name',
|
||||
'description',
|
||||
]
|
||||
)
|
||||
->addProperties(
|
||||
[
|
||||
'id',
|
||||
'name',
|
||||
'description',
|
||||
]
|
||||
)
|
||||
->build();
|
||||
}
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function setDescription(?string $description): self
|
||||
{
|
||||
$this->isChanged('description', $description);
|
||||
$this->description = $description;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDescription(): ?string
|
||||
{
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
public function setName(?string $name): self
|
||||
{
|
||||
$this->isChanged('name', $name);
|
||||
$this->name = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getName(): ?string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\PointBundle\Entity;
|
||||
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Mautic\ApiBundle\Serializer\Driver\ApiMetadataDriver;
|
||||
use Mautic\CoreBundle\Doctrine\Mapping\ClassMetadataBuilder;
|
||||
use Mautic\CoreBundle\Entity\CommonEntity;
|
||||
use Mautic\LeadBundle\Entity\Lead;
|
||||
|
||||
class GroupContactScore extends CommonEntity
|
||||
{
|
||||
public const TABLE_NAME = 'point_group_contact_score';
|
||||
|
||||
private Lead $contact;
|
||||
|
||||
private Group $group;
|
||||
|
||||
private int $score;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->contact = new Lead();
|
||||
$this->group = new Group();
|
||||
$this->score = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ORM\ClassMetadata<GroupContactScore> $metadata
|
||||
*/
|
||||
public static function loadMetadata(ORM\ClassMetadata $metadata): void
|
||||
{
|
||||
$builder = new ClassMetadataBuilder($metadata);
|
||||
|
||||
$builder->setTable(self::TABLE_NAME)
|
||||
->setCustomRepositoryClass(GroupContactScoreRepository::class);
|
||||
|
||||
$builder->addContact(false, 'CASCADE', true, 'groupScores');
|
||||
|
||||
$builder->createManyToOne('group', Group::class)
|
||||
->isPrimaryKey()
|
||||
->addJoinColumn('group_id', 'id', true, false, 'CASCADE')
|
||||
->build();
|
||||
|
||||
$builder->createField('score', Types::INTEGER)
|
||||
->build();
|
||||
}
|
||||
|
||||
public static function loadApiMetadata(ApiMetadataDriver $metadata): void
|
||||
{
|
||||
$metadata->setGroupPrefix('groupContactScore')
|
||||
->addListProperties(
|
||||
[
|
||||
'score',
|
||||
'group',
|
||||
]
|
||||
)
|
||||
->addProperties(
|
||||
[
|
||||
'score',
|
||||
'group',
|
||||
]
|
||||
)
|
||||
->build();
|
||||
}
|
||||
|
||||
public function getContact(): Lead
|
||||
{
|
||||
return $this->contact;
|
||||
}
|
||||
|
||||
public function setContact(Lead $contact): void
|
||||
{
|
||||
$this->contact = $contact;
|
||||
}
|
||||
|
||||
public function getGroup(): Group
|
||||
{
|
||||
return $this->group;
|
||||
}
|
||||
|
||||
public function setGroup(Group $group): void
|
||||
{
|
||||
$this->group = $group;
|
||||
}
|
||||
|
||||
public function getScore(): int
|
||||
{
|
||||
return $this->score;
|
||||
}
|
||||
|
||||
public function setScore(int $score): void
|
||||
{
|
||||
$this->score = $score;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\PointBundle\Entity;
|
||||
|
||||
use Mautic\CoreBundle\Entity\CommonRepository;
|
||||
|
||||
/**
|
||||
* @extends CommonRepository<GroupContactScore>
|
||||
*/
|
||||
class GroupContactScoreRepository extends CommonRepository
|
||||
{
|
||||
public function compareScore(int $leadId, int $groupId, int $score, string $operatorExpr): bool
|
||||
{
|
||||
$q = $this->_em->getConnection()->createQueryBuilder();
|
||||
$q->select('lcs.contact_id')
|
||||
->from(MAUTIC_TABLE_PREFIX.GroupContactScore::TABLE_NAME, 'lcs');
|
||||
|
||||
$expr = $q->expr()->and(
|
||||
$q->expr()->eq('lcs.contact_id', ':lead'),
|
||||
$q->expr()->eq('lcs.group_id', ':groupId'),
|
||||
$q->expr()->$operatorExpr('lcs.score', ':score'),
|
||||
);
|
||||
|
||||
$q->where($expr)
|
||||
->setParameter('lead', $leadId)
|
||||
->setParameter('groupId', $groupId)
|
||||
->setParameter('score', $score);
|
||||
|
||||
return false !== $q->executeQuery()->fetchOne();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\PointBundle\Entity;
|
||||
|
||||
use Mautic\CoreBundle\Entity\CommonRepository;
|
||||
|
||||
/**
|
||||
* @extends CommonRepository<Group>
|
||||
*/
|
||||
class GroupRepository extends CommonRepository
|
||||
{
|
||||
public function getTableAlias(): string
|
||||
{
|
||||
return 'pl';
|
||||
}
|
||||
|
||||
public function getEntities(array $args = [])
|
||||
{
|
||||
// Without qb it returns entities indexed by id instead of array indexes
|
||||
$args['qb'] = $this->createQueryBuilder($this->getTableAlias());
|
||||
|
||||
return parent::getEntities($args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\PointBundle\Entity;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Mautic\CoreBundle\Doctrine\Mapping\ClassMetadataBuilder;
|
||||
use Mautic\CoreBundle\Entity\IpAddress;
|
||||
|
||||
class LeadPointLog
|
||||
{
|
||||
public const TABLE_NAME = 'point_lead_action_log';
|
||||
/**
|
||||
* @var Point
|
||||
**/
|
||||
private $point;
|
||||
|
||||
/**
|
||||
* @var \Mautic\LeadBundle\Entity\Lead
|
||||
*/
|
||||
private $lead;
|
||||
|
||||
/**
|
||||
* @var IpAddress|null
|
||||
*/
|
||||
private $ipAddress;
|
||||
|
||||
/**
|
||||
* @var \DateTimeInterface
|
||||
**/
|
||||
private $dateFired;
|
||||
|
||||
public static function loadMetadata(ORM\ClassMetadata $metadata): void
|
||||
{
|
||||
$builder = new ClassMetadataBuilder($metadata);
|
||||
|
||||
$builder->setTable(self::TABLE_NAME)
|
||||
->setCustomRepositoryClass(LeadPointLogRepository::class);
|
||||
|
||||
$builder->createManyToOne('point', 'Point')
|
||||
->isPrimaryKey()
|
||||
->addJoinColumn('point_id', 'id', true, false, 'CASCADE')
|
||||
->inversedBy('log')
|
||||
->build();
|
||||
|
||||
$builder->addLead(false, 'CASCADE', true);
|
||||
|
||||
$builder->addIpAddress(true);
|
||||
|
||||
$builder->createField('dateFired', 'datetime')
|
||||
->columnName('date_fired')
|
||||
->build();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getDateFired()
|
||||
{
|
||||
return $this->dateFired;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $dateFired
|
||||
*/
|
||||
public function setDateFired($dateFired): void
|
||||
{
|
||||
$this->dateFired = $dateFired;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return IpAddress|null
|
||||
*/
|
||||
public function getIpAddress()
|
||||
{
|
||||
return $this->ipAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IpAddress $ipAddress
|
||||
*/
|
||||
public function setIpAddress($ipAddress): void
|
||||
{
|
||||
$this->ipAddress = $ipAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getLead()
|
||||
{
|
||||
return $this->lead;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $lead
|
||||
*/
|
||||
public function setLead($lead): void
|
||||
{
|
||||
$this->lead = $lead;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getPoint()
|
||||
{
|
||||
return $this->point;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $point
|
||||
*/
|
||||
public function setPoint($point): void
|
||||
{
|
||||
$this->point = $point;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\PointBundle\Entity;
|
||||
|
||||
use Mautic\CoreBundle\Entity\CommonRepository;
|
||||
|
||||
/**
|
||||
* @extends CommonRepository<LeadPointLog>
|
||||
*/
|
||||
class LeadPointLogRepository extends CommonRepository
|
||||
{
|
||||
/**
|
||||
* Updates lead ID (e.g. after a lead merge).
|
||||
*/
|
||||
public function updateLead($fromLeadId, $toLeadId): void
|
||||
{
|
||||
// First check to ensure the $toLead doesn't already exist
|
||||
$results = $this->_em->getConnection()->createQueryBuilder()
|
||||
->select('pl.point_id')
|
||||
->from(MAUTIC_TABLE_PREFIX.'point_lead_action_log', 'pl')
|
||||
->where('pl.lead_id = '.$toLeadId)
|
||||
->executeQuery()
|
||||
->fetchAllAssociative();
|
||||
|
||||
$actions = [];
|
||||
foreach ($results as $r) {
|
||||
$actions[] = $r['point_id'];
|
||||
}
|
||||
|
||||
$q = $this->_em->getConnection()->createQueryBuilder();
|
||||
$q->update(MAUTIC_TABLE_PREFIX.'point_lead_action_log')
|
||||
->set('lead_id', (int) $toLeadId)
|
||||
->where('lead_id = '.(int) $fromLeadId);
|
||||
|
||||
if (!empty($actions)) {
|
||||
$q->andWhere(
|
||||
$q->expr()->notIn('point_id', $actions)
|
||||
)->executeStatement();
|
||||
|
||||
// Delete remaining leads as the new lead already belongs
|
||||
$this->_em->getConnection()->createQueryBuilder()
|
||||
->delete(MAUTIC_TABLE_PREFIX.'point_lead_action_log')
|
||||
->where('lead_id = '.(int) $fromLeadId)
|
||||
->executeStatement();
|
||||
} else {
|
||||
$q->executeStatement();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\PointBundle\Entity;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Mautic\CoreBundle\Doctrine\Mapping\ClassMetadataBuilder;
|
||||
use Mautic\CoreBundle\Entity\IpAddress;
|
||||
|
||||
class LeadTriggerLog
|
||||
{
|
||||
public const TABLE_NAME = 'point_lead_event_log';
|
||||
/**
|
||||
* @var TriggerEvent
|
||||
**/
|
||||
private $event;
|
||||
|
||||
/**
|
||||
* @var \Mautic\LeadBundle\Entity\Lead
|
||||
**/
|
||||
private $lead;
|
||||
|
||||
/**
|
||||
* @var IpAddress|null
|
||||
**/
|
||||
private $ipAddress;
|
||||
|
||||
/**
|
||||
* @var \DateTimeInterface
|
||||
**/
|
||||
private $dateFired;
|
||||
|
||||
public static function loadMetadata(ORM\ClassMetadata $metadata): void
|
||||
{
|
||||
$builder = new ClassMetadataBuilder($metadata);
|
||||
|
||||
$builder->setTable(self::TABLE_NAME)
|
||||
->setCustomRepositoryClass(LeadTriggerLogRepository::class);
|
||||
|
||||
$builder->createManyToOne('event', 'TriggerEvent')
|
||||
->isPrimaryKey()
|
||||
->addJoinColumn('event_id', 'id', false, false, 'CASCADE')
|
||||
->inversedBy('log')
|
||||
->build();
|
||||
|
||||
$builder->addLead(false, 'CASCADE', true);
|
||||
|
||||
$builder->addIpAddress(true);
|
||||
|
||||
$builder->createField('dateFired', 'datetime')
|
||||
->columnName('date_fired')
|
||||
->build();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getDateFired()
|
||||
{
|
||||
return $this->dateFired;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $dateFired
|
||||
*/
|
||||
public function setDateFired($dateFired): void
|
||||
{
|
||||
$this->dateFired = $dateFired;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return IpAddress|null
|
||||
*/
|
||||
public function getIpAddress()
|
||||
{
|
||||
return $this->ipAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IpAddress $ipAddress
|
||||
*/
|
||||
public function setIpAddress($ipAddress): void
|
||||
{
|
||||
$this->ipAddress = $ipAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getLead()
|
||||
{
|
||||
return $this->lead;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $lead
|
||||
*/
|
||||
public function setLead($lead): void
|
||||
{
|
||||
$this->lead = $lead;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getEvent()
|
||||
{
|
||||
return $this->event;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $event
|
||||
*/
|
||||
public function setEvent($event): void
|
||||
{
|
||||
$this->event = $event;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\PointBundle\Entity;
|
||||
|
||||
use Mautic\CoreBundle\Entity\CommonRepository;
|
||||
|
||||
/**
|
||||
* @extends CommonRepository<LeadTriggerLog>
|
||||
*/
|
||||
class LeadTriggerLogRepository extends CommonRepository
|
||||
{
|
||||
/**
|
||||
* Updates lead ID (e.g. after a lead merge).
|
||||
*/
|
||||
public function updateLead($fromLeadId, $toLeadId): void
|
||||
{
|
||||
// First check to ensure the $toLead doesn't already exist
|
||||
$results = $this->_em->getConnection()->createQueryBuilder()
|
||||
->select('pl.event_id')
|
||||
->from(MAUTIC_TABLE_PREFIX.'point_lead_event_log', 'pl')
|
||||
->where('pl.lead_id = '.$toLeadId)
|
||||
->executeQuery()
|
||||
->fetchAllAssociative();
|
||||
|
||||
$events = [];
|
||||
foreach ($results as $r) {
|
||||
$events[] = $r['event_id'];
|
||||
}
|
||||
|
||||
$q = $this->_em->getConnection()->createQueryBuilder();
|
||||
$q->update(MAUTIC_TABLE_PREFIX.'point_lead_event_log')
|
||||
->set('lead_id', (int) $toLeadId)
|
||||
->where('lead_id = '.(int) $fromLeadId);
|
||||
|
||||
if (!empty($events)) {
|
||||
$q->andWhere(
|
||||
$q->expr()->notIn('event_id', $events)
|
||||
)->executeStatement();
|
||||
|
||||
// Delete remaining leads as the new lead already belongs
|
||||
$this->_em->getConnection()->createQueryBuilder()
|
||||
->delete(MAUTIC_TABLE_PREFIX.'point_lead_event_log')
|
||||
->where('lead_id = '.(int) $fromLeadId)
|
||||
->executeStatement();
|
||||
} else {
|
||||
$q->executeStatement();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,446 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\PointBundle\Entity;
|
||||
|
||||
use ApiPlatform\Metadata\ApiResource;
|
||||
use ApiPlatform\Metadata\Delete;
|
||||
use ApiPlatform\Metadata\Get;
|
||||
use ApiPlatform\Metadata\GetCollection;
|
||||
use ApiPlatform\Metadata\Patch;
|
||||
use ApiPlatform\Metadata\Post;
|
||||
use ApiPlatform\Metadata\Put;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Mautic\ApiBundle\Serializer\Driver\ApiMetadataDriver;
|
||||
use Mautic\CategoryBundle\Entity\Category;
|
||||
use Mautic\CoreBundle\Doctrine\Mapping\ClassMetadataBuilder;
|
||||
use Mautic\CoreBundle\Entity\FormEntity;
|
||||
use Mautic\CoreBundle\Entity\UuidInterface;
|
||||
use Mautic\CoreBundle\Entity\UuidTrait;
|
||||
use Mautic\CoreBundle\Helper\IntHelper;
|
||||
use Mautic\ProjectBundle\Entity\ProjectTrait;
|
||||
use Symfony\Component\Serializer\Attribute\Groups;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
use Symfony\Component\Validator\Mapping\ClassMetadata;
|
||||
|
||||
#[ApiResource(
|
||||
operations: [
|
||||
new GetCollection(security: "is_granted('point:triggers:viewown')"),
|
||||
new Post(security: "is_granted('point:triggers:create')"),
|
||||
new Get(security: "is_granted('point:triggers:viewown')"),
|
||||
new Put(security: "is_granted('point:triggers:editown')"),
|
||||
new Patch(security: "is_granted('point:triggers:editother')"),
|
||||
new Delete(security: "is_granted('point:triggers:deleteown')"),
|
||||
],
|
||||
normalizationContext: [
|
||||
'groups' => ['point:read'],
|
||||
'swagger_definition_name' => 'Read',
|
||||
'api_included' => ['category'],
|
||||
],
|
||||
denormalizationContext: [
|
||||
'groups' => ['point:write'],
|
||||
'swagger_definition_name' => 'Write',
|
||||
]
|
||||
)]
|
||||
class Point extends FormEntity implements UuidInterface
|
||||
{
|
||||
use UuidTrait;
|
||||
use ProjectTrait;
|
||||
public const ENTITY_NAME = 'point';
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
#[Groups(['point:read'])]
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
#[Groups(['point:read', 'point:write'])]
|
||||
private $name;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
#[Groups(['point:read', 'point:write'])]
|
||||
private $description;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
#[Groups(['point:read', 'point:write'])]
|
||||
private $type;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
#[Groups(['point:read', 'point:write'])]
|
||||
private $repeatable = false;
|
||||
|
||||
/**
|
||||
* @var \DateTimeInterface
|
||||
*/
|
||||
#[Groups(['point:read', 'point:write'])]
|
||||
private $publishUp;
|
||||
|
||||
/**
|
||||
* @var \DateTimeInterface
|
||||
*/
|
||||
#[Groups(['point:read', 'point:write'])]
|
||||
private $publishDown;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
#[Groups(['point:read', 'point:write'])]
|
||||
private $delta = 0;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
#[Groups(['point:read', 'point:write'])]
|
||||
private $properties = [];
|
||||
|
||||
/**
|
||||
* @var ArrayCollection<int,LeadPointLog>
|
||||
*/
|
||||
private $log;
|
||||
|
||||
/**
|
||||
* @var Category|null
|
||||
**/
|
||||
#[Groups(['point:read', 'point:write'])]
|
||||
private $category;
|
||||
|
||||
#[Groups(['point:read', 'point:write'])]
|
||||
private ?Group $group = null;
|
||||
|
||||
public function __clone()
|
||||
{
|
||||
$this->id = null;
|
||||
|
||||
parent::__clone();
|
||||
}
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->log = new ArrayCollection();
|
||||
$this->initializeProjects();
|
||||
}
|
||||
|
||||
public static function loadMetadata(ORM\ClassMetadata $metadata): void
|
||||
{
|
||||
$builder = new ClassMetadataBuilder($metadata);
|
||||
|
||||
$builder->setTable('points')
|
||||
->setCustomRepositoryClass(PointRepository::class)
|
||||
->addIndex(['type'], 'point_type_search');
|
||||
|
||||
$builder->addIdColumns();
|
||||
|
||||
$builder->createField('type', 'string')
|
||||
->length(50)
|
||||
->build();
|
||||
|
||||
$builder->addPublishDates();
|
||||
|
||||
$builder->createField('repeatable', 'boolean')
|
||||
->build();
|
||||
|
||||
$builder->addField('delta', 'integer');
|
||||
|
||||
$builder->addField('properties', 'array');
|
||||
|
||||
$builder->createOneToMany('log', 'LeadPointLog')
|
||||
->mappedBy('point')
|
||||
->cascadePersist()
|
||||
->cascadeRemove()
|
||||
->fetchExtraLazy()
|
||||
->build();
|
||||
|
||||
$builder->addCategory();
|
||||
|
||||
$builder->createManyToOne('group', Group::class)
|
||||
->addJoinColumn('group_id', 'id', true, false, 'CASCADE')
|
||||
->build();
|
||||
|
||||
static::addUuidField($builder);
|
||||
self::addProjectsField($builder, 'point_projects_xref', 'point_id');
|
||||
}
|
||||
|
||||
public static function loadValidatorMetadata(ClassMetadata $metadata): void
|
||||
{
|
||||
$metadata->addPropertyConstraint('name', new Assert\NotBlank([
|
||||
'message' => 'mautic.core.name.required',
|
||||
]));
|
||||
|
||||
$metadata->addPropertyConstraint('type', new Assert\NotBlank([
|
||||
'message' => 'mautic.point.type.notblank',
|
||||
]));
|
||||
|
||||
$metadata->addPropertyConstraint('delta', new Assert\NotBlank([
|
||||
'message' => 'mautic.point.delta.notblank',
|
||||
]));
|
||||
|
||||
$metadata->addPropertyConstraint('delta', new Assert\Range([
|
||||
'min' => IntHelper::MIN_INTEGER_VALUE,
|
||||
'max' => IntHelper::MAX_INTEGER_VALUE,
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the metadata for API usage.
|
||||
*/
|
||||
public static function loadApiMetadata(ApiMetadataDriver $metadata): void
|
||||
{
|
||||
$metadata->setGroupPrefix('point')
|
||||
->addListProperties(
|
||||
[
|
||||
'id',
|
||||
'name',
|
||||
'category',
|
||||
'type',
|
||||
'description',
|
||||
]
|
||||
)
|
||||
->addProperties(
|
||||
[
|
||||
'publishUp',
|
||||
'publishDown',
|
||||
'delta',
|
||||
'properties',
|
||||
'repeatable',
|
||||
]
|
||||
)
|
||||
->build();
|
||||
|
||||
self::addProjectsInLoadApiMetadata($metadata, 'point');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $properties
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setProperties($properties)
|
||||
{
|
||||
$this->isChanged('properties', $properties);
|
||||
|
||||
$this->properties = $properties;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getProperties()
|
||||
{
|
||||
return $this->properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setType($type)
|
||||
{
|
||||
$this->isChanged('type', $type);
|
||||
$this->type = $type;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getType()
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
public function convertToArray(): array
|
||||
{
|
||||
return get_object_vars($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $description
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setDescription($description)
|
||||
{
|
||||
$this->isChanged('description', $description);
|
||||
$this->description = $description;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getDescription()
|
||||
{
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setName($name)
|
||||
{
|
||||
$this->isChanged('name', $name);
|
||||
$this->name = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return self
|
||||
*/
|
||||
public function addLog(LeadPointLog $log)
|
||||
{
|
||||
$this->log[] = $log;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeLog(LeadPointLog $log): void
|
||||
{
|
||||
$this->log->removeElement($log);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Doctrine\Common\Collections\Collection
|
||||
*/
|
||||
public function getLog()
|
||||
{
|
||||
return $this->log;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DateTime $publishUp
|
||||
*
|
||||
* @return Point
|
||||
*/
|
||||
public function setPublishUp($publishUp)
|
||||
{
|
||||
$this->isChanged('publishUp', $publishUp);
|
||||
$this->publishUp = $publishUp;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \DateTimeInterface
|
||||
*/
|
||||
public function getPublishUp()
|
||||
{
|
||||
return $this->publishUp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DateTime $publishDown
|
||||
*
|
||||
* @return Point
|
||||
*/
|
||||
public function setPublishDown($publishDown)
|
||||
{
|
||||
$this->isChanged('publishDown', $publishDown);
|
||||
$this->publishDown = $publishDown;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \DateTimeInterface
|
||||
*/
|
||||
public function getPublishDown()
|
||||
{
|
||||
return $this->publishDown;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getCategory()
|
||||
{
|
||||
return $this->category;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $category
|
||||
*/
|
||||
public function setCategory($category): void
|
||||
{
|
||||
$this->category = $category;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getDelta()
|
||||
{
|
||||
return $this->delta;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $delta
|
||||
*/
|
||||
public function setDelta($delta): void
|
||||
{
|
||||
$this->delta = (int) $delta;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $repeatable
|
||||
*
|
||||
* @return Point
|
||||
*/
|
||||
public function setRepeatable($repeatable)
|
||||
{
|
||||
$this->isChanged('repeatable', $repeatable);
|
||||
$this->repeatable = $repeatable;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function getRepeatable()
|
||||
{
|
||||
return $this->repeatable;
|
||||
}
|
||||
|
||||
public function getGroup(): ?Group
|
||||
{
|
||||
return $this->group;
|
||||
}
|
||||
|
||||
public function setGroup(?Group $group): void
|
||||
{
|
||||
$this->group = $group;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\PointBundle\Entity;
|
||||
|
||||
use Mautic\CoreBundle\Entity\CommonRepository;
|
||||
use Mautic\ProjectBundle\Entity\ProjectRepositoryTrait;
|
||||
|
||||
/**
|
||||
* @extends CommonRepository<Point>
|
||||
*/
|
||||
class PointRepository extends CommonRepository
|
||||
{
|
||||
use ProjectRepositoryTrait;
|
||||
|
||||
public function getEntities(array $args = [])
|
||||
{
|
||||
$q = $this->_em
|
||||
->createQueryBuilder()
|
||||
->select($this->getTableAlias().', cat')
|
||||
->from(Point::class, $this->getTableAlias())
|
||||
->leftJoin($this->getTableAlias().'.category', 'cat')
|
||||
->leftJoin($this->getTableAlias().'.group', 'pl');
|
||||
|
||||
$args['qb'] = $q;
|
||||
|
||||
return parent::getEntities($args);
|
||||
}
|
||||
|
||||
public function getTableAlias(): string
|
||||
{
|
||||
return 'p';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get array of published actions based on type.
|
||||
*
|
||||
* @param string $type
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getPublishedByType($type)
|
||||
{
|
||||
$q = $this->createQueryBuilder('p')
|
||||
->select('partial p.{id, type, name, delta, repeatable, properties}')
|
||||
->setParameter('type', $type);
|
||||
|
||||
// make sure the published up and down dates are good
|
||||
$expr = $this->getPublishedByDateExpression($q);
|
||||
$expr->add($q->expr()->eq('p.type', ':type'));
|
||||
|
||||
$q->where($expr);
|
||||
|
||||
return $q->getQuery()->getResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
* @param int $leadId
|
||||
*/
|
||||
public function getCompletedLeadActions($type, $leadId): array
|
||||
{
|
||||
$q = $this->_em->getConnection()->createQueryBuilder()
|
||||
->select('p.*')
|
||||
->from(MAUTIC_TABLE_PREFIX.'point_lead_action_log', 'x')
|
||||
->innerJoin('x', MAUTIC_TABLE_PREFIX.'points', 'p', 'x.point_id = p.id');
|
||||
|
||||
// make sure the published up and down dates are good
|
||||
$q->where(
|
||||
$q->expr()->and(
|
||||
$q->expr()->eq('p.type', ':type'),
|
||||
$q->expr()->eq('x.lead_id', (int) $leadId)
|
||||
)
|
||||
)
|
||||
->setParameter('type', $type);
|
||||
|
||||
$results = $q->executeQuery()->fetchAllAssociative();
|
||||
|
||||
$return = [];
|
||||
|
||||
foreach ($results as $r) {
|
||||
$return[$r['id']] = $r;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $leadId
|
||||
*/
|
||||
public function getCompletedLeadActionsByLeadId($leadId): array
|
||||
{
|
||||
$q = $this->_em->getConnection()->createQueryBuilder()
|
||||
->select('p.*')
|
||||
->from(MAUTIC_TABLE_PREFIX.'point_lead_action_log', 'x')
|
||||
->innerJoin('x', MAUTIC_TABLE_PREFIX.'points', 'p', 'x.point_id = p.id');
|
||||
|
||||
// make sure the published up and down dates are good
|
||||
$q->where(
|
||||
$q->expr()->and(
|
||||
$q->expr()->eq('x.lead_id', (int) $leadId)
|
||||
)
|
||||
);
|
||||
|
||||
$results = $q->executeQuery()->fetchAllAssociative();
|
||||
|
||||
$return = [];
|
||||
|
||||
foreach ($results as $r) {
|
||||
$return[$r['id']] = $r;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
protected function addCatchAllWhereClause($q, $filter): array
|
||||
{
|
||||
return $this->addStandardCatchAllWhereClause($q, $filter, [
|
||||
'p.name',
|
||||
'p.description',
|
||||
]);
|
||||
}
|
||||
|
||||
protected function addSearchCommandWhereClause($q, $filter): array
|
||||
{
|
||||
return match ($filter->command) {
|
||||
$this->translator->trans('mautic.project.searchcommand.name'), $this->translator->trans('mautic.project.searchcommand.name', [], null, 'en_US') => $this->handleProjectFilter(
|
||||
$this->_em->getConnection()->createQueryBuilder(),
|
||||
'point_id',
|
||||
'point_projects_xref',
|
||||
$this->getTableAlias(),
|
||||
$filter->string,
|
||||
$filter->not
|
||||
),
|
||||
default => $this->addStandardSearchCommandWhereClause($q, $filter),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getSearchCommands(): array
|
||||
{
|
||||
return array_merge(['mautic.project.searchcommand.name'], $this->getStandardSearchCommands());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,432 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\PointBundle\Entity;
|
||||
|
||||
use ApiPlatform\Metadata\ApiResource;
|
||||
use ApiPlatform\Metadata\Delete;
|
||||
use ApiPlatform\Metadata\Get;
|
||||
use ApiPlatform\Metadata\GetCollection;
|
||||
use ApiPlatform\Metadata\Patch;
|
||||
use ApiPlatform\Metadata\Post;
|
||||
use ApiPlatform\Metadata\Put;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Mautic\ApiBundle\Serializer\Driver\ApiMetadataDriver;
|
||||
use Mautic\CategoryBundle\Entity\Category;
|
||||
use Mautic\CoreBundle\Doctrine\Mapping\ClassMetadataBuilder;
|
||||
use Mautic\CoreBundle\Entity\FormEntity;
|
||||
use Mautic\CoreBundle\Entity\UuidInterface;
|
||||
use Mautic\CoreBundle\Entity\UuidTrait;
|
||||
use Mautic\ProjectBundle\Entity\ProjectTrait;
|
||||
use Symfony\Component\Serializer\Attribute\Groups;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
use Symfony\Component\Validator\Mapping\ClassMetadata;
|
||||
|
||||
#[ApiResource(
|
||||
operations: [
|
||||
new GetCollection(security: "is_granted('point:triggers:viewown')"),
|
||||
new Post(security: "is_granted('point:triggers:create')"),
|
||||
new Get(security: "is_granted('point:triggers:viewown')"),
|
||||
new Put(security: "is_granted('point:triggers:editown')"),
|
||||
new Patch(security: "is_granted('point:triggers:editother')"),
|
||||
new Delete(security: "is_granted('point:triggers:deleteown')"),
|
||||
],
|
||||
normalizationContext: [
|
||||
'groups' => ['trigger:read'],
|
||||
'swagger_definition_name' => 'Read',
|
||||
'api_included' => ['category', 'events'],
|
||||
],
|
||||
denormalizationContext: [
|
||||
'groups' => ['trigger:write'],
|
||||
'swagger_definition_name' => 'Write',
|
||||
]
|
||||
)]
|
||||
class Trigger extends FormEntity implements UuidInterface
|
||||
{
|
||||
use UuidTrait;
|
||||
use ProjectTrait;
|
||||
public const ENTITY_NAME = 'point_trigger';
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
#[Groups(['trigger:read'])]
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
#[Groups(['trigger:read', 'trigger:write'])]
|
||||
private $name;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
#[Groups(['trigger:read', 'trigger:write'])]
|
||||
private $description;
|
||||
|
||||
/**
|
||||
* @var \DateTimeInterface
|
||||
*/
|
||||
#[Groups(['trigger:read', 'trigger:write'])]
|
||||
private $publishUp;
|
||||
|
||||
/**
|
||||
* @var \DateTimeInterface
|
||||
*/
|
||||
#[Groups(['trigger:read', 'trigger:write'])]
|
||||
private $publishDown;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
#[Groups(['trigger:read', 'trigger:write'])]
|
||||
private $points = 0;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
#[Groups(['trigger:read', 'trigger:write'])]
|
||||
private $color = 'a0acb8';
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
#[Groups(['trigger:read', 'trigger:write'])]
|
||||
private $triggerExistingLeads = false;
|
||||
|
||||
/**
|
||||
* @var Category|null
|
||||
**/
|
||||
#[Groups(['trigger:read', 'trigger:write'])]
|
||||
private $category;
|
||||
|
||||
/**
|
||||
* @var ArrayCollection<int, TriggerEvent>
|
||||
*/
|
||||
#[Groups(['trigger:read', 'trigger:write'])]
|
||||
private $events;
|
||||
|
||||
#[Groups(['trigger:read', 'trigger:write'])]
|
||||
private ?Group $group = null;
|
||||
|
||||
public function __clone()
|
||||
{
|
||||
$this->id = null;
|
||||
|
||||
parent::__clone();
|
||||
}
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->events = new ArrayCollection();
|
||||
$this->initializeProjects();
|
||||
}
|
||||
|
||||
public static function loadMetadata(ORM\ClassMetadata $metadata): void
|
||||
{
|
||||
$builder = new ClassMetadataBuilder($metadata);
|
||||
|
||||
$builder->setTable('point_triggers')
|
||||
->setCustomRepositoryClass(TriggerRepository::class);
|
||||
|
||||
$builder->addIdColumns();
|
||||
|
||||
$builder->addPublishDates();
|
||||
|
||||
$builder->addField('points', 'integer');
|
||||
|
||||
$builder->createField('color', 'string')
|
||||
->length(7)
|
||||
->build();
|
||||
|
||||
$builder->createField('triggerExistingLeads', 'boolean')
|
||||
->columnName('trigger_existing_leads')
|
||||
->build();
|
||||
|
||||
$builder->addCategory();
|
||||
|
||||
$builder->createOneToMany('events', 'TriggerEvent')
|
||||
->setIndexBy('id')
|
||||
->setOrderBy(['order' => 'ASC'])
|
||||
->mappedBy('trigger')
|
||||
->cascadeAll()
|
||||
->fetchExtraLazy()
|
||||
->build();
|
||||
|
||||
$builder->createManyToOne('group', Group::class)
|
||||
->addJoinColumn('group_id', 'id', true, false, 'CASCADE')
|
||||
->build();
|
||||
|
||||
static::addUuidField($builder);
|
||||
self::addProjectsField($builder, 'point_trigger_projects_xref', 'point_trigger_id');
|
||||
}
|
||||
|
||||
public static function loadValidatorMetadata(ClassMetadata $metadata): void
|
||||
{
|
||||
$metadata->addPropertyConstraint('name', new Assert\NotBlank([
|
||||
'message' => 'mautic.core.name.required',
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the metadata for API usage.
|
||||
*/
|
||||
public static function loadApiMetadata(ApiMetadataDriver $metadata): void
|
||||
{
|
||||
$metadata->setGroupPrefix('trigger')
|
||||
->addListProperties(
|
||||
[
|
||||
'id',
|
||||
'name',
|
||||
'category',
|
||||
'description',
|
||||
]
|
||||
)
|
||||
->addProperties(
|
||||
[
|
||||
'publishUp',
|
||||
'publishDown',
|
||||
'points',
|
||||
'color',
|
||||
'events',
|
||||
'triggerExistingLeads',
|
||||
]
|
||||
)
|
||||
->build();
|
||||
|
||||
self::addProjectsInLoadApiMetadata($metadata, 'trigger');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $prop
|
||||
* @param mixed $val
|
||||
*/
|
||||
protected function isChanged($prop, $val)
|
||||
{
|
||||
if ('events' == $prop) {
|
||||
// changes are already computed so just add them
|
||||
$this->changes[$prop][$val[0]] = $val[1];
|
||||
} else {
|
||||
parent::isChanged($prop, $val);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get id.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set description.
|
||||
*
|
||||
* @param string $description
|
||||
*
|
||||
* @return Trigger
|
||||
*/
|
||||
public function setDescription($description)
|
||||
{
|
||||
$this->isChanged('description', $description);
|
||||
$this->description = $description;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get description.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDescription()
|
||||
{
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set name.
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return Trigger
|
||||
*/
|
||||
public function setName($name)
|
||||
{
|
||||
$this->isChanged('name', $name);
|
||||
$this->name = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add events.
|
||||
*
|
||||
* @return Point
|
||||
*/
|
||||
public function addTriggerEvent($key, TriggerEvent $event)
|
||||
{
|
||||
if ($changes = $event->getChanges()) {
|
||||
$this->isChanged('events', [$key, $changes]);
|
||||
}
|
||||
$this->events[$key] = $event;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove events.
|
||||
*/
|
||||
public function removeTriggerEvent(TriggerEvent $event): void
|
||||
{
|
||||
$this->events->removeElement($event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get events.
|
||||
*
|
||||
* @return \Doctrine\Common\Collections\Collection
|
||||
*/
|
||||
public function getEvents()
|
||||
{
|
||||
return $this->events;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set publishUp.
|
||||
*
|
||||
* @param \DateTime $publishUp
|
||||
*
|
||||
* @return Point
|
||||
*/
|
||||
public function setPublishUp($publishUp)
|
||||
{
|
||||
$this->isChanged('publishUp', $publishUp);
|
||||
$this->publishUp = $publishUp;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get publishUp.
|
||||
*
|
||||
* @return \DateTimeInterface
|
||||
*/
|
||||
public function getPublishUp()
|
||||
{
|
||||
return $this->publishUp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set publishDown.
|
||||
*
|
||||
* @param \DateTime $publishDown
|
||||
*
|
||||
* @return Point
|
||||
*/
|
||||
public function setPublishDown($publishDown)
|
||||
{
|
||||
$this->isChanged('publishDown', $publishDown);
|
||||
$this->publishDown = $publishDown;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get publishDown.
|
||||
*
|
||||
* @return \DateTimeInterface
|
||||
*/
|
||||
public function getPublishDown()
|
||||
{
|
||||
return $this->publishDown;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getPoints()
|
||||
{
|
||||
return $this->points;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $points
|
||||
*/
|
||||
public function setPoints($points): void
|
||||
{
|
||||
$this->isChanged('points', $points);
|
||||
$this->points = $points;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getColor()
|
||||
{
|
||||
return $this->color;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $color
|
||||
*/
|
||||
public function setColor($color): void
|
||||
{
|
||||
$this->color = $color;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getTriggerExistingLeads()
|
||||
{
|
||||
return $this->triggerExistingLeads;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $triggerExistingLeads
|
||||
*/
|
||||
public function setTriggerExistingLeads($triggerExistingLeads): void
|
||||
{
|
||||
$this->triggerExistingLeads = $triggerExistingLeads;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getCategory()
|
||||
{
|
||||
return $this->category;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $category
|
||||
*/
|
||||
public function setCategory($category): void
|
||||
{
|
||||
$this->category = $category;
|
||||
}
|
||||
|
||||
public function getGroup(): ?Group
|
||||
{
|
||||
return $this->group;
|
||||
}
|
||||
|
||||
public function setGroup(Group $group): void
|
||||
{
|
||||
$this->group = $group;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,333 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\PointBundle\Entity;
|
||||
|
||||
use ApiPlatform\Metadata\ApiResource;
|
||||
use ApiPlatform\Metadata\Delete;
|
||||
use ApiPlatform\Metadata\Get;
|
||||
use ApiPlatform\Metadata\GetCollection;
|
||||
use ApiPlatform\Metadata\Patch;
|
||||
use ApiPlatform\Metadata\Post;
|
||||
use ApiPlatform\Metadata\Put;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Mautic\ApiBundle\Serializer\Driver\ApiMetadataDriver;
|
||||
use Mautic\CoreBundle\Doctrine\Mapping\ClassMetadataBuilder;
|
||||
use Mautic\CoreBundle\Entity\UuidInterface;
|
||||
use Mautic\CoreBundle\Entity\UuidTrait;
|
||||
use Symfony\Component\Serializer\Attribute\Groups;
|
||||
|
||||
#[ApiResource(
|
||||
operations: [
|
||||
new GetCollection(security: "is_granted('point:triggers:viewown')"),
|
||||
new Post(security: "is_granted('point:triggers:create')"),
|
||||
new Get(security: "is_granted('point:triggers:viewown')"),
|
||||
new Put(security: "is_granted('point:triggers:editown')"),
|
||||
new Patch(security: "is_granted('point:triggers:editother')"),
|
||||
new Delete(security: "is_granted('point:triggers:deleteown')"),
|
||||
],
|
||||
normalizationContext: [
|
||||
'groups' => ['trigger_event:read'],
|
||||
'swagger_definition_name' => 'Read',
|
||||
],
|
||||
denormalizationContext: [
|
||||
'groups' => ['trigger_event:write'],
|
||||
'swagger_definition_name' => 'Write',
|
||||
]
|
||||
)]
|
||||
class TriggerEvent implements UuidInterface
|
||||
{
|
||||
use UuidTrait;
|
||||
|
||||
/**
|
||||
* @var int|null
|
||||
*/
|
||||
#[Groups(['trigger_event:read'])]
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
#[Groups(['trigger_event:read', 'trigger_event:write'])]
|
||||
private $name;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
#[Groups(['trigger_event:read', 'trigger_event:write'])]
|
||||
private $description;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
#[Groups(['trigger_event:read', 'trigger_event:write'])]
|
||||
private $type;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
#[Groups(['trigger_event:read', 'trigger_event:write'])]
|
||||
private $order = 0;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
#[Groups(['trigger_event:read', 'trigger_event:write'])]
|
||||
private $properties = [];
|
||||
|
||||
/**
|
||||
* @var Trigger
|
||||
*/
|
||||
#[Groups(['trigger_event:read', 'trigger_event:write'])]
|
||||
private $trigger;
|
||||
|
||||
/**
|
||||
* @var ArrayCollection<int,LeadTriggerLog>
|
||||
*/
|
||||
private $log;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $changes;
|
||||
|
||||
public function __clone(): void
|
||||
{
|
||||
$this->id = null;
|
||||
}
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->log = new ArrayCollection();
|
||||
}
|
||||
|
||||
public static function loadMetadata(ORM\ClassMetadata $metadata): void
|
||||
{
|
||||
$builder = new ClassMetadataBuilder($metadata);
|
||||
|
||||
$builder->setTable('point_trigger_events')
|
||||
->setCustomRepositoryClass(TriggerEventRepository::class)
|
||||
->addIndex(['type'], 'trigger_type_search');
|
||||
|
||||
$builder->addIdColumns();
|
||||
|
||||
$builder->createField('type', 'string')
|
||||
->length(50)
|
||||
->build();
|
||||
|
||||
$builder->createField('order', 'integer')
|
||||
->columnName('action_order')
|
||||
->build();
|
||||
|
||||
$builder->addField('properties', 'array');
|
||||
|
||||
$builder->createManyToOne('trigger', 'Trigger')
|
||||
->inversedBy('events')
|
||||
->addJoinColumn('trigger_id', 'id', false, false, 'CASCADE')
|
||||
->build();
|
||||
|
||||
$builder->createOneToMany('log', 'LeadTriggerLog')
|
||||
->mappedBy('event')
|
||||
->cascadePersist()
|
||||
->cascadeRemove()
|
||||
->fetchExtraLazy()
|
||||
->build();
|
||||
|
||||
static::addUuidField($builder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the metadata for API usage.
|
||||
*/
|
||||
public static function loadApiMetadata(ApiMetadataDriver $metadata): void
|
||||
{
|
||||
$metadata->setGroupPrefix('trigger')
|
||||
->addProperties(
|
||||
[
|
||||
'id',
|
||||
'name',
|
||||
'description',
|
||||
'type',
|
||||
'order',
|
||||
'properties',
|
||||
]
|
||||
)
|
||||
->build();
|
||||
}
|
||||
|
||||
private function isChanged($prop, $val): void
|
||||
{
|
||||
if ($this->$prop != $val) {
|
||||
$this->changes[$prop] = [$this->$prop, $val];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getChanges()
|
||||
{
|
||||
return $this->changes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $order
|
||||
*
|
||||
* @return TriggerEvent
|
||||
*/
|
||||
public function setOrder($order)
|
||||
{
|
||||
$this->isChanged('order', $order);
|
||||
|
||||
$this->order = $order;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getOrder()
|
||||
{
|
||||
return $this->order;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $properties
|
||||
*
|
||||
* @return TriggerEvent
|
||||
*/
|
||||
public function setProperties($properties)
|
||||
{
|
||||
$this->isChanged('properties', $properties);
|
||||
|
||||
$this->properties = $properties;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getProperties()
|
||||
{
|
||||
return $this->properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return self
|
||||
*/
|
||||
public function setTrigger(Trigger $trigger)
|
||||
{
|
||||
$this->trigger = $trigger;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Trigger
|
||||
*/
|
||||
public function getTrigger()
|
||||
{
|
||||
return $this->trigger;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
*
|
||||
* @return TriggerEvent
|
||||
*/
|
||||
public function setType($type)
|
||||
{
|
||||
$this->isChanged('type', $type);
|
||||
$this->type = $type;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getType()
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
public function convertToArray(): array
|
||||
{
|
||||
return get_object_vars($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $description
|
||||
*
|
||||
* @return TriggerEvent
|
||||
*/
|
||||
public function setDescription($description)
|
||||
{
|
||||
$this->isChanged('description', $description);
|
||||
$this->description = $description;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getDescription()
|
||||
{
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
*
|
||||
* @return TriggerEvent
|
||||
*/
|
||||
public function setName($name)
|
||||
{
|
||||
$this->isChanged('name', $name);
|
||||
$this->name = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return self
|
||||
*/
|
||||
public function addLog(LeadTriggerLog $log)
|
||||
{
|
||||
$this->log[] = $log;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeLog(LeadTriggerLog $log): void
|
||||
{
|
||||
$this->log->removeElement($log);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Doctrine\Common\Collections\Collection
|
||||
*/
|
||||
public function getLog()
|
||||
{
|
||||
return $this->log;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\PointBundle\Entity;
|
||||
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Mautic\CoreBundle\Entity\CommonRepository;
|
||||
|
||||
/**
|
||||
* @extends CommonRepository<TriggerEvent>
|
||||
*/
|
||||
class TriggerEventRepository extends CommonRepository
|
||||
{
|
||||
/**
|
||||
* Get array of published triggers based on point total.
|
||||
*
|
||||
* @param int $points
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getPublishedByPointTotal($points)
|
||||
{
|
||||
$q = $this->createQueryBuilder('a')
|
||||
->select('partial a.{id, type, name, properties}, partial r.{id, name, points, color}')
|
||||
->leftJoin('a.trigger', 'r')
|
||||
->orderBy('a.order,r.points');
|
||||
|
||||
// make sure the published up and down dates are good
|
||||
$expr = $this->getPublishedByDateExpression($q, 'r');
|
||||
|
||||
$expr->add(
|
||||
$q->expr()->lte('r.points', (int) $points)
|
||||
);
|
||||
|
||||
$q->where($expr);
|
||||
$q->andWhere('r.group IS NULL');
|
||||
|
||||
return $q->getQuery()->getArrayResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ArrayCollection<int,GroupContactScore> $groupScores
|
||||
*
|
||||
* @return mixed[]
|
||||
*/
|
||||
public function getPublishedByGroupScore(Collection $groupScores)
|
||||
{
|
||||
if ($groupScores->isEmpty()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$q = $this->createQueryBuilder('a')
|
||||
->select('partial a.{id, type, name, properties}, partial r.{id, name, points, color}, partial pl.{id, name}')
|
||||
->leftJoin('a.trigger', 'r')
|
||||
->leftJoin('r.group', 'pl')
|
||||
->orderBy('a.order');
|
||||
|
||||
// make sure the published up and down dates are good
|
||||
$expr = $this->getPublishedByDateExpression($q, 'r');
|
||||
|
||||
$groupsExpr = $q->expr()->orX();
|
||||
/** @var GroupContactScore $score */
|
||||
foreach ($groupScores as $score) {
|
||||
$groupsExpr->add(
|
||||
$q->expr()->andX(
|
||||
$q->expr()->eq('pl.id', $score->getGroup()->getId()),
|
||||
$q->expr()->lte('r.points', $score->getScore())
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$q->where($expr);
|
||||
$q->andWhere($groupsExpr);
|
||||
$q->andWhere('r.group IS NOT NULL');
|
||||
|
||||
return $q->getQuery()->getArrayResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get array of published actions based on type.
|
||||
*
|
||||
* @param string $type
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getPublishedByType($type)
|
||||
{
|
||||
$q = $this->createQueryBuilder('e')
|
||||
->select('partial e.{id, type, name, properties}, partial t.{id, name, points, color}')
|
||||
->join('e.trigger', 't')
|
||||
->orderBy('e.order');
|
||||
|
||||
// make sure the published up and down dates are good
|
||||
$expr = $this->getPublishedByDateExpression($q);
|
||||
$expr->add(
|
||||
$q->expr()->eq('e.type', ':type')
|
||||
);
|
||||
$q->where($expr)
|
||||
->setParameter('type', $type);
|
||||
|
||||
return $q->getQuery()->getResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $leadId
|
||||
*/
|
||||
public function getLeadTriggeredEvents($leadId): array
|
||||
{
|
||||
$q = $this->_em->getConnection()->createQueryBuilder()
|
||||
->select('e.*')
|
||||
->from(MAUTIC_TABLE_PREFIX.'point_lead_event_log', 'x')
|
||||
->innerJoin('x', MAUTIC_TABLE_PREFIX.'point_trigger_events', 'e', 'x.event_id = e.id')
|
||||
->innerJoin('e', MAUTIC_TABLE_PREFIX.'point_triggers', 't', 'e.trigger_id = t.id');
|
||||
|
||||
// make sure the published up and down dates are good
|
||||
$q->where($q->expr()->eq('x.lead_id', (int) $leadId));
|
||||
|
||||
$results = $q->executeQuery()->fetchAllAssociative();
|
||||
|
||||
$return = [];
|
||||
|
||||
foreach ($results as $r) {
|
||||
$return[$r['id']] = $r;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $eventId
|
||||
*/
|
||||
public function getLeadsForEvent($eventId): array
|
||||
{
|
||||
$results = $this->_em->getConnection()->createQueryBuilder()
|
||||
->select('e.lead_id')
|
||||
->from(MAUTIC_TABLE_PREFIX.'point_lead_event_log', 'e')
|
||||
->where('e.event_id = '.(int) $eventId)
|
||||
->executeQuery()
|
||||
->fetchAllAssociative();
|
||||
|
||||
$return = [];
|
||||
|
||||
foreach ($results as $r) {
|
||||
$return[] = $r['lead_id'];
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\PointBundle\Entity;
|
||||
|
||||
use Doctrine\Common\Collections\Order;
|
||||
use Mautic\CoreBundle\Entity\CommonRepository;
|
||||
use Mautic\ProjectBundle\Entity\ProjectRepositoryTrait;
|
||||
|
||||
/**
|
||||
* @extends CommonRepository<Trigger>
|
||||
*/
|
||||
class TriggerRepository extends CommonRepository
|
||||
{
|
||||
use ProjectRepositoryTrait;
|
||||
|
||||
public function getEntities(array $args = [])
|
||||
{
|
||||
$q = $this->_em
|
||||
->createQueryBuilder()
|
||||
->select($this->getTableAlias().', cat')
|
||||
->from(Trigger::class, $this->getTableAlias())
|
||||
->leftJoin($this->getTableAlias().'.category', 'cat')
|
||||
->leftJoin($this->getTableAlias().'.group', 'pl');
|
||||
|
||||
$args['qb'] = $q;
|
||||
|
||||
return parent::getEntities($args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of published triggers with color and points.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getTriggerColors()
|
||||
{
|
||||
$q = $this->_em->createQueryBuilder()
|
||||
->select('partial t.{id, color, points}')
|
||||
->from(Trigger::class, 't', 't.id');
|
||||
|
||||
$q->where($this->getPublishedByDateExpression($q));
|
||||
$q->orderBy('t.points', Order::Ascending->value);
|
||||
|
||||
return $q->getQuery()->getArrayResult();
|
||||
}
|
||||
|
||||
public function getTableAlias(): string
|
||||
{
|
||||
return 't';
|
||||
}
|
||||
|
||||
protected function addCatchAllWhereClause($q, $filter): array
|
||||
{
|
||||
return $this->addStandardCatchAllWhereClause($q, $filter, [
|
||||
't.name',
|
||||
't.description',
|
||||
]);
|
||||
}
|
||||
|
||||
protected function addSearchCommandWhereClause($q, $filter): array
|
||||
{
|
||||
return match ($filter->command) {
|
||||
$this->translator->trans('mautic.project.searchcommand.name'), $this->translator->trans('mautic.project.searchcommand.name', [], null, 'en_US') => $this->handleProjectFilter(
|
||||
$this->_em->getConnection()->createQueryBuilder(),
|
||||
'point_trigger_id',
|
||||
'point_trigger_projects_xref',
|
||||
$this->getTableAlias(),
|
||||
$filter->string,
|
||||
$filter->not
|
||||
),
|
||||
// Handle standard search commands
|
||||
default => $this->addStandardSearchCommandWhereClause($q, $filter),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getSearchCommands(): array
|
||||
{
|
||||
return array_merge(['mautic.project.searchcommand.name'], $this->getStandardSearchCommands());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user