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,26 @@
<?php
declare(strict_types=1);
namespace Mautic\PointBundle\Tests\Unit\Helper;
use Mautic\LeadBundle\Entity\Lead;
use Mautic\PointBundle\Helper\EventHelper;
use PHPUnit\Framework\TestCase;
class EventHelperTest extends TestCase
{
public function testEngagePointAction(): void
{
$lead = new Lead();
// Define the action array
$action = ['id' => 1, 'type' => 'helloworld.action.custom_action', 'name' => 'My custom point action', 'properties' => [], 'points' => 50];
$points = EventHelper::engagePointAction($lead, $action);
$this->assertEquals(50, $points);
$points = EventHelper::engagePointAction($lead, $action);
$this->assertEquals(0, $points, 'Second call should return 0 points because the action is already initiated for this lead and type and session.');
}
}

View File

@@ -0,0 +1,191 @@
<?php
declare(strict_types=1);
namespace Mautic\PointBundle\Tests\Unit\Model;
use Doctrine\ORM\EntityManager;
use Mautic\CoreBundle\Entity\IpAddress;
use Mautic\CoreBundle\Helper\CoreParametersHelper;
use Mautic\CoreBundle\Helper\IpLookupHelper;
use Mautic\CoreBundle\Helper\UserHelper;
use Mautic\CoreBundle\Security\Permissions\CorePermissions;
use Mautic\CoreBundle\Translation\Translator;
use Mautic\LeadBundle\Entity\Lead;
use Mautic\LeadBundle\Model\LeadModel;
use Mautic\LeadBundle\Tracker\ContactTracker;
use Mautic\PageBundle\Entity\Hit;
use Mautic\PageBundle\Helper\PointActionHelper;
use Mautic\PointBundle\Entity\Point;
use Mautic\PointBundle\Entity\PointRepository;
use Mautic\PointBundle\Event\PointActionEvent;
use Mautic\PointBundle\Event\PointBuilderEvent;
use Mautic\PointBundle\Model\PointGroupModel;
use Mautic\PointBundle\Model\PointModel;
use Mautic\PointBundle\PointEvents;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Contracts\EventDispatcher\Event;
class PointModelTest extends TestCase
{
private RequestStack&MockObject $requestStack;
private IpLookupHelper&MockObject $ipLookupHelper;
private LeadModel&MockObject $leadModel;
private ContactTracker&MockObject $contactTracker;
private EntityManager&MockObject $em;
private CorePermissions&MockObject $security;
private EventDispatcherInterface&MockObject $dispatcher;
private UrlGeneratorInterface&MockObject $router;
private Translator&MockObject $translator;
private UserHelper&MockObject $userHelper;
private LoggerInterface&MockObject $mauticLogger;
private CoreParametersHelper&MockObject $coreParametersHelper;
private PointGroupModel&MockObject $pointGroupModel;
private PointModel $pointModel;
protected function setUp(): void
{
$this->requestStack = $this->createMock(RequestStack::class);
$this->ipLookupHelper = $this->createMock(IpLookupHelper::class);
$this->leadModel = $this->createMock(LeadModel::class);
$this->contactTracker = $this->createMock(ContactTracker::class);
$this->em = $this->createMock(EntityManager::class);
$this->security = $this->createMock(CorePermissions::class);
$this->dispatcher = $this->createMock(EventDispatcherInterface::class);
$this->router = $this->createMock(RouterInterface::class);
$this->translator = $this->createMock(Translator::class);
$this->userHelper = $this->createMock(UserHelper::class);
$this->mauticLogger = $this->createMock(LoggerInterface::class);
$this->coreParametersHelper = $this->createMock(CoreParametersHelper::class);
$this->pointGroupModel = $this->createMock(PointGroupModel::class);
$this->pointModel = new PointModel(
$this->requestStack,
$this->ipLookupHelper,
$this->leadModel,
$this->contactTracker,
$this->em,
$this->security,
$this->dispatcher,
$this->router,
$this->translator,
$this->userHelper,
$this->mauticLogger,
$this->coreParametersHelper,
$this->pointGroupModel,
);
}
public function testTriggerUrlHitWithCallbackObject(): void
{
$type = 'url.hit';
$pointId = 98783;
$pointName = 'Point name';
$pointProperties = ['property' => 'value'];
$pointDelta = 7;
$pointGroup = null;
$ip = $this->createMock(IpAddress::class);
$this->security->method('isAnonymous')->willReturn(true);
$this->ipLookupHelper->method('getIpAddress')->willReturn($ip);
$lead = $this->createMock(Lead::class);
$lead->expects(self::once())
->method('adjustPoints')
->with($pointDelta);
$lead->expects(self::once())
->method('addPointsChangeLogEntry')
->with(
'url',
$pointId.': '.$pointName,
'hit',
$pointDelta,
$ip,
$pointGroup
);
$eventDetails = $this->createMock(Hit::class);
$repository = $this->createMock(PointRepository::class);
$this->em->expects(self::once())
->method('getRepository')
->with(Point::class)
->willReturn($repository);
$pointActionHelper = $this->createMock(PointActionHelper::class);
$pointActionHelper->expects(self::once())
->method('validateUrlHit')
->with(
$eventDetails,
[
'id' => $pointId,
'type' => $type,
'name' => $pointName,
'properties' => $pointProperties,
'points' => $pointDelta,
]
)
->willReturn(true);
$point = $this->createMock(Point::class);
$point->method('getRepeatable')->willReturn(true);
$point->method('getType')->willReturn($type);
$point->method('getId')->willReturn($pointId);
$point->method('getName')->willReturn($pointName);
$point->method('getProperties')->willReturn($pointProperties);
$point->method('getDelta')->willReturn($pointDelta);
$point->method('getGroup')->willReturn($pointGroup);
$repository->expects(self::once())
->method('getPublishedByType')
->with($type)
->willReturn([$point]);
$repository->expects(self::once())
->method('getCompletedLeadActions')
->willReturn([]);
$repository->expects(self::never())
->method('saveEntities');
$repository->expects(self::never())
->method('detachEntities');
$this->dispatcher->expects(self::exactly(2))
->method('dispatch')
->willReturnCallback(function (Event $event, string $eventName) use ($pointActionHelper, $type, $lead, $point): Event {
if (PointEvents::POINT_ON_BUILD === $eventName) {
self::assertInstanceOf(PointBuilderEvent::class, $event);
self::assertEquals(new PointBuilderEvent($this->translator), $event);
$event->addAction(
$type,
[
'callback' => [
$pointActionHelper,
'validateUrlHit',
],
'group' => 'group',
'label' => 'label',
],
);
return $event;
}
if (PointEvents::POINT_ON_ACTION === $eventName) {
$pointActionEvent = new PointActionEvent($point, $lead);
self::assertEquals($pointActionEvent, $event);
return $pointActionEvent;
}
self::fail('Unknown event called: '.$eventName);
});
$this->leadModel->expects(self::once())
->method('saveEntity')
->with($lead);
$this->pointModel->triggerAction($type, $eventDetails, null, $lead);
}
}

