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,136 @@
<?php
namespace Mautic\CampaignBundle\EventCollector\Accessor\Event;
abstract class AbstractEventAccessor
{
/**
* @var array
*/
protected $systemProperties = [
'label',
'description',
'formType',
'formTypeOptions',
'formTheme',
'timelineTemplate',
'connectionRestrictions',
'channel',
'channelIdField',
];
private array $extraProperties = [];
public function __construct(
protected array $config,
) {
$this->filterExtraProperties();
}
/**
* @return string
*/
public function getLabel()
{
return $this->getProperty('label');
}
/**
* @return string
*/
public function getDescription()
{
return $this->getProperty('description');
}
/**
* @return string
*/
public function getFormType()
{
return $this->getProperty('formType');
}
/**
* @return array
*/
public function getFormTypeOptions()
{
return $this->getProperty('formTypeOptions', []);
}
/**
* @return string
*/
public function getFormTheme()
{
return $this->getProperty('formTheme');
}
/**
* @return string
*/
public function getTimelineTemplate()
{
return $this->getProperty('timelineTemplate');
}
/**
* @return array
*/
public function getConnectionRestrictions()
{
return $this->getProperty('connectionRestrictions', []);
}
/**
* @return array
*/
public function getExtraProperties()
{
return $this->extraProperties;
}
/**
* @return string
*/
public function getChannel()
{
return $this->getProperty('channel');
}
/**
* @return mixed
*/
public function getChannelIdField()
{
return $this->getProperty('channelIdField');
}
/**
* @deprecated pre 2.13.0 support; to be removed in 3.0
*/
public function getConfig()
{
return $this->config;
}
/**
* @param string $property
* @param mixed $default
*
* @return mixed
*/
protected function getProperty($property, $default = null)
{
return $this->config[$property] ?? $default;
}
/**
* Calculate the difference in systemProperties and what was fed to the class.
*/
private function filterExtraProperties(): void
{
$this->extraProperties = array_diff_key($this->config, array_flip($this->systemProperties));
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace Mautic\CampaignBundle\EventCollector\Accessor\Event;
class ActionAccessor extends AbstractEventAccessor
{
public function __construct(array $config)
{
$this->systemProperties[] = 'batchEventName';
parent::__construct($config);
}
/**
* @return mixed
*/
public function getBatchEventName()
{
return $this->getProperty('batchEventName');
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace Mautic\CampaignBundle\EventCollector\Accessor\Event;
class ConditionAccessor extends AbstractEventAccessor
{
public function __construct(array $config)
{
$this->systemProperties[] = 'eventName';
parent::__construct($config);
}
/**
* @return string
*/
public function getEventName()
{
return $this->getProperty('eventName');
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace Mautic\CampaignBundle\EventCollector\Accessor\Event;
class DecisionAccessor extends AbstractEventAccessor
{
public function __construct(array $config)
{
$this->systemProperties[] = 'eventName';
parent::__construct($config);
}
/**
* @return string
*/
public function getEventName()
{
return $this->getProperty('eventName');
}
}

View File

@@ -0,0 +1,131 @@
<?php
namespace Mautic\CampaignBundle\EventCollector\Accessor;
use Mautic\CampaignBundle\Entity\Event;
use Mautic\CampaignBundle\EventCollector\Accessor\Event\AbstractEventAccessor;
use Mautic\CampaignBundle\EventCollector\Accessor\Event\ActionAccessor;
use Mautic\CampaignBundle\EventCollector\Accessor\Event\DecisionAccessor;
use Mautic\CampaignBundle\EventCollector\Accessor\Exception\EventNotFoundException;
use Mautic\CampaignBundle\EventCollector\Accessor\Exception\TypeNotFoundException;
use Mautic\CampaignBundle\EventCollector\Builder\EventBuilder;
class EventAccessor
{
private array $actions = [];
private array $conditions = [];
private array $decisions = [];
public function __construct(array $events)
{
$this->buildEvents($events);
}
/**
* @param string $type
* @param string $key
*
* @return AbstractEventAccessor
*
* @throws TypeNotFoundException
* @throws EventNotFoundException
*/
public function getEvent($type, $key)
{
return match ($type) {
Event::TYPE_ACTION => $this->getAction($key),
Event::TYPE_CONDITION => $this->getCondition($key),
Event::TYPE_DECISION => $this->getDecision($key),
default => throw new TypeNotFoundException("$type is not a valid event type"),
};
}
/**
* @param string $key
*
* @return ActionAccessor
*
* @throws EventNotFoundException
*/
public function getAction($key)
{
if (!isset($this->actions[$key])) {
throw new EventNotFoundException("Action $key is not valid");
}
return $this->actions[$key];
}
/**
* @return array
*/
public function getActions()
{
return $this->actions;
}
/**
* @param string $key
*
* @return mixed
*
* @throws EventNotFoundException
*/
public function getCondition($key)
{
if (!isset($this->conditions[$key])) {
throw new EventNotFoundException("Condition $key is not valid");
}
return $this->conditions[$key];
}
/**
* @return array
*/
public function getConditions()
{
return $this->conditions;
}
/**
* @param string $key
*
* @return DecisionAccessor
*
* @throws EventNotFoundException
*/
public function getDecision($key)
{
if (!isset($this->decisions[$key])) {
throw new EventNotFoundException("Decision $key is not valid");
}
return $this->decisions[$key];
}
/**
* @return array
*/
public function getDecisions()
{
return $this->decisions;
}
private function buildEvents(array $events): void
{
if (isset($events[Event::TYPE_ACTION])) {
$this->actions = EventBuilder::buildActions($events[Event::TYPE_ACTION]);
}
if (isset($events[Event::TYPE_CONDITION])) {
$this->conditions = EventBuilder::buildConditions($events[Event::TYPE_CONDITION]);
}
if (isset($events[Event::TYPE_DECISION])) {
$this->decisions = EventBuilder::buildDecisions($events[Event::TYPE_DECISION]);
}
}
}

View File

@@ -0,0 +1,7 @@
<?php
namespace Mautic\CampaignBundle\EventCollector\Accessor\Exception;
class EventNotFoundException extends \InvalidArgumentException
{
}

View File

@@ -0,0 +1,7 @@
<?php
namespace Mautic\CampaignBundle\EventCollector\Accessor\Exception;
class TypeNotFoundException extends \InvalidArgumentException
{
}

View File

@@ -0,0 +1,111 @@
<?php
namespace Mautic\CampaignBundle\EventCollector\Builder;
use Mautic\CampaignBundle\Entity\Event;
class ConnectionBuilder
{
private static array $eventTypes = [];
private static array $connectionRestrictions = ['anchor' => []];
/**
* Used by JS/JsPlumb to restrict how events can be associated to each other in the UI.
*
* @return array
*/
public static function buildRestrictionsArray(array $events)
{
// Reset restrictions
self::$connectionRestrictions = ['anchor' => []];
// Build the restrictions
self::$eventTypes = array_fill_keys(array_keys($events), []);
foreach ($events as $eventType => $typeEvents) {
foreach ($typeEvents as $key => $event) {
self::addTypeConnection($eventType, $key, $event);
}
}
return self::$connectionRestrictions;
}
/**
* @param string $eventType
* @param string $key
*/
private static function addTypeConnection($eventType, $key, array $event): void
{
if (!isset(self::$connectionRestrictions[$key])) {
self::$connectionRestrictions[$key] = [
'source' => self::$eventTypes,
'target' => self::$eventTypes,
];
}
if (!isset(self::$connectionRestrictions[$key])) {
self::$connectionRestrictions['anchor'][$key] = [];
}
if (isset($event['connectionRestrictions'])) {
foreach ($event['connectionRestrictions'] as $restrictionType => $restrictions) {
self::addRestriction($key, $restrictionType, $restrictions);
}
}
self::addDeprecatedAnchorRestrictions($eventType, $key, $event);
}
/**
* @param string $key
* @param string $restrictionType
*/
private static function addRestriction($key, $restrictionType, array $restrictions): void
{
switch ($restrictionType) {
case 'source':
case 'target':
foreach ($restrictions as $groupType => $groupRestrictions) {
self::$connectionRestrictions[$key][$restrictionType][$groupType] += $groupRestrictions;
}
break;
case 'anchor':
foreach ($restrictions as $anchor) {
[$group, $anchor] = explode('.', $anchor);
self::$connectionRestrictions[$restrictionType][$group][$key][] = $anchor;
}
break;
}
}
/**
* @deprecated 2.6.0 to be removed in 3.0; BC support
*
* @param string $eventType
* @param string $key
*/
private static function addDeprecatedAnchorRestrictions($eventType, $key, array $event): void
{
switch ($eventType) {
case Event::TYPE_DECISION:
if (isset($event['associatedActions'])) {
self::$connectionRestrictions[$key]['target']['action'] += $event['associatedActions'];
}
break;
case Event::TYPE_ACTION:
if (isset($event['associatedDecisions'])) {
self::$connectionRestrictions[$key]['source']['decision'] += $event['associatedDecisions'];
}
break;
}
if (isset($event['anchorRestrictions'])) {
foreach ($event['anchorRestrictions'] as $restriction) {
[$group, $anchor] = explode('.', $restriction);
self::$connectionRestrictions['anchor'][$key][$group][] = $anchor;
}
}
}
}

View File

@@ -0,0 +1,40 @@
<?php
namespace Mautic\CampaignBundle\EventCollector\Builder;
use Mautic\CampaignBundle\EventCollector\Accessor\Event\ActionAccessor;
use Mautic\CampaignBundle\EventCollector\Accessor\Event\ConditionAccessor;
use Mautic\CampaignBundle\EventCollector\Accessor\Event\DecisionAccessor;
class EventBuilder
{
public static function buildActions(array $actions): array
{
$converted = [];
foreach ($actions as $key => $actionArray) {
$converted[$key] = new ActionAccessor($actionArray);
}
return $converted;
}
public static function buildConditions(array $conditions): array
{
$converted = [];
foreach ($conditions as $key => $conditionArray) {
$converted[$key] = new ConditionAccessor($conditionArray);
}
return $converted;
}
public static function buildDecisions(array $decisions): array
{
$converted = [];
foreach ($decisions as $key => $decisionArray) {
$converted[$key] = new DecisionAccessor($decisionArray);
}
return $converted;
}
}

View File

@@ -0,0 +1,88 @@
<?php
namespace Mautic\CampaignBundle\EventCollector;
use Mautic\CampaignBundle\CampaignEvents;
use Mautic\CampaignBundle\Entity\Event;
use Mautic\CampaignBundle\Event\CampaignBuilderEvent;
use Mautic\CampaignBundle\EventCollector\Accessor\Event\AbstractEventAccessor;
use Mautic\CampaignBundle\EventCollector\Accessor\EventAccessor;
use Mautic\CampaignBundle\EventCollector\Builder\ConnectionBuilder;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
class EventCollector
{
private array $eventsArray = [];
private ?EventAccessor $events = null;
public function __construct(
private TranslatorInterface $translator,
private EventDispatcherInterface $dispatcher,
) {
}
/**
* @return EventAccessor
*/
public function getEvents()
{
if (empty($this->eventsArray)) {
$this->buildEventList();
}
if (empty($this->events)) {
$this->events = new EventAccessor($this->eventsArray);
}
return $this->events;
}
/**
* @return AbstractEventAccessor
*/
public function getEventConfig(Event $event)
{
return $this->getEvents()->getEvent($event->getEventType(), $event->getType());
}
/**
* Deprecated support for pre 2.13.
*
* @deprecated 2.13.0 to be removed in 3.0
*
* @param string|null $type
*
* @return array|mixed
*/
public function getEventsArray($type = null)
{
if (empty($this->eventsArray)) {
$this->buildEventList();
}
if (null !== $type) {
if (!isset($this->events[$type])) {
throw new \InvalidArgumentException("$type not found as array key");
}
return $this->eventsArray[$type];
}
return $this->eventsArray;
}
private function buildEventList(): void
{
// build them
$event = new CampaignBuilderEvent($this->translator);
$this->dispatcher->dispatch($event, CampaignEvents::CAMPAIGN_ON_BUILD);
$this->eventsArray[Event::TYPE_ACTION] = $event->getActions();
$this->eventsArray[Event::TYPE_CONDITION] = $event->getConditions();
$this->eventsArray[Event::TYPE_DECISION] = $event->getDecisions();
$this->eventsArray['connectionRestrictions'] = ConnectionBuilder::buildRestrictionsArray($this->eventsArray);
}
}