Initial commit: CloudOps infrastructure platform

This commit is contained in:
root
2026-04-09 19:58:57 +02:00
commit 1166a52f26
7762 changed files with 839452 additions and 0 deletions

View File

@@ -0,0 +1,120 @@
<?php
namespace Mautic\CampaignBundle\Event;
use Doctrine\Common\Collections\ArrayCollection;
use Mautic\CampaignBundle\Entity\Event;
use Mautic\CampaignBundle\Entity\LeadEventLog;
use Mautic\CampaignBundle\EventCollector\Accessor\Event\AbstractEventAccessor;
use Mautic\CampaignBundle\Executioner\Exception\NoContactsFoundException;
use Mautic\LeadBundle\Entity\Lead;
abstract class AbstractLogCollectionEvent extends \Symfony\Contracts\EventDispatcher\Event
{
/**
* @var ArrayCollection
*/
protected $logs;
/**
* @var ArrayCollection|Lead[]
*/
private ArrayCollection $contacts;
private array $logContactXref = [];
public function __construct(
protected AbstractEventAccessor $config,
protected Event $event,
ArrayCollection $logs,
) {
$this->logs = $logs;
$this->contacts = new ArrayCollection();
$this->extractContacts();
}
/**
* @return AbstractEventAccessor
*/
public function getConfig()
{
return $this->config;
}
/**
* @return Event
*/
public function getEvent()
{
return $this->event;
}
/**
* Return an array of Lead entities keyed by LeadEventLog ID.
*
* @return Lead[]|ArrayCollection
*/
public function getContacts()
{
return $this->contacts;
}
/**
* @return ArrayCollection
*/
public function getContactsKeyedById()
{
$contacts = new ArrayCollection();
/** @var Lead $contact */
foreach ($this->contacts as $contact) {
$contacts->set($contact->getId(), $contact);
}
return $contacts;
}
/**
* Get the IDs of all contacts affected by this event.
*
* @return array
*/
public function getContactIds()
{
$contactIds = array_keys($this->logContactXref);
return array_combine($contactIds, $contactIds);
}
/**
* @param int $id
*
* @return LeadEventLog
*
* @throws NoContactsFoundException
*/
public function findLogByContactId($id)
{
if (!isset($this->logContactXref[$id])) {
throw new NoContactsFoundException("$id not found");
}
if (!$this->logs->offsetExists($this->logContactXref[$id])) {
throw new NoContactsFoundException("$id was found in the xref table but no log was found");
}
return $this->logs->get($this->logContactXref[$id]);
}
private function extractContacts(): void
{
/** @var LeadEventLog $log */
foreach ($this->logs as $log) {
$contact = $log->getLead();
$this->logContactXref[$contact->getId()] = $log->getId();
$this->contacts->set($log->getId(), $contact);
}
}
}

View File

