Initial commit: CloudOps infrastructure platform
This commit is contained in:
@@ -0,0 +1,463 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\CampaignBundle\Controller\Api;
|
||||
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
use Mautic\ApiBundle\Controller\CommonApiController;
|
||||
use Mautic\ApiBundle\Helper\EntityResultHelper;
|
||||
use Mautic\CampaignBundle\Entity\Campaign;
|
||||
use Mautic\CampaignBundle\Entity\Event;
|
||||
use Mautic\CampaignBundle\Membership\MembershipManager;
|
||||
use Mautic\CampaignBundle\Model\CampaignModel;
|
||||
use Mautic\CampaignBundle\Model\EventModel;
|
||||
use Mautic\CoreBundle\Event\EntityExportEvent;
|
||||
use Mautic\CoreBundle\Event\EntityImportEvent;
|
||||
use Mautic\CoreBundle\Factory\ModelFactory;
|
||||
use Mautic\CoreBundle\Helper\AppVersion;
|
||||
use Mautic\CoreBundle\Helper\CoreParametersHelper;
|
||||
use Mautic\CoreBundle\Helper\ImportHelper;
|
||||
use Mautic\CoreBundle\Helper\InputHelper;
|
||||
use Mautic\CoreBundle\Helper\UserHelper;
|
||||
use Mautic\CoreBundle\Security\Permissions\CorePermissions;
|
||||
use Mautic\CoreBundle\Translation\Translator;
|
||||
use Mautic\LeadBundle\Controller\LeadAccessTrait;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\Form\FormFactoryInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\RouterInterface;
|
||||
use Symfony\Component\Validator\ConstraintViolationInterface;
|
||||
use Symfony\Component\Validator\ConstraintViolationListInterface;
|
||||
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||
|
||||
/**
|
||||
* @extends CommonApiController<Campaign>
|
||||
*/
|
||||
class CampaignApiController extends CommonApiController
|
||||
{
|
||||
use LeadAccessTrait;
|
||||
|
||||
/**
|
||||
* @var CampaignModel|null
|
||||
*/
|
||||
protected $model;
|
||||
|
||||
public function __construct(
|
||||
CorePermissions $security,
|
||||
Translator $translator,
|
||||
EntityResultHelper $entityResultHelper,
|
||||
RouterInterface $router,
|
||||
FormFactoryInterface $formFactory,
|
||||
AppVersion $appVersion,
|
||||
private RequestStack $requestStack,
|
||||
private MembershipManager $membershipManager,
|
||||
ManagerRegistry $doctrine,
|
||||
ModelFactory $modelFactory,
|
||||
EventDispatcherInterface $dispatcher,
|
||||
CoreParametersHelper $coreParametersHelper,
|
||||
private ValidatorInterface $validator,
|
||||
private EventModel $eventModel,
|
||||
) {
|
||||
$campaignModel = $modelFactory->getModel('campaign');
|
||||
\assert($campaignModel instanceof CampaignModel);
|
||||
|
||||
$this->model = $campaignModel;
|
||||
$this->entityClass = Campaign::class;
|
||||
$this->entityNameOne = 'campaign';
|
||||
$this->entityNameMulti = 'campaigns';
|
||||
$this->permissionBase = 'campaign:campaigns';
|
||||
$this->serializerGroups = [
|
||||
'campaignDetails',
|
||||
'campaignEventDetails',
|
||||
'categoryList',
|
||||
'publishDetails',
|
||||
'leadListList',
|
||||
'formList',
|
||||
];
|
||||
|
||||
parent::__construct($security, $translator, $entityResultHelper, $router, $formFactory, $appVersion, $requestStack, $doctrine, $modelFactory, $dispatcher, $coreParametersHelper);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a lead to a campaign.
|
||||
*
|
||||
* @param int $id Campaign ID
|
||||
* @param int $leadId Lead ID
|
||||
*
|
||||
* @return Response
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
|
||||
*/
|
||||
public function addLeadAction($id, $leadId)
|
||||
{
|
||||
$entity = $this->model->getEntity($id);
|
||||
if (null !== $entity) {
|
||||
$leadModel = $this->getModel('lead');
|
||||
$lead = $leadModel->getEntity($leadId);
|
||||
|
||||
if (null == $lead) {
|
||||
return $this->notFound();
|
||||
} elseif (!$this->security->hasEntityAccess('lead:leads:editown', 'lead:leads:editother', $lead->getOwner())) {
|
||||
return $this->accessDenied();
|
||||
}
|
||||
|
||||
$this->membershipManager->addContact($lead, $entity);
|
||||
|
||||
$view = $this->view(['success' => 1], Response::HTTP_OK);
|
||||
|
||||
return $this->handleView($view);
|
||||
}
|
||||
|
||||
return $this->notFound();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes given lead from a campaign.
|
||||
*
|
||||
* @param int $id Campaign ID
|
||||
* @param int $leadId Lead ID
|
||||
*
|
||||
* @return Response
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
|
||||
*/
|
||||
public function removeLeadAction($id, $leadId)
|
||||
{
|
||||
$entity = $this->model->getEntity($id);
|
||||
if (null !== $entity) {
|
||||
$lead = $this->checkLeadAccess($leadId, 'edit');
|
||||
if ($lead instanceof Response) {
|
||||
return $lead;
|
||||
}
|
||||
|
||||
$this->membershipManager->removeContact($lead, $entity);
|
||||
|
||||
$view = $this->view(['success' => 1], Response::HTTP_OK);
|
||||
|
||||
return $this->handleView($view);
|
||||
}
|
||||
|
||||
return $this->notFound();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Campaign &$entity
|
||||
* @param string $action
|
||||
*/
|
||||
protected function preSaveEntity(&$entity, $form, $parameters, $action = 'edit')
|
||||
{
|
||||
$method = $this->requestStack->getCurrentRequest()->getMethod();
|
||||
|
||||
if ('POST' === $method || 'PUT' === $method) {
|
||||
if (empty($parameters['events'])) {
|
||||
$msg = $this->translator->trans('mautic.campaign.form.events.notempty', [], 'validators');
|
||||
|
||||
return $this->returnError($msg, Response::HTTP_BAD_REQUEST);
|
||||
} elseif (empty($parameters['lists']) && empty($parameters['forms'])) {
|
||||
$msg = $this->translator->trans('mautic.campaign.form.sources.notempty', [], 'validators');
|
||||
|
||||
return $this->returnError($msg, Response::HTTP_BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
|
||||
$deletedSources = ['lists' => [], 'forms' => []];
|
||||
$deletedEvents = [];
|
||||
$currentSources = [
|
||||
'lists' => isset($parameters['lists']) ? $this->modifyCampaignEventArray($parameters['lists']) : [],
|
||||
'forms' => isset($parameters['forms']) ? $this->modifyCampaignEventArray($parameters['forms']) : [],
|
||||
];
|
||||
|
||||
// delete events and sources which does not exist in the PUT request
|
||||
if ('PUT' === $method) {
|
||||
$requestEventIds = [];
|
||||
$requestSegmentIds = [];
|
||||
$requestFormIds = [];
|
||||
|
||||
foreach ($parameters['events'] as $key => $requestEvent) {
|
||||
if (!isset($requestEvent['id'])) {
|
||||
return $this->returnError('$campaign[events]['.$key.']["id"] is missing', Response::HTTP_BAD_REQUEST);
|
||||
}
|
||||
$requestEventIds[] = $requestEvent['id'];
|
||||
}
|
||||
|
||||
foreach ($entity->getEvents() as $currentEvent) {
|
||||
if (!in_array($currentEvent->getId(), $requestEventIds)) {
|
||||
$deletedEvents[] = $currentEvent->getId();
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($parameters['lists'])) {
|
||||
foreach ($parameters['lists'] as $requestSegment) {
|
||||
if (!isset($requestSegment['id'])) {
|
||||
return $this->returnError('$campaign[lists]['.$key.']["id"] is missing', Response::HTTP_BAD_REQUEST);
|
||||
}
|
||||
$requestSegmentIds[] = $requestSegment['id'];
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($entity->getLists() as $currentSegment) {
|
||||
if (!in_array($currentSegment->getId(), $requestSegmentIds)) {
|
||||
$deletedSources['lists'][$currentSegment->getId()] = 'ignore';
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($parameters['forms'])) {
|
||||
foreach ($parameters['forms'] as $requestForm) {
|
||||
if (!isset($requestForm['id'])) {
|
||||
return $this->returnError('$campaign[forms]['.$key.']["id"] is missing', Response::HTTP_BAD_REQUEST);
|
||||
}
|
||||
$requestFormIds[] = $requestForm['id'];
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($entity->getForms() as $currentForm) {
|
||||
if (!in_array($currentForm->getId(), $requestFormIds)) {
|
||||
$deletedSources['forms'][$currentForm->getId()] = 'ignore';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set lead sources
|
||||
$this->model->setLeadSources($entity, $currentSources, $deletedSources);
|
||||
|
||||
// Build and set Event entities
|
||||
if (isset($parameters['events']) && isset($parameters['canvasSettings'])) {
|
||||
$this->model->setEvents($entity, $parameters['events'], $parameters['canvasSettings'], $deletedEvents);
|
||||
}
|
||||
|
||||
/** @var array<ConstraintViolationListInterface<ConstraintViolationInterface>> $eventViolations */
|
||||
$eventViolations = array_filter(
|
||||
array_map(
|
||||
fn (Event $event) => $this->validator->validate($event),
|
||||
$entity->getEvents()->toArray()
|
||||
),
|
||||
fn ($error) => $error->count() > 0
|
||||
);
|
||||
|
||||
if (count($eventViolations) > 0) {
|
||||
$errors = [];
|
||||
foreach ($eventViolations as $violationList) {
|
||||
foreach ($violationList as $violation) {
|
||||
\assert($violation instanceof ConstraintViolationInterface);
|
||||
$errors[] = [
|
||||
'code' => $violation->getCode(),
|
||||
'message' => $violation->getMessage(),
|
||||
'details' => $violation->getPropertyPath(),
|
||||
'type' => 'validation',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$view = $this->view(['errors' => $errors], Response::HTTP_UNPROCESSABLE_ENTITY);
|
||||
|
||||
return $this->handleView($view);
|
||||
}
|
||||
|
||||
// Persist to the database before building connection so that IDs are available
|
||||
$this->model->saveEntity($entity);
|
||||
|
||||
// Update canvas settings with new event IDs then save
|
||||
if (isset($parameters['canvasSettings'])) {
|
||||
$this->model->setCanvasSettings($entity, $parameters['canvasSettings']);
|
||||
}
|
||||
|
||||
if (Request::METHOD_PUT === $method && !empty($deletedEvents)) {
|
||||
$this->eventModel->deleteEvents($entity->getEvents()->toArray(), $deletedEvents);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the array structure.
|
||||
*
|
||||
* @param array $events
|
||||
*/
|
||||
public function modifyCampaignEventArray($events): array
|
||||
{
|
||||
$updatedEvents = [];
|
||||
|
||||
if ($events && is_array($events)) {
|
||||
foreach ($events as $event) {
|
||||
if (!empty($event['id'])) {
|
||||
$updatedEvents[$event['id']] = 'ignore';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $updatedEvents;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a list of campaign contacts.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function getContactsAction(Request $request, $id)
|
||||
{
|
||||
$entity = $this->model->getEntity($id);
|
||||
|
||||
if (null === $entity) {
|
||||
return $this->notFound();
|
||||
}
|
||||
|
||||
if (!$this->checkEntityAccess($entity)) {
|
||||
return $this->accessDenied();
|
||||
}
|
||||
|
||||
$where = InputHelper::clean($request->query->get('where') ?? []);
|
||||
$order = InputHelper::clean($request->query->get('order') ?? []);
|
||||
$start = (int) $request->query->get('start', 0);
|
||||
$limit = (int) $request->query->get('limit', 100);
|
||||
|
||||
$where[] = [
|
||||
'col' => 'campaign_id',
|
||||
'expr' => 'eq',
|
||||
'val' => $id,
|
||||
];
|
||||
|
||||
$where[] = [
|
||||
'col' => 'manually_removed',
|
||||
'expr' => 'eq',
|
||||
'val' => 0,
|
||||
];
|
||||
|
||||
return $this->forward(
|
||||
'Mautic\CoreBundle\Controller\Api\StatsApiController::listAction',
|
||||
[
|
||||
'table' => 'campaign_leads',
|
||||
'itemsName' => 'contacts',
|
||||
'order' => $order,
|
||||
'where' => $where,
|
||||
'start' => $start,
|
||||
'limit' => $limit,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function cloneCampaignAction($campaignId)
|
||||
{
|
||||
if (empty($campaignId) || false == intval($campaignId)) {
|
||||
return $this->notFound();
|
||||
}
|
||||
|
||||
$original = $this->model->getEntity($campaignId);
|
||||
if (empty($original)) {
|
||||
return $this->notFound();
|
||||
}
|
||||
$entity = clone $original;
|
||||
|
||||
if (!$this->checkEntityAccess($entity, 'create')) {
|
||||
return $this->accessDenied();
|
||||
}
|
||||
|
||||
$this->model->saveEntity($entity);
|
||||
|
||||
$headers = [];
|
||||
// return the newly created entities location if applicable
|
||||
|
||||
$route = 'mautic_api_campaigns_getone';
|
||||
$headers['Location'] = $this->generateUrl(
|
||||
$route,
|
||||
array_merge(['id' => $entity->getId()], $this->routeParams),
|
||||
true
|
||||
);
|
||||
|
||||
$view = $this->view([$this->entityNameOne => $entity], Response::HTTP_OK, $headers);
|
||||
|
||||
$this->setSerializationContext($view);
|
||||
|
||||
return $this->handleView($view);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of events.
|
||||
*/
|
||||
public function exportCampaignAction(Request $request, int $campaignId): Response
|
||||
{
|
||||
// Check if the campaign exists
|
||||
$campaign = $this->model->getEntity($campaignId);
|
||||
if (!$campaign) {
|
||||
return $this->notFound();
|
||||
}
|
||||
|
||||
// Check if user has permission to export campaigns
|
||||
if (!$this->security->isGranted('campaign:export:enable', 'MATCH_ONE')) {
|
||||
return $this->accessDenied();
|
||||
}
|
||||
|
||||
// Dispatch event to collect campaign data for export
|
||||
$event = new EntityExportEvent(Campaign::ENTITY_NAME, $campaignId);
|
||||
$this->dispatcher->dispatch($event);
|
||||
$data = $event->getEntities();
|
||||
|
||||
// Prepare response
|
||||
$view = $this->view([$data], Response::HTTP_OK);
|
||||
$this->setSerializationContext($view);
|
||||
|
||||
return $this->handleView($view);
|
||||
}
|
||||
|
||||
public function importCampaignAction(Request $request, UserHelper $userHelper, ImportHelper $importHelper): Response
|
||||
{
|
||||
// Check if user has permission to import campaigns
|
||||
if (!$this->security->isGranted('campaign:imports:create')) {
|
||||
return $this->accessDenied();
|
||||
}
|
||||
|
||||
// Decode request JSON
|
||||
$data = json_decode($request->getContent(), true);
|
||||
|
||||
if (!$data || !isset($data[0][Campaign::ENTITY_NAME])) {
|
||||
$files = $request->files->all();
|
||||
|
||||
if (1 !== count($files)) {
|
||||
return $this->handleView(
|
||||
$this->view(['error' => $this->translator->trans('mautic.campaign.api.import.incorrect_zip_file', [], 'messages')], Response::HTTP_BAD_REQUEST)
|
||||
);
|
||||
}
|
||||
|
||||
$uploadedFile = array_values($files)[0];
|
||||
|
||||
if (!$uploadedFile->isValid()) {
|
||||
return $this->handleView(
|
||||
$this->view(['error' => $this->translator->trans('mautic.campaign.api.import.upload_failed', [], 'messages')], Response::HTTP_BAD_REQUEST)
|
||||
);
|
||||
}
|
||||
|
||||
if ('zip' !== strtolower($uploadedFile->getClientOriginalExtension())) {
|
||||
return $this->handleView(
|
||||
$this->view(['error' => $this->translator->trans('mautic.campaign.api.import.incorrect_upload_file_format', [], 'messages')], Response::HTTP_BAD_REQUEST)
|
||||
);
|
||||
}
|
||||
|
||||
$zipPath = $uploadedFile->getPathname();
|
||||
|
||||
if (!file_exists($zipPath)) {
|
||||
return $this->handleView(
|
||||
$this->view(['error' => $this->translator->trans('mautic.campaign.api.import.uploaded_file_no_exist', [], 'messages')], Response::HTTP_INTERNAL_SERVER_ERROR)
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
$data = $importHelper->readZipFile($zipPath);
|
||||
} catch (\RuntimeException $e) {
|
||||
unlink($zipPath);
|
||||
|
||||
return $this->handleView(
|
||||
$this->view(['error' => $e->getMessage()], Response::HTTP_BAD_REQUEST)
|
||||
);
|
||||
}
|
||||
}
|
||||
$importHelper->recursiveRemoveEmailaddress($data);
|
||||
$userId = $userHelper->getUser()->getId();
|
||||
|
||||
foreach ($data as $entity) {
|
||||
$event = new EntityImportEvent(Campaign::ENTITY_NAME, $entity, $userId);
|
||||
$this->dispatcher->dispatch($event);
|
||||
}
|
||||
$view = $this->view([$this->translator->trans('mautic.campaign.campaign.import.finished', [], 'messages')], Response::HTTP_CREATED);
|
||||
$this->setSerializationContext($view);
|
||||
|
||||
return $this->handleView($view);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\CampaignBundle\Controller\Api;
|
||||
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
use Mautic\ApiBundle\Controller\CommonApiController;
|
||||
use Mautic\ApiBundle\Helper\EntityResultHelper;
|
||||
use Mautic\ApiBundle\Serializer\Exclusion\FieldExclusionStrategy;
|
||||
use Mautic\CampaignBundle\Entity\Event;
|
||||
use Mautic\CampaignBundle\Model\EventModel;
|
||||
use Mautic\CoreBundle\Entity\FormEntity;
|
||||
use Mautic\CoreBundle\Factory\ModelFactory;
|
||||
use Mautic\CoreBundle\Helper\AppVersion;
|
||||
use Mautic\CoreBundle\Helper\CoreParametersHelper;
|
||||
use Mautic\CoreBundle\Security\Permissions\CorePermissions;
|
||||
use Mautic\CoreBundle\Translation\Translator;
|
||||
use Mautic\LeadBundle\Controller\LeadAccessTrait;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\Form\FormFactoryInterface;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\Routing\RouterInterface;
|
||||
|
||||
/**
|
||||
* @extends CommonApiController<Event>
|
||||
*/
|
||||
class EventApiController extends CommonApiController
|
||||
{
|
||||
use LeadAccessTrait;
|
||||
|
||||
public function __construct(CorePermissions $security, Translator $translator, EntityResultHelper $entityResultHelper, RouterInterface $router, FormFactoryInterface $formFactory, AppVersion $appVersion, RequestStack $requestStack, ManagerRegistry $doctrine, ModelFactory $modelFactory, EventDispatcherInterface $dispatcher, CoreParametersHelper $coreParametersHelper)
|
||||
{
|
||||
$campaignEventModel = $modelFactory->getModel('campaign.event');
|
||||
\assert($campaignEventModel instanceof EventModel);
|
||||
|
||||
$this->model = $campaignEventModel;
|
||||
$this->entityClass = Event::class;
|
||||
$this->entityNameOne = 'event';
|
||||
$this->entityNameMulti = 'events';
|
||||
$this->serializerGroups = ['campaignEventStandaloneDetails', 'campaignList'];
|
||||
$this->parentChildrenLevelDepth = 1;
|
||||
|
||||
// Don't include campaign in children/parent arrays
|
||||
$this->addExclusionStrategy(new FieldExclusionStrategy(['campaign'], 1));
|
||||
|
||||
parent::__construct($security, $translator, $entityResultHelper, $router, $formFactory, $appVersion, $requestStack, $doctrine, $modelFactory, $dispatcher, $coreParametersHelper);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Event|FormEntity $entity
|
||||
*/
|
||||
protected function checkEntityAccess($entity, $action = 'view')
|
||||
{
|
||||
// Use the campaign for permission checks
|
||||
return parent::checkEntityAccess($entity->getCampaign(), $action);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,276 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\CampaignBundle\Controller\Api;
|
||||
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
use FOS\RestBundle\View\View;
|
||||
use Mautic\ApiBundle\Controller\FetchCommonApiController;
|
||||
use Mautic\ApiBundle\Helper\EntityResultHelper;
|
||||
use Mautic\ApiBundle\Serializer\Exclusion\FieldInclusionStrategy;
|
||||
use Mautic\CampaignBundle\Entity\Campaign;
|
||||
use Mautic\CampaignBundle\Entity\Event;
|
||||
use Mautic\CampaignBundle\Entity\LeadEventLog;
|
||||
use Mautic\CampaignBundle\Model\EventLogModel;
|
||||
use Mautic\CampaignBundle\Model\EventModel;
|
||||
use Mautic\CoreBundle\Factory\ModelFactory;
|
||||
use Mautic\CoreBundle\Helper\AppVersion;
|
||||
use Mautic\CoreBundle\Helper\CoreParametersHelper;
|
||||
use Mautic\CoreBundle\Helper\UserHelper;
|
||||
use Mautic\CoreBundle\Security\Permissions\CorePermissions;
|
||||
use Mautic\CoreBundle\Translation\Translator;
|
||||
use Mautic\LeadBundle\Controller\LeadAccessTrait;
|
||||
use Mautic\LeadBundle\Entity\Lead;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
/**
|
||||
* @extends FetchCommonApiController<LeadEventLog>
|
||||
*/
|
||||
class EventLogApiController extends FetchCommonApiController
|
||||
{
|
||||
use LeadAccessTrait;
|
||||
|
||||
private const LOG_SERIALIZATION = 30;
|
||||
|
||||
/**
|
||||
* @var Campaign
|
||||
*/
|
||||
protected $campaign;
|
||||
|
||||
/**
|
||||
* @var Lead
|
||||
*/
|
||||
protected $contact;
|
||||
|
||||
/**
|
||||
* @var EventLogModel|null
|
||||
*/
|
||||
protected $model;
|
||||
|
||||
public function __construct(
|
||||
CorePermissions $security,
|
||||
Translator $translator,
|
||||
EntityResultHelper $entityResultHelper,
|
||||
AppVersion $appVersion,
|
||||
RequestStack $requestStack,
|
||||
ManagerRegistry $doctrine,
|
||||
ModelFactory $modelFactory,
|
||||
EventDispatcherInterface $dispatcher,
|
||||
CoreParametersHelper $coreParametersHelper,
|
||||
) {
|
||||
$campaignEventLogModel = $modelFactory->getModel('campaign.event_log');
|
||||
\assert($campaignEventLogModel instanceof EventLogModel);
|
||||
$this->model = $campaignEventLogModel;
|
||||
$this->entityClass = LeadEventLog::class;
|
||||
$this->entityNameOne = 'event';
|
||||
$this->entityNameMulti = 'events';
|
||||
$this->parentChildrenLevelDepth = 1;
|
||||
$this->serializerGroups = [
|
||||
'campaignList',
|
||||
'ipAddressList',
|
||||
self::LOG_SERIALIZATION => 'campaignEventLogDetails',
|
||||
];
|
||||
|
||||
// Only include the id of the parent
|
||||
$this->addExclusionStrategy(new FieldInclusionStrategy(['id'], 1, 'parent'));
|
||||
|
||||
parent::__construct($security, $translator, $entityResultHelper, $appVersion, $requestStack, $doctrine, $modelFactory, $dispatcher, $coreParametersHelper);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Response
|
||||
*/
|
||||
public function getEntitiesAction(Request $request, UserHelper $userHelper)
|
||||
{
|
||||
$this->serializerGroups[self::LOG_SERIALIZATION] = 'campaignEventStandaloneLogDetails';
|
||||
$this->serializerGroups[] = 'campaignEventStandaloneList';
|
||||
$this->serializerGroups[] = 'leadBasicList';
|
||||
|
||||
return parent::getEntitiesAction($request, $userHelper);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of events.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function getContactEventsAction(Request $request, UserHelper $userHelper, $contactId, $campaignId = null)
|
||||
{
|
||||
// Ensure contact exists and user has access
|
||||
$contact = $this->checkLeadAccess($contactId, 'view');
|
||||
if ($contact instanceof Response) {
|
||||
return $contact;
|
||||
}
|
||||
|
||||
// Ensure campaign exists and user has access
|
||||
if (!empty($campaignId)) {
|
||||
$campaign = $this->getModel('campaign')->getEntity($campaignId);
|
||||
if (null == $campaign || !$campaign->getId()) {
|
||||
return $this->notFound();
|
||||
}
|
||||
if (!$this->checkEntityAccess($campaign)) {
|
||||
return $this->accessDenied();
|
||||
}
|
||||
// Check that contact is part of the campaign
|
||||
$membership = $campaign->getContactMembership($contact);
|
||||
if (0 === count($membership)) {
|
||||
return $this->returnError(
|
||||
$this->translator->trans(
|
||||
'mautic.campaign.error.contact_not_in_campaign',
|
||||
['%campaign%' => $campaignId, '%contact%' => $contactId]
|
||||
),
|
||||
Response::HTTP_CONFLICT
|
||||
);
|
||||
}
|
||||
|
||||
$this->campaign = $campaign;
|
||||
$this->serializerGroups[] = 'campaignEventWithLogsList';
|
||||
$this->serializerGroups[] = 'campaignLeadList';
|
||||
} else {
|
||||
unset($this->serializerGroups[self::LOG_SERIALIZATION]);
|
||||
$this->serializerGroups[] = 'campaignEventStandaloneList';
|
||||
$this->serializerGroups[] = 'campaignEventStandaloneLogDetails';
|
||||
}
|
||||
|
||||
$this->contact = $contact;
|
||||
$this->extraGetEntitiesArguments = [
|
||||
'contact_id' => $contactId,
|
||||
'campaign_id' => $campaignId,
|
||||
];
|
||||
|
||||
return $this->getEntitiesAction($request, $userHelper);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Response
|
||||
*/
|
||||
public function editContactEventAction(Request $request, $eventId, $contactId)
|
||||
{
|
||||
$parameters = $request->request->all();
|
||||
|
||||
// Ensure contact exists and user has access
|
||||
$contact = $this->checkLeadAccess($contactId, 'edit');
|
||||
if ($contact instanceof Response) {
|
||||
return $contact;
|
||||
}
|
||||
|
||||
/** @var EventModel $eventModel */
|
||||
$eventModel = $this->getModel('campaign.event');
|
||||
/** @var Event $event */
|
||||
$event = $eventModel->getEntity($eventId);
|
||||
if (null === $event || !$event->getId()) {
|
||||
return $this->notFound();
|
||||
}
|
||||
|
||||
// Ensure campaign edit access
|
||||
$campaign = $event->getCampaign();
|
||||
if (!$this->checkEntityAccess($campaign, 'edit')) {
|
||||
return $this->accessDenied();
|
||||
}
|
||||
|
||||
$result = $this->model->updateContactEvent($event, $contact, $parameters);
|
||||
|
||||
if (is_string($result)) {
|
||||
return $this->returnError($result, Response::HTTP_CONFLICT);
|
||||
} else {
|
||||
[$log, $created] = $result;
|
||||
}
|
||||
|
||||
$event->addContactLog($log);
|
||||
$view = $this->view(
|
||||
[
|
||||
$this->entityNameOne => $event,
|
||||
],
|
||||
($created) ? Response::HTTP_CREATED : Response::HTTP_OK
|
||||
);
|
||||
$this->serializerGroups[] = 'campaignEventWithLogsDetails';
|
||||
$this->serializerGroups[] = 'campaignBasicList';
|
||||
$this->setSerializationContext($view);
|
||||
|
||||
return $this->handleView($view);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|Response
|
||||
*/
|
||||
public function editEventsAction(Request $request)
|
||||
{
|
||||
$parameters = $request->request->all();
|
||||
|
||||
$valid = $this->validateBatchPayload($parameters);
|
||||
if ($valid instanceof Response) {
|
||||
return $valid;
|
||||
}
|
||||
|
||||
$events = $this->getBatchEntities($parameters, $errors, false, 'eventId', $this->getModel('campaign.event'), false);
|
||||
$contacts = $this->getBatchEntities($parameters, $errors, false, 'contactId', $this->getModel('lead'), false);
|
||||
|
||||
$this->inBatchMode = true;
|
||||
$errors = [];
|
||||
foreach ($parameters as $key => $params) {
|
||||
if (!isset($params['eventId']) || !isset($params['contactId']) || !isset($events[$params['eventId']])
|
||||
|| !isset($contacts[$params['contactId']])
|
||||
) {
|
||||
$errors[$key] = $this->notFound('mautic.campaign.error.edit_events.request_invalid');
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$event = $events[$params['eventId']];
|
||||
|
||||
// Ensure contact exists and user has access
|
||||
$contact = $this->checkLeadAccess($contacts[$params['contactId']], 'edit');
|
||||
if ($contact instanceof Response) {
|
||||
$errors[$key] = $contact->getContent();
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ensure campaign edit access
|
||||
$campaign = $event->getCampaign();
|
||||
if (!$this->checkEntityAccess($campaign, 'edit')) {
|
||||
$errors[$key] = $this->accessDenied();
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$result = $this->model->updateContactEvent($event, $contact, $params);
|
||||
|
||||
if (is_string($result)) {
|
||||
$errors[$key] = $this->returnError($result, Response::HTTP_CONFLICT);
|
||||
} else {
|
||||
[$log, $created] = $result;
|
||||
$event->addContactLog($log);
|
||||
}
|
||||
}
|
||||
|
||||
$payload = [
|
||||
$this->entityNameMulti => $events,
|
||||
];
|
||||
|
||||
if (!empty($errors)) {
|
||||
$payload['errors'] = $errors;
|
||||
}
|
||||
|
||||
$view = $this->view($payload, Response::HTTP_OK);
|
||||
$this->serializerGroups[] = 'campaignEventWithLogsList';
|
||||
$this->setSerializationContext($view);
|
||||
|
||||
return $this->handleView($view);
|
||||
}
|
||||
|
||||
protected function view($data = null, ?int $statusCode = null, array $headers = []): View
|
||||
{
|
||||
if ($this->campaign) {
|
||||
$data['campaign'] = $this->campaign;
|
||||
|
||||
if ($this->contact) {
|
||||
[$data['membership'], $ignore] = $this->prepareEntitiesForView($this->campaign->getContactMembership($this->contact));
|
||||
}
|
||||
}
|
||||
|
||||
return parent::view($data, $statusCode, $headers);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user