Spaces:
No application file
No application file
| 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\Membership\MembershipManager; | |
| use Mautic\CampaignBundle\Model\CampaignModel; | |
| use Mautic\CampaignBundle\Model\EventModel; | |
| use Mautic\CoreBundle\Factory\MauticFactory; | |
| use Mautic\CoreBundle\Factory\ModelFactory; | |
| use Mautic\CoreBundle\Helper\AppVersion; | |
| use Mautic\CoreBundle\Helper\CoreParametersHelper; | |
| use Mautic\CoreBundle\Helper\InputHelper; | |
| 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; | |
| /** | |
| * @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, | |
| MauticFactory $factory | |
| ) { | |
| $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, $factory); | |
| } | |
| /** | |
| * 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); | |
| } | |
| // 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)) { | |
| $campaignEventModel = $this->getModel('campaign.event'); | |
| \assert($campaignEventModel instanceof EventModel); | |
| $campaignEventModel->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); | |
| } | |
| } | |