@@ -0,0 +1,199 @@
<?php
namespace Mautic\CampaignBundle\Event;
use Mautic\CampaignBundle\Event\Exception\KeyAlreadyRegisteredException;
use Mautic\CoreBundle\Event\ComponentValidationTrait;
use Symfony\Contracts\EventDispatcher\Event;
use Symfony\Contracts\Translation\TranslatorInterface;
class CampaignBuilderEvent extends Event
{
use ComponentValidationTrait;
private array $decisions = [];
private array $conditions = [];
private array $actions = [];
/**
* Holds info if some property has been already sorted or not.
*/
private array $sortCache = [];
public function __construct(
private TranslatorInterface $translator,
) {
}
/**
* Add an lead decision to the list of available .
*
* @param string $key a unique identifier; it is recommended that it be namespaced i.e. lead.mytrigger
* @param array $decision can contain the following keys:
* $decision = [
* 'label' => (required) what to display in the list
* 'eventName' => (required) The event name to fire when this event is triggered.
* 'description' => (optional) short description of event
* 'formType' => (optional) name of the form type SERVICE for the action
* 'formTypeOptions' => (optional) array of options to pass to the formType service
* 'formTheme' => (optional) form theme
* 'connectionRestrictions' => (optional) Array of events to restrict this event to. Implicit events
* [
* 'anchor' => [], // array of anchors this event should _not_ be allowed to connect to in the format of eventType.anchorName, e.g. decision.no
* 'source' => ['action' => [], 'decision' => [], 'condition' => []], // array of event keys allowed to connect into this event
* 'target' => ['action' => [], 'decision' => [], 'condition' => []], // array of event keys allowed to flow from this event
* ]
* ]
*/
public function addDecision($key, array $decision): void
{
if (array_key_exists($key, $this->decisions)) {
throw new KeyAlreadyRegisteredException("The key, '$key' is already used by another contact action. Please use a different key.");
}
// check for required keys and that given functions are callable
$this->verifyComponent(
['label', ['eventName', 'callback']],
$decision,
['callback']
);
$decision['label'] = $this->translator->trans($decision['label']);
$decision['description'] = (isset($decision['description'])) ? $this->translator->trans($decision['description']) : '';
$this->decisions[$key] = $decision;
}
/**
* @return mixed
*/
public function getDecisions()
{
return $this->sort('decisions');
}
/**
* Add an lead condition to the list of available conditions.
*
* @param string $key a unique identifier; it is recommended that it be namespaced i.e. lead.mytrigger
* @param array $event can contain the following keys:
* $condition = [
* 'label' => (required) what to display in the list
* 'eventName' => (required) The event name to fire when this event is triggered.
* 'description' => (optional) short description of event
* 'formType' => (optional) name of the form type SERVICE for the action
* 'formTypeOptions' => (optional) array of options to pass to the formType service
* 'formTheme' => (optional) form theme
* 'connectionRestrictions' => (optional) Array of events to restrict this event to. Implicit events
* [
* 'anchor' => [], // array of anchors this event should _not_ be allowed to connect to in the format of eventType.anchorName, e.g. decision.no
* 'source' => ['action' => [], 'decision' => [], 'condition' => []], // array of event keys allowed to connect into this event
* 'target' => ['action' => [], 'decision' => [], 'condition' => []], // array of event keys allowed to flow from this event
* ]
* ]
*/
public function addCondition($key, array $event): void
{
if (array_key_exists($key, $this->conditions)) {
throw new KeyAlreadyRegisteredException("The key, '$key' is already used by another contact action. Please use a different key.");
}
// check for required keys and that given functions are callable
$this->verifyComponent(
['label', ['eventName', 'callback']],
$event,
['callback']
);
$event['label'] = $this->translator->trans($event['label']);
$event['description'] = (isset($event['description'])) ? $this->translator->trans($event['description']) : '';
$this->conditions[$key] = $event;
}
/**
* Get lead conditions.
*
* @return array
*/
public function getConditions()
{
return $this->sort('conditions');
}
/**
* Add an action to the list of available .
*
* @param string $key a unique identifier; it is recommended that it be namespaced i.e. lead.action
* @param array $action can contain the following keys:
* $action = [
* 'label' => (required) what to display in the list
* 'eventName' => (required) The event to fire when this event is triggered.
* 'description' => (optional) short description of event
* 'formType' => (optional) name of the form type SERVICE for the action
* 'formTypeOptions' => (optional) array of options to pass to the formType service
* 'formTheme' => (optional) form theme
* 'timelineTemplate' => (optional) custom template for the lead timeline
* 'connectionRestrictions' => (optional) Array of events to restrict this event to. Implicit events
* [
* 'anchor' => [], // array of anchors this event should _not_ be allowed to connect to in the format of eventType.anchorName, e.g. decision.no
* 'source' => ['action' => [], 'decision' => [], 'condition' => []], // array of event keys allowed to connect into this event
* 'target' => ['action' => [], 'decision' => [], 'condition' => []], // array of event keys allowed to flow from this event
* ]
* ]
*/
public function addAction($key, array $action): void
{
if (array_key_exists($key, $this->actions)) {
throw new KeyAlreadyRegisteredException("The key, '$key' is already used by another action. Please use a different key.");
}
// check for required keys and that given functions are callable
$this->verifyComponent(
['label', ['batchEventName', 'eventName', 'callback']],
$action,
['callback']
);
// translate the group
$action['label'] = $this->translator->trans($action['label']);
$action['description'] = (isset($action['description'])) ? $this->translator->trans($action['description']) : '';
$this->actions[$key] = $action;
}
/**
* Get actions.
*
* @return array
*/
public function getActions()
{
return $this->sort('actions');
}
/**
* Sort internal actions, decisions and conditions arrays.
*
* @param string $property name
*
* @return array
*/
protected function sort($property)
{
if (empty($this->sortCache[$property])) {
uasort(
$this->{$property},
fn ($a, $b): int => strnatcasecmp(
$a['label'],
$b['label']
)
);
$this->sortCache[$property] = true;
}
return $this->{$property};
}
}

View File

@@ -0,0 +1,112 @@
<?php
namespace Mautic\CampaignBundle\Event;
use Mautic\CampaignBundle\Entity\LeadEventLog;
use Symfony\Contracts\EventDispatcher\Event;
/**
* @deprecated 2.13.0; to be removed in 3.0
*/
class CampaignDecisionEvent extends Event
{
protected $decisionTriggered = false;
/**
* @param LeadEventLog[] $logs
*/
public function __construct(
protected $lead,
protected $decisionType,
protected $decisionEventDetails,
protected $events,
protected $eventSettings,
protected $isRootLevel = false,
protected $logs = [],
) {
}
/**
* @return mixed
*/
public function getLead()
{
return $this->lead;
}
/**
* @return mixed
*/
public function getEvents()
{
return $this->events;
}
/**
* @return mixed
*/
public function getDecisionType()
{
return $this->decisionType;
}
/**
* @return mixed
*/
public function getDecisionEventDetails()
{
return $this->decisionEventDetails;
}
/**
* @return bool
*/
public function getEventSettings($eventType = null, $type = null)
{
if ($type) {
return (!empty($this->eventSettings[$eventType][$type])) ? $this->eventSettings[$eventType][$type] : false;
} elseif ($eventType) {
return (!empty($this->eventSettings[$eventType])) ? $this->eventSettings[$eventType] : false;
}
return $this->eventSettings;
}
/**
* Is the decision used as a root level event?
*
* @return bool
*/
public function isRootLevel()
{
return $this->isRootLevel;
}
/**
* Set if the decision has already been triggered and if so, child events will be executed.
*
* @param bool|true $triggered
*/
public function setDecisionAlreadyTriggered($triggered = true): void
{
$this->decisionTriggered = $triggered;
}
/**
* Returns if the decision has already been triggered.
*
* @return mixed
*/
public function wasDecisionTriggered()
{
return $this->decisionTriggered;
}
/**
* @return array|LeadEventLog[]
*/
public function getLogs()
{
return $this->logs;
}
}

View File

@@ -0,0 +1,36 @@
<?php
namespace Mautic\CampaignBundle\Event;
use Mautic\CampaignBundle\Entity\Campaign;
use Mautic\CoreBundle\Event\CommonEvent;
class CampaignEvent extends CommonEvent
{
/**
* @param bool $isNew
*/
public function __construct(Campaign &$campaign, $isNew = false)
{
$this->entity = &$campaign;
$this->isNew = $isNew;
}
/**
* Returns the Campaign entity.
*
* @return Campaign
*/
public function getCampaign()
{
return $this->entity;
}
/**
* Sets the Campaign entity.
*/
public function setCampaign(Campaign $campaign): void
{
$this->entity = $campaign;
}
}

View File

@@ -0,0 +1,240 @@
<?php
namespace Mautic\CampaignBundle\Event;
use Mautic\CampaignBundle\Entity\LeadEventLog;
use Mautic\LeadBundle\Entity\Lead;
use Symfony\Contracts\EventDispatcher\Event;
/**
* @deprecated 2.13.0; to be removed in 3.0
*/
class CampaignExecutionEvent extends Event
{
use EventArrayTrait;
use ContextTrait;
/**
* @var Lead
*/
protected $lead;
/**
* @var array
*/
protected $event;
/**
* @var array
*/
protected $eventDetails;
/**
* @var bool
*/
protected $systemTriggered;
/**
* @var array
*/
protected $eventSettings;
/**
* @var bool
*/
protected $logUpdatedByListener = false;
/**
* @var string
*/
protected $channel;
/**
* @var int
*/
protected $channelId;
/**
* @param bool|mixed[]|string|null $result
*/
public function __construct(
array $args,
protected $result,
protected ?LeadEventLog $log = null,
) {
$this->lead = $args['lead'];
$this->event = $args['event'];
$this->eventDetails = $args['eventDetails'];
$this->systemTriggered = $args['systemTriggered'];
$this->eventSettings = $args['eventSettings'];
}
/**
* @return Lead
*/
public function getLead()
{
return $this->lead;
}
/**
* Returns array with lead fields and owner ID if exist.
*
* @return array
*/
public function getLeadFields()
{
$lead = $this->getLead();
$isLeadEntity = $lead instanceof Lead;
// In case Lead is a scalar value:
if (!$isLeadEntity && !is_array($lead)) {
$lead = [];
}
$leadFields = $isLeadEntity ? $lead->getProfileFields() : $lead;
$leadFields['owner_id'] = $isLeadEntity && ($owner = $lead->getOwner()) ? $owner->getId() : 0;
return $leadFields;
}
/**
* @return array
*/
public function getEvent()
{
return ($this->event instanceof \Mautic\CampaignBundle\Entity\Event) ? $this->getEventArray($this->event) : $this->event;
}
/**
* @return array
*/
public function getConfig()
{
return $this->getEvent()['properties'];
}
/**
* @return array
*/
public function getEventDetails()
{
return $this->eventDetails;
}
/**
* @return bool
*/
public function getSystemTriggered()
{
return $this->systemTriggered;
}
/**
* @return bool|mixed[]|string|null
*/
public function getResult()
{
return $this->result;
}
/**
* @param bool|mixed[]|string|null $result
*
* @return $this
*/
public function setResult($result)
{
$this->result = $result;
return $this;
}
/**
* Set the result to failed.
*
* @param string|null $reason
*
* @return $this
*/
public function setFailed($reason = null)
{
$this->result = [
'failed' => 1,
'reason' => $reason,
];
return $this;
}
/**
* @return mixed
*/
public function getEventSettings()
{
return $this->eventSettings;
}
/**
* Set a custom log entry to override auto-handling of the log entry.
*
* @return $this
*/
public function setLogEntry(LeadEventLog $log)
{
$this->logUpdatedByListener = true;
$this->log = $log;
return $this;
}
/**
* @return LeadEventLog
*/
public function getLogEntry()
{
return $this->log;
}
/**
* Returns if a listener updated the log entry.
*
* @return bool
*/
public function wasLogUpdatedByListener()
{
return $this->logUpdatedByListener;
}
/**
* @param string $channel
* @param string|int|null $channelId
*/
public function setChannel($channel, $channelId = null): void
{
if (null !== $this->log) {
// Set the channel since we have the resource
$this->log->setChannel($channel);
$this->log->setChannelId($channelId);
}
$this->channel = $channel;
$this->channelId = $channelId;
}
/**
* @return mixed
*/
public function getChannel()
{
return $this->channel;
}
/**
* @return mixed
*/
public function getChannelId()
{
return $this->channelId;
}
}

View File

@@ -0,0 +1,92 @@
<?php
namespace Mautic\CampaignBundle\Event;
use Mautic\CampaignBundle\Entity\Campaign;
use Mautic\LeadBundle\Entity\Lead;
use Symfony\Contracts\EventDispatcher\Event;
class CampaignLeadChangeEvent extends Event
{
/**
* @var ?Lead
*/
private $lead;
/**
* @var Lead[]
*/
private array $leads = [];
/**
* @param Lead|Lead[] $leads
* @param ?string $action
*/
public function __construct(
private Campaign $campaign,
$leads,
private $action,
) {
if (is_array($leads)) {
$this->leads = $leads;
} else {
$this->lead = $leads;
}
}
/**
* Returns the Campaign entity.
*
* @return Campaign
*/
public function getCampaign()
{
return $this->campaign;
}
/**
* Returns the Lead entity.
*
* @return Lead|null
*/
public function getLead()
{
return $this->lead;
}
/**
* If this is a batch event, return array of leads.
*
* @return Lead[]|null
*/
public function getLeads()
{
return $this->leads;
}
/**
* Returns added or removed.
*
* @return string|null
*/
public function getAction()
{
return $this->action;
}
/**
* Lead was removed from the campaign.
*/
public function wasRemoved(): bool
{
return 'removed' === $this->action;
}
/**
* Lead was added to the campaign.
*/
public function wasAdded(): bool
{
return 'added' === $this->action;
}
}

View File

@@ -0,0 +1,120 @@
<?php
namespace Mautic\CampaignBundle\Event;
use Mautic\CampaignBundle\Entity\LeadEventLog;
use Symfony\Contracts\EventDispatcher\Event;
/**
* @deprecated 2.13.0; to be removed in 3.0
*/
class CampaignScheduledEvent extends Event
{
use EventArrayTrait;
/**
* @var \Mautic\LeadBundle\Entity\Lead
*/
protected $lead;
/**
* @var array
*/
protected $event;
/**
* @var array
*/
protected $eventDetails;
/**
* @var bool
*/
protected $systemTriggered;
/**
* @var \DateTimeInterface
*/
protected $dateScheduled;
/**
* @var array
*/
protected $eventSettings;
public function __construct(
array $args,
protected ?LeadEventLog $log = null,
) {
$this->lead = $args['lead'];
$this->event = $args['event'];
$this->eventDetails = $args['eventDetails'];
$this->systemTriggered = $args['systemTriggered'];
$this->dateScheduled = $args['dateScheduled'];
$this->eventSettings = $args['eventSettings'];
}
/**
* @return \Mautic\LeadBundle\Entity\Lead
*/
public function getLead()
{
return $this->lead;
}
/**
* @return array
*/
public function getEvent()
{
return ($this->event instanceof \Mautic\CampaignBundle\Entity\Event) ? $this->getEventArray($this->event) : $this->event;
}
/**
* @return array
*/
public function getConfig()
{
return $this->getEvent()['properties'];
}
/**
* @return array
*/
public function getEventDetails()
{
return $this->eventDetails;
}
/**
* @return bool
*/
public function getSystemTriggered()
{
return $this->systemTriggered;
}
/**
* @return \DateTimeInterface
*/
public function getDateScheduled()
{
return $this->dateScheduled;
}
/**
* @return mixed
*/
public function getEventSettings()
{
return $this->eventSettings;
}
/**
* @return LeadEventLog|null
*/
public function getLog()
{
return $this->log;
}
}

View File

@@ -0,0 +1,47 @@
<?php
namespace Mautic\CampaignBundle\Event;
use Mautic\CampaignBundle\Entity\Campaign;
use Symfony\Contracts\EventDispatcher\Event;
class CampaignTriggerEvent extends Event
{
/**
* @var bool
*/
protected $triggerCampaign = true;
public function __construct(
protected Campaign $campaign,
) {
}
/**
* Returns the Campaign entity.
*
* @return Campaign
*/
public function getCampaign()
{
return $this->campaign;
}
/**
* @return bool
*/
public function shouldTrigger()
{
return $this->triggerCampaign;
}
/**
* Do not trigger this campaign.
*/
public function doNotTrigger(): void
{
$this->triggerCampaign = false;
$this->stopPropagation();
}
}

View File

@@ -0,0 +1,98 @@
<?php
namespace Mautic\CampaignBundle\Event;
use Mautic\CampaignBundle\Entity\LeadEventLog;
use Mautic\CampaignBundle\EventCollector\Accessor\Event\AbstractEventAccessor;
class ConditionEvent extends CampaignExecutionEvent
{
use ContextTrait;
private bool $passed = false;
public function __construct(
private AbstractEventAccessor $eventConfig,
private LeadEventLog $eventLog,
) {
// @deprecated support for pre 2.13.0; to be removed in 3.0
parent::__construct(
[
'eventSettings' => $eventConfig->getConfig(),
'eventDetails' => null,
'event' => $eventLog->getEvent(),
'lead' => $eventLog->getLead(),
'systemTriggered' => $eventLog->getSystemTriggered(),
],
null,
$eventLog
);
}
/**
* @return AbstractEventAccessor
*/
public function getEventConfig()
{
return $this->eventConfig;
}
/**
* @return LeadEventLog
*/
public function getLog()
{
return $this->eventLog;
}
/**
* Pass this condition.
*/
public function pass(): void
{
$this->passed = true;
}
/**
* Fail this condition.
*/
public function fail(): void
{
$this->passed = false;
}
public function wasConditionSatisfied(): bool
{
return $this->passed;
}
/**
* @param string $channel
* @param int|null $channelId
*/
public function setChannel($channel, $channelId = null): void
{
$this->log->setChannel($this->channel);
$this->log->setChannelId($this->channelId);
}
/**
* @deprecated 2.13.0 to be removed in 3.0; BC support
*/
public function getResult(): bool
{
return $this->passed;
}
/**
* @deprecated 2.13.0 to be removed in 3.0; BC support
*
* @return $this
*/
public function setResult($result)
{
$this->passed = (bool) $result;
return $this;
}
}

View File

@@ -0,0 +1,22 @@
<?php
namespace Mautic\CampaignBundle\Event;
use Mautic\CampaignBundle\Entity\Event;
trait ContextTrait
{
/**
* Check if an event is applicable.
*/
public function checkContext($eventType): bool
{
if (!$this->event) {
return false;
}
$type = ($this->event instanceof Event) ? $this->event->getType() : $this->event['type'];
return strtolower((string) $eventType) === strtolower((string) $type);
}
}

View File

@@ -0,0 +1,105 @@
<?php
namespace Mautic\CampaignBundle\Event;
use Mautic\CampaignBundle\Entity\LeadEventLog;
use Mautic\CampaignBundle\EventCollector\Accessor\Event\AbstractEventAccessor;
class DecisionEvent extends CampaignExecutionEvent
{
use ContextTrait;
private bool $applicable = false;
/**
* @param mixed $passthrough
*/
public function __construct(
private AbstractEventAccessor $eventConfig,
private LeadEventLog $eventLog,
private $passthrough = null,
) {
// @deprecated support for pre 2.13.0; to be removed in 3.0
parent::__construct(
[
'eventSettings' => $eventConfig->getConfig(),
'eventDetails' => $passthrough,
'event' => $eventLog->getEvent(),
'lead' => $eventLog->getLead(),
'systemTriggered' => defined('MAUTIC_CAMPAIGN_SYSTEM_TRIGGERED'),
'dateScheduled' => $eventLog->getTriggerDate(),
],
null,
$eventLog
);
}
/**
* @return AbstractEventAccessor
*/
public function getEventConfig()
{
return $this->eventConfig;
}
/**
* @return LeadEventLog
*/
public function getLog()
{
return $this->eventLog;
}
/**
* @return mixed
*/
public function getPassthrough()
{
return $this->passthrough;
}
/**
* Note that this decision is a match and the child events should be executed.
*/
public function setAsApplicable(): void
{
$this->applicable = true;
}
public function wasDecisionApplicable(): bool
{
return $this->applicable;
}
/**
* @param string $channel
* @param int|null $channelId
*/
public function setChannel($channel, $channelId = null): void
{
$this->log->setChannel($this->channel);
$this->log->setChannelId($this->channelId);
}
/**
* @deprecated 2.13.0 to be removed in 3.0; BC support
*/
public function getResult(): bool
{
return $this->applicable;
}
/**
* @deprecated 2.13.0 to be removed in 3.0; BC support
*
* @param mixed $result
*
* @return $this
*/
public function setResult($result)
{
$this->applicable = (bool) $result;
return $this;
}
}

View File

@@ -0,0 +1,46 @@
<?php
namespace Mautic\CampaignBundle\Event;
use Doctrine\Common\Collections\ArrayCollection;
use Mautic\CampaignBundle\Entity\LeadEventLog;
use Mautic\CampaignBundle\EventCollector\Accessor\Event\AbstractEventAccessor;
use Mautic\CampaignBundle\Executioner\Result\EvaluatedContacts;
use Symfony\Contracts\EventDispatcher\Event;
class DecisionResultsEvent extends Event
{
/**
* @param ArrayCollection<int, LeadEventLog> $eventLogs
*/
public function __construct(
private AbstractEventAccessor $eventConfig,
private ArrayCollection $eventLogs,
private EvaluatedContacts $evaluatedContacts,
) {
}
/**
* @return AbstractEventAccessor
*/
public function getEventConfig()
{
return $this->eventConfig;
}
/**
* @return ArrayCollection|LeadEventLog[]
*/
public function getLogs()
{
return $this->eventLogs;
}
/**
* @return EvaluatedContacts
*/
public function getEvaluatedContacts()
{
return $this->evaluatedContacts;
}
}

View File

@@ -0,0 +1,19 @@
<?php
declare(strict_types=1);
namespace Mautic\CampaignBundle\Event;
use Mautic\CampaignBundle\Entity\Campaign;
final class DeleteCampaign extends \Symfony\Contracts\EventDispatcher\Event
{
public function __construct(private Campaign $campaign)
{
}
public function getCampaign(): Campaign
{
return $this->campaign;
}
}

View File

@@ -0,0 +1,23 @@
<?php
declare(strict_types=1);
namespace Mautic\CampaignBundle\Event;
final class DeleteEvent extends \Symfony\Contracts\EventDispatcher\Event
{
/**
* @param string[] $eventIds
*/
public function __construct(private array $eventIds)
{
}
/**
* @return string[]
*/
public function getEventIds(): array
{
return $this->eventIds;
}
}

View File

@@ -0,0 +1,87 @@
<?php
namespace Mautic\CampaignBundle\Event;
use Mautic\CampaignBundle\Entity\Event;
use Mautic\CampaignBundle\Entity\LeadEventLog;
use Mautic\CampaignBundle\EventCollector\Accessor\Event\AbstractEventAccessor;
/**
* Trait EventArrayTrait.
*
* @deprecated 2.13.0; used for BC support. To be removed in 3.0
*/
trait EventArrayTrait
{
/**
* @var array
*/
protected $eventArray = [];
/**
* Used to convert entities to the old array format; tried to minimize the need for this except where needed.
*
* @return array
*/
protected function getEventArray(Event $event)
{
$eventId = $event->getId();
if (isset($this->eventArray[$eventId])) {
return $this->eventArray[$eventId];
}
$eventArray = $event->convertToArray();
$campaign = $event->getCampaign();
$eventArray['campaign'] = [
'id' => $campaign->getId(),
'name' => $campaign->getName(),
'createdBy' => $campaign->getCreatedBy(),
];
$eventArray['parent'] = null;
if ($parent = $event->getParent()) {
$eventArray['parent'] = $parent->convertToArray();
$eventArray['parent']['campaign'] = $eventArray['campaign'];
}
$eventArray['children'] = [];
if ($children = $event->getChildren()) {
/** @var Event $child */
foreach ($children as $child) {
$childArray = $child->convertToArray();
$childArray['parent'] =&$eventArray;
$childArray['campaign'] =&$eventArray['campaign'];
unset($childArray['children']);
$eventArray['children'] = $childArray;
}
}
$this->eventArray[$eventId] = $eventArray;
return $this->eventArray[$eventId];
}
protected function getLegacyEventsArray(LeadEventLog $log): array
{
$event = $log->getEvent();
return [
$event->getCampaign()->getId() => [
$this->getEventArray($event),
],
];
}
protected function getLegacyEventsConfigArray(Event $event, AbstractEventAccessor $config): array
{
return [
$event->getEventType() => [
$event->getType() => [
$config->getConfig(),
],
],
];
}
}

View File

@@ -0,0 +1,12 @@
<?php
namespace Mautic\CampaignBundle\Event\Exception;
use Symfony\Component\Process\Exception\InvalidArgumentException;
/**
* Extends Symfony\Component\Process\Exception\InvalidArgumentException to keep BC.
*/
class KeyAlreadyRegisteredException extends InvalidArgumentException
{
}

View File

@@ -0,0 +1,16 @@
<?php
namespace Mautic\CampaignBundle\Event;
use Doctrine\Common\Collections\ArrayCollection;
class ExecutedBatchEvent extends AbstractLogCollectionEvent
{
/**
* @return ArrayCollection
*/
public function getExecuted()
{
return $this->logs;
}
}