View File

@@ -0,0 +1,160 @@
<?php
declare(strict_types=1);
namespace Mautic\PointBundle\Tests\Unit\Model;
use Doctrine\ORM\EntityManager;
use Mautic\CoreBundle\Helper\CoreParametersHelper;
use Mautic\CoreBundle\Helper\IpLookupHelper;
use Mautic\CoreBundle\Helper\UserHelper;
use Mautic\CoreBundle\Security\Permissions\CorePermissions;
use Mautic\CoreBundle\Translation\Translator;
use Mautic\EmailBundle\EmailEvents;
use Mautic\EmailBundle\Form\Type\EmailToUserType;
use Mautic\LeadBundle\Entity\Lead;
use Mautic\LeadBundle\Model\LeadModel;
use Mautic\LeadBundle\Tracker\ContactTracker;
use Mautic\PointBundle\Entity\TriggerEvent;
use Mautic\PointBundle\Entity\TriggerEventRepository;
use Mautic\PointBundle\Model\TriggerEventModel;
use Mautic\PointBundle\Model\TriggerModel;
use Mautic\PointBundle\PointEvents;
use PHPUnit\Framework\Assert;
use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
final class TriggerModelTest extends \PHPUnit\Framework\TestCase
{
/**
* @var IpLookupHelper&MockObject
*/
private MockObject $ipLookupHelper;
/**
* @var LeadModel&MockObject
*/
private MockObject $leadModel;
/**
* @var TriggerEventModel&MockObject
*/
private MockObject $triggerEventModel;
/**
* @var EventDispatcherInterface&MockObject
*/
private MockObject $dispatcher;
/**
* @var TranslatorInterface&MockObject
*/
private MockObject $translator;
/**
* @var EntityManager&MockObject
*/
private MockObject $entityManager;
/**
* @var TriggerEventRepository&MockObject
*/
private MockObject $triggerEventRepository;
private TriggerModel $triggerModel;
/**
* @var ContactTracker&MockObject
*/
private MockObject $contactTracker;
public function setUp(): void
{
parent::setUp();
$this->ipLookupHelper = $this->createMock(IpLookupHelper::class);
$this->leadModel = $this->createMock(LeadModel::class);
$this->triggerEventModel = $this->createMock(TriggerEventModel::class);
$this->contactTracker = $this->createMock(ContactTracker::class);
$this->dispatcher = $this->createMock(EventDispatcherInterface::class);
$this->translator = $this->createMock(Translator::class);
$this->entityManager = $this->createMock(EntityManager::class);
$this->triggerEventRepository = $this->createMock(TriggerEventRepository::class);
$this->triggerModel = new TriggerModel(
$this->ipLookupHelper,
$this->leadModel,
$this->triggerEventModel,
$this->contactTracker,
$this->entityManager,
$this->createMock(CorePermissions::class),
$this->dispatcher,
$this->createMock(UrlGeneratorInterface::class),
$this->translator,
$this->createMock(UserHelper::class),
$this->createMock(LoggerInterface::class),
$this->createMock(CoreParametersHelper::class)
);
// reset private property cachedEvents in TriggerModel instance
$reflectionClass = new \ReflectionClass(TriggerModel::class);
$property = $reflectionClass->getProperty('cachedEvents');
$property->setAccessible(true);
$property->setValue($this->triggerModel, []);
}
public function testTriggerEvent(): void
{
$triggerEvent = new TriggerEvent();
$contact = new Lead();
$dispatchCalls = new \ArrayObject();
$triggerEvent->setType('email.send_to_user');
$this->entityManager->expects($this->once())
->method('getRepository')
->willReturn($this->triggerEventRepository);
$this->triggerEventRepository->expects($this->once())
->method('find')
->willReturn($triggerEvent);
$this->dispatcher->expects($this->exactly(2))
->method('dispatch')
->willReturnCallback(function ($event, $eventName) use ($dispatchCalls, $contact, $triggerEvent) {
$dispatchCalls->append($eventName);
if (PointEvents::TRIGGER_ON_BUILD === $eventName) {
// Emulate a subscriber:
$event->addEvent(
'email.send_to_user',
[
'group' => 'mautic.email.point.trigger',
'label' => 'mautic.email.point.trigger.send_email_to_user',
'formType' => EmailToUserType::class,
'formTypeOptions' => ['update_select' => 'pointtriggerevent_properties_useremail_email'],
'formTheme' => 'MauticEmailBundle:FormTheme\EmailSendList',
'eventName' => EmailEvents::ON_SENT_EMAIL_TO_USER,
]
);
return $event;
} elseif (EmailEvents::ON_SENT_EMAIL_TO_USER === $eventName) {
Assert::assertSame($contact, $event->getLead());
Assert::assertSame($triggerEvent, $event->getTriggerEvent());
return $event;
} else {
$this->fail("Unexpected event name: $eventName");
}
});
$this->triggerModel->triggerEvent($triggerEvent->convertToArray(), $contact, true);
// Assert both expected events were dispatched
Assert::assertContains(PointEvents::TRIGGER_ON_BUILD, $dispatchCalls);
Assert::assertContains(EmailEvents::ON_SENT_EMAIL_TO_USER, $dispatchCalls);
Assert::assertCount(2, $dispatchCalls);
}
}