View File

@@ -0,0 +1,31 @@
<?php
namespace Mautic\CampaignBundle\Event;
use Mautic\CampaignBundle\Entity\LeadEventLog;
use Mautic\CampaignBundle\EventCollector\Accessor\Event\AbstractEventAccessor;
class ExecutedEvent extends \Symfony\Contracts\EventDispatcher\Event
{
public function __construct(
private AbstractEventAccessor $config,
private LeadEventLog $log,
) {
}
/**
* @return AbstractEventAccessor
*/
public function getConfig()
{
return $this->config;
}
/**
* @return LeadEventLog
*/
public function getLog()
{
return $this->log;
}
}

View File

@@ -0,0 +1,31 @@
<?php
namespace Mautic\CampaignBundle\Event;
use Mautic\CampaignBundle\Entity\LeadEventLog;
use Mautic\CampaignBundle\EventCollector\Accessor\Event\AbstractEventAccessor;
class FailedEvent extends \Symfony\Contracts\EventDispatcher\Event
{
public function __construct(
private AbstractEventAccessor $config,
private LeadEventLog $log,
) {
}
/**
* @return AbstractEventAccessor
*/
public function getConfig()
{
return $this->config;
}
/**
* @return LeadEventLog
*/
public function getLog()
{
return $this->log;
}
}

View File

@@ -0,0 +1,24 @@
<?php
namespace Mautic\CampaignBundle\Event;
use Mautic\CampaignBundle\Entity\Event as CampaignEvent;
use Mautic\LeadBundle\Entity\Lead;
use Symfony\Contracts\EventDispatcher\Event;
class NotifyOfFailureEvent extends Event
{
public function __construct(private Lead $lead, private CampaignEvent $failedEvent)
{
}
public function getLead(): Lead
{
return $this->lead;
}
public function getFailedEvent(): CampaignEvent
{
return $this->failedEvent;
}
}

View File

@@ -0,0 +1,18 @@
<?php
namespace Mautic\CampaignBundle\Event;
use Mautic\CampaignBundle\Entity\Event as CampaignEvent;
use Symfony\Contracts\EventDispatcher\Event;
class NotifyOfUnpublishEvent extends Event
{
public function __construct(private CampaignEvent $failedEvent)
{
}
public function getFailedEvent(): CampaignEvent
{
return $this->failedEvent;
}
}

View File

@@ -0,0 +1,261 @@
<?php
namespace Mautic\CampaignBundle\Event;
use Doctrine\Common\Collections\ArrayCollection;
use Mautic\CampaignBundle\Entity\Event;
use Mautic\CampaignBundle\Entity\FailedLeadEventLog;
use Mautic\CampaignBundle\Entity\LeadEventLog;
use Mautic\CampaignBundle\EventCollector\Accessor\Event\AbstractEventAccessor;
class PendingEvent extends AbstractLogCollectionEvent
{
use ContextTrait;
private ArrayCollection $failures;
private ArrayCollection $successful;
/**
* @var string|null
*/
private $channel;
/**
* @var int|null
*/
private $channelId;
private \DateTimeInterface $now;
/**
* @throws \Exception
*/
public function __construct(AbstractEventAccessor $config, Event $event, ArrayCollection $logs)
{
$this->failures = new ArrayCollection();
$this->successful = new ArrayCollection();
$this->now = new \DateTime();
parent::__construct($config, $event, $logs);
}
/**
* @return LeadEventLog[]|ArrayCollection
*/
public function getPending()
{
return $this->logs;
}
/**
* @param string $reason
*/
public function fail(LeadEventLog $log, $reason, ?\DateInterval $rescheduleInterval = null): void
{
if (!$failedLog = $log->getFailedLog()) {
$failedLog = new FailedLeadEventLog();
}
$log->setRescheduleInterval($rescheduleInterval);
$failedLog->setLog($log)
->setDateAdded(new \DateTime())
->setReason($reason);
// Used by the UI
$metadata = $log->getMetadata();
$metadata = array_merge(
$metadata,
[
'failed' => 1,
'reason' => $reason,
]
);
$log->setMetadata($metadata);
$this->logChannel($log);
$this->failures->set($log->getId(), $log);
}
/**
* @param string $reason
*/
public function failAll($reason): void
{
foreach ($this->logs as $log) {
$this->fail($log, $reason);
}
}
/**
* Fail all that have not passed yet.
*
* @param string $reason
*/
public function failRemaining($reason): void
{
foreach ($this->logs as $log) {
if (!$this->successful->contains($log)) {
$this->fail($log, $reason);
}
}
}
/**
* Fail all that have not passed or failed yet.
*
* @param string $reason
*/
public function failRemainingPending($reason): void
{
foreach ($this->logs as $log) {
if (!$this->failures->contains($log) && !$this->successful->contains($log)) {
$this->fail($log, $reason);
}
}
}
/**
* @param LeadEventLog[]|ArrayCollection $logs
* @param string $reason
*/
public function failLogs(ArrayCollection $logs, $reason): void
{
foreach ($logs as $log) {
$this->fail($log, $reason);
}
}
public function pass(LeadEventLog $log): void
{
$metadata = $log->getMetadata();
unset($metadata['errors']);
if (isset($metadata['failed'])) {
unset($metadata['failed'], $metadata['reason']);
}
$log->setMetadata($metadata);
$this->passLog($log);
}
/**
* @param string $error
*/
public function passWithError(LeadEventLog $log, $error): void
{
$log->appendToMetadata(
[
'failed' => 1,
'reason' => $error,
]
);
$this->passLog($log);
}
/**
* @param string $error
*/
public function passAllWithError($error): void
{
/** @var LeadEventLog $log */
foreach ($this->logs as $log) {
$this->passWithError($log, $error);
}
}
/**
* Pass all remainging logs that have not failed failed nor suceeded yet.
*/
public function passRemainingWithError(string $error): void
{
foreach ($this->logs as $log) {
if (!$this->failures->contains($log) && !$this->successful->contains($log)) {
$this->passWithError($log, $error);
}
}
}
/**
* Pass all pending.
*/
public function passAll(): void
{
/** @var LeadEventLog $log */
foreach ($this->logs as $log) {
$this->pass($log);
}
}
/**
* @param LeadEventLog[]|ArrayCollection $logs
*/
public function passLogs(ArrayCollection $logs): void
{
foreach ($logs as $log) {
$this->pass($log);
}
}
/**
* Pass all that have not failed yet.
*/
public function passRemaining(): void
{
foreach ($this->logs as $log) {
if (!$this->failures->contains($log)) {
$this->pass($log);
}
}
}
/**
* @return LeadEventLog[]|ArrayCollection
*/
public function getFailures()
{
return $this->failures;
}
/**
* @return LeadEventLog[]|ArrayCollection
*/
public function getSuccessful()
{
return $this->successful;
}
/**
* @param string $channel
* @param int|null $channelId
*/
public function setChannel($channel, $channelId = null): void
{
$this->channel = $channel;
$this->channelId = $channelId;
}
private function passLog(LeadEventLog $log): void
{
if ($failedLog = $log->getFailedLog()) {
// Delete existing entries
$failedLog->setLog(null);
$log->setFailedLog(null);
}
$this->logChannel($log);
$log->setIsScheduled(false)
->setDateTriggered($this->now);
$this->successful->set($log->getId(), $log);
}
private function logChannel(LeadEventLog $log): void
{
if ($this->channel) {
$log->setChannel($this->channel);
$log->setChannelId($this->channelId);
}
}
}

View File

@@ -0,0 +1,38 @@
<?php
namespace Mautic\CampaignBundle\Event;
use Doctrine\Common\Collections\ArrayCollection;
use Mautic\CampaignBundle\Entity\Event;
use Mautic\CampaignBundle\EventCollector\Accessor\Event\AbstractEventAccessor;
class ScheduledBatchEvent extends AbstractLogCollectionEvent
{
/**
* @param bool $isReschedule
*/
public function __construct(
AbstractEventAccessor $config,
Event $event,
ArrayCollection $logs,
private $isReschedule = false,
) {
parent::__construct($config, $event, $logs);
}
/**
* @return ArrayCollection
*/
public function getScheduled()
{
return $this->logs;
}
/**
* @return bool
*/
public function isReschedule()
{
return $this->isReschedule;
}
}

View File

@@ -0,0 +1,57 @@
<?php
namespace Mautic\CampaignBundle\Event;
use Mautic\CampaignBundle\Entity\LeadEventLog;
use Mautic\CampaignBundle\EventCollector\Accessor\Event\AbstractEventAccessor;
class ScheduledEvent extends CampaignScheduledEvent
{
use ContextTrait;
/**
* @param bool $isReschedule
*/
public function __construct(
private AbstractEventAccessor $eventConfig,
private LeadEventLog $eventLog,
private $isReschedule = false,
) {
// @deprecated support for pre 2.13.0; to be removed in 3.0
parent::__construct(
[
'eventSettings' => $eventConfig->getConfig(),
'eventDetails' => null,
'event' => $eventLog->getEvent(),
'lead' => $eventLog->getLead(),
'systemTriggered' => true,
'dateScheduled' => $eventLog->getTriggerDate(),
],
$eventLog
);
}
/**
* @return AbstractEventAccessor
*/
public function getEventConfig()
{
return $this->eventConfig;
}
/**
* @return LeadEventLog
*/
public function getLog()
{
return $this->eventLog;
}
/**
* @return bool
*/
public function isReschedule()
{
return $this->isReschedule;
}
}