Initial commit: CloudOps infrastructure platform
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\PointBundle\Controller\Api;
|
||||
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
use Mautic\ApiBundle\Controller\CommonApiController;
|
||||
use Mautic\ApiBundle\Helper\EntityResultHelper;
|
||||
use Mautic\CoreBundle\Factory\ModelFactory;
|
||||
use Mautic\CoreBundle\Helper\AppVersion;
|
||||
use Mautic\CoreBundle\Helper\CoreParametersHelper;
|
||||
use Mautic\CoreBundle\Helper\InputHelper;
|
||||
use Mautic\CoreBundle\Helper\IpLookupHelper;
|
||||
use Mautic\CoreBundle\Security\Permissions\CorePermissions;
|
||||
use Mautic\CoreBundle\Translation\Translator;
|
||||
use Mautic\LeadBundle\Controller\LeadAccessTrait;
|
||||
use Mautic\LeadBundle\Model\LeadModel;
|
||||
use Mautic\PointBundle\Entity\Point;
|
||||
use Mautic\PointBundle\Model\PointModel;
|
||||
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<Point>
|
||||
*/
|
||||
class PointApiController extends CommonApiController
|
||||
{
|
||||
use LeadAccessTrait;
|
||||
|
||||
protected LeadModel $leadModel;
|
||||
|
||||
/**
|
||||
* @var PointModel|null
|
||||
*/
|
||||
protected $model;
|
||||
|
||||
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)
|
||||
{
|
||||
$leadModel = $modelFactory->getModel('lead');
|
||||
\assert($leadModel instanceof LeadModel);
|
||||
|
||||
$pointModel = $modelFactory->getModel('point');
|
||||
\assert($pointModel instanceof PointModel);
|
||||
|
||||
$this->model = $pointModel;
|
||||
$this->leadModel = $leadModel;
|
||||
$this->entityClass = Point::class;
|
||||
$this->entityNameOne = 'point';
|
||||
$this->entityNameMulti = 'points';
|
||||
$this->serializerGroups = ['pointDetails', 'categoryList', 'publishDetails'];
|
||||
|
||||
parent::__construct($security, $translator, $entityResultHelper, $router, $formFactory, $appVersion, $requestStack, $doctrine, $modelFactory, $dispatcher, $coreParametersHelper);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return array of available point action types.
|
||||
*/
|
||||
public function getPointActionTypesAction()
|
||||
{
|
||||
if (!$this->security->isGranted([$this->permissionBase.':view', $this->permissionBase.':viewown'])) {
|
||||
return $this->accessDenied();
|
||||
}
|
||||
|
||||
$actionTypes = $this->model->getPointActions();
|
||||
$view = $this->view(['pointActionTypes' => $actionTypes['list']]);
|
||||
|
||||
return $this->handleView($view);
|
||||
}
|
||||
|
||||
/**
|
||||
* Subtract points from a lead.
|
||||
*
|
||||
* @param int $leadId
|
||||
* @param string $operator
|
||||
* @param int $delta
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function adjustPointsAction(Request $request, IpLookupHelper $ipLookupHelper, $leadId, $operator, $delta)
|
||||
{
|
||||
$lead = $this->checkLeadAccess($leadId, 'edit');
|
||||
if ($lead instanceof Response) {
|
||||
return $lead;
|
||||
}
|
||||
|
||||
try {
|
||||
$this->logApiPointChange($request, $ipLookupHelper, $lead, $delta, $operator);
|
||||
} catch (\Exception $e) {
|
||||
return $this->returnError($e->getMessage(), Response::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
return $this->handleView($this->view(['success' => 1], Response::HTTP_OK));
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the lead points change.
|
||||
*
|
||||
* @param int $delta
|
||||
*/
|
||||
protected function logApiPointChange(Request $request, IpLookupHelper $ipLookupHelper, $lead, $delta, $operator)
|
||||
{
|
||||
$trans = $this->translator;
|
||||
$ip = $ipLookupHelper->getIpAddress();
|
||||
$eventName = InputHelper::clean($request->request->get('eventName', $trans->trans('mautic.lead.lead.submitaction.operator_'.$operator)));
|
||||
$actionName = InputHelper::clean($request->request->get('actionName', $trans->trans('mautic.lead.event.api')));
|
||||
|
||||
$lead->adjustPoints($delta, $operator);
|
||||
$lead->addPointsChangeLogEntry('API', $eventName, $actionName, $delta, $ip);
|
||||
$this->leadModel->saveEntity($lead, false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\PointBundle\Controller\Api;
|
||||
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
use Mautic\ApiBundle\Controller\CommonApiController;
|
||||
use Mautic\ApiBundle\Helper\EntityResultHelper;
|
||||
use Mautic\CoreBundle\Factory\ModelFactory;
|
||||
use Mautic\CoreBundle\Helper\AppVersion;
|
||||
use Mautic\CoreBundle\Helper\CoreParametersHelper;
|
||||
use Mautic\CoreBundle\Helper\InputHelper;
|
||||
use Mautic\CoreBundle\Helper\IpLookupHelper;
|
||||
use Mautic\CoreBundle\Security\Permissions\CorePermissions;
|
||||
use Mautic\CoreBundle\Translation\Translator;
|
||||
use Mautic\LeadBundle\Model\LeadModel;
|
||||
use Mautic\PointBundle\Entity\Group;
|
||||
use Mautic\PointBundle\Model\PointGroupModel;
|
||||
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<Group>
|
||||
*/
|
||||
class PointGroupsApiController extends CommonApiController
|
||||
{
|
||||
/**
|
||||
* @var PointGroupModel
|
||||
*/
|
||||
protected $model;
|
||||
|
||||
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, PointGroupModel $pointGroupModel, private LeadModel $leadModel)
|
||||
{
|
||||
$this->model = $pointGroupModel;
|
||||
$this->entityClass = Group::class;
|
||||
$this->entityNameOne = 'pointGroup';
|
||||
$this->entityNameMulti = 'pointGroups';
|
||||
$this->serializerGroups = ['pointGroupDetails', 'pointGroupList', 'publishDetails'];
|
||||
|
||||
parent::__construct($security, $translator, $entityResultHelper, $router, $formFactory, $appVersion, $requestStack, $doctrine, $modelFactory, $dispatcher, $coreParametersHelper);
|
||||
}
|
||||
|
||||
public function getContactPointGroupsAction(int $contactId): Response
|
||||
{
|
||||
$contact = $this->leadModel->getEntity($contactId);
|
||||
|
||||
if (null === $contact) {
|
||||
return $this->notFound($this->translator->trans('mautic.lead.event.api.lead.not.found'));
|
||||
}
|
||||
|
||||
if (!$this->checkEntityAccess($contact)) {
|
||||
return $this->accessDenied();
|
||||
}
|
||||
|
||||
$groupScores = $contact->getGroupScores();
|
||||
$view = $this->view(
|
||||
[
|
||||
'total' => count($groupScores),
|
||||
'groupScores' => $groupScores,
|
||||
],
|
||||
Response::HTTP_OK
|
||||
);
|
||||
|
||||
$context = $view->getContext()->setGroups(['groupContactScoreDetails', 'pointGroupDetails']);
|
||||
$view->setContext($context);
|
||||
|
||||
return $this->handleView($view);
|
||||
}
|
||||
|
||||
public function getContactPointGroupAction(int $contactId, int $groupId): Response
|
||||
{
|
||||
$contact = $this->leadModel->getEntity($contactId);
|
||||
|
||||
if (null === $contact) {
|
||||
return $this->notFound($this->translator->trans('mautic.lead.event.api.lead.not.found'));
|
||||
}
|
||||
|
||||
if (!$this->checkEntityAccess($contact)) {
|
||||
return $this->accessDenied();
|
||||
}
|
||||
|
||||
$pointGroup = $this->model->getEntity($groupId);
|
||||
if (null === $pointGroup) {
|
||||
return $this->notFound($this->translator->trans('mautic.lead.event.api.point.group.not.found'));
|
||||
}
|
||||
|
||||
$groupScore = $contact->getGroupScore($pointGroup);
|
||||
$view = $this->view(
|
||||
[
|
||||
'groupScore' => $groupScore,
|
||||
],
|
||||
Response::HTTP_OK
|
||||
);
|
||||
|
||||
$context = $view->getContext()->setGroups(['groupContactScoreDetails', 'pointGroupDetails']);
|
||||
$view->setContext($context);
|
||||
|
||||
return $this->handleView($view);
|
||||
}
|
||||
|
||||
public function adjustGroupPointsAction(Request $request, IpLookupHelper $ipLookupHelper, int $contactId, int $groupId, string $operator, int $value): Response
|
||||
{
|
||||
$contact = $this->leadModel->getEntity($contactId);
|
||||
|
||||
if (null === $contact) {
|
||||
return $this->notFound($this->translator->trans('mautic.lead.event.api.lead.not.found'));
|
||||
}
|
||||
|
||||
if (!$this->checkEntityAccess($contact)) {
|
||||
return $this->accessDenied();
|
||||
}
|
||||
|
||||
$pointGroup = $this->model->getEntity($groupId);
|
||||
if (null === $pointGroup) {
|
||||
return $this->notFound($this->translator->trans('mautic.lead.event.api.point.group.not.found'));
|
||||
}
|
||||
|
||||
if (!PointGroupModel::isAllowedPointOperation($operator)) {
|
||||
return $this->badRequest($this->translator->trans('mautic.lead.event.api.operation.not.allowed'));
|
||||
}
|
||||
|
||||
$oldScore = $contact->getGroupScore($pointGroup)?->getScore();
|
||||
$contact = $this->model->adjustPoints($contact, $pointGroup, $value, $operator);
|
||||
$newScore = $contact->getGroupScore($pointGroup)->getScore();
|
||||
$delta = $newScore - ($oldScore ?? 0);
|
||||
|
||||
$eventName = InputHelper::clean($request->request->get('eventName', $this->translator->trans('mautic.point.event.manual_change')));
|
||||
$actionName = InputHelper::clean($request->request->get('actionName', $this->translator->trans('mautic.lead.event.api')));
|
||||
$contact->addPointsChangeLogEntry(
|
||||
type: 'API',
|
||||
name: $eventName,
|
||||
action: $actionName,
|
||||
pointChanges: $delta,
|
||||
ip: $ipLookupHelper->getIpAddress(),
|
||||
group: $pointGroup
|
||||
);
|
||||
$this->leadModel->saveEntity($contact, false);
|
||||
|
||||
$view = $this->view(['groupScore' => $contact->getGroupScore($pointGroup)], Response::HTTP_OK);
|
||||
$context = $view->getContext()->setGroups(['groupContactScoreDetails', 'pointGroupDetails']);
|
||||
$view->setContext($context);
|
||||
|
||||
return $this->handleView($view);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\PointBundle\Controller\Api;
|
||||
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
use Mautic\ApiBundle\Controller\CommonApiController;
|
||||
use Mautic\ApiBundle\Helper\EntityResultHelper;
|
||||
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\PointBundle\Entity\Trigger;
|
||||
use Mautic\PointBundle\Model\TriggerEventModel;
|
||||
use Mautic\PointBundle\Model\TriggerModel;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\Form\FormFactoryInterface;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\RouterInterface;
|
||||
|
||||
/**
|
||||
* @extends CommonApiController<Trigger>
|
||||
*/
|
||||
class TriggerApiController extends CommonApiController
|
||||
{
|
||||
/**
|
||||
* @var TriggerModel|null
|
||||
*/
|
||||
protected $model;
|
||||
|
||||
public function __construct(
|
||||
CorePermissions $security,
|
||||
Translator $translator,
|
||||
EntityResultHelper $entityResultHelper,
|
||||
RouterInterface $router,
|
||||
FormFactoryInterface $formFactory,
|
||||
AppVersion $appVersion,
|
||||
private ?RequestStack $requestStack,
|
||||
ManagerRegistry $doctrine,
|
||||
ModelFactory $modelFactory,
|
||||
EventDispatcherInterface $dispatcher,
|
||||
CoreParametersHelper $coreParametersHelper,
|
||||
) {
|
||||
$triggerModel = $modelFactory->getModel('point.trigger');
|
||||
\assert($triggerModel instanceof TriggerModel);
|
||||
|
||||
$this->model = $triggerModel;
|
||||
$this->entityClass = Trigger::class;
|
||||
$this->entityNameOne = 'trigger';
|
||||
$this->entityNameMulti = 'triggers';
|
||||
$this->serializerGroups = ['triggerDetails', 'categoryList', 'publishDetails'];
|
||||
|
||||
parent::__construct($security, $translator, $entityResultHelper, $router, $formFactory, $appVersion, $requestStack, $doctrine, $modelFactory, $dispatcher, $coreParametersHelper);
|
||||
}
|
||||
|
||||
protected function preSaveEntity(&$entity, $form, $parameters, $action = 'edit')
|
||||
{
|
||||
$method = $this->requestStack->getCurrentRequest()->getMethod();
|
||||
$triggerEventModel = $this->getModel('point.triggerevent');
|
||||
$isNew = false;
|
||||
|
||||
// Set timestamps
|
||||
$this->model->setTimestamps($entity, true, false);
|
||||
|
||||
if (!$entity->getId()) {
|
||||
$isNew = true;
|
||||
|
||||
// Save the entitz first to get the ID.
|
||||
// Using the repository function to not trigger the listeners twice.
|
||||
$this->model->getRepository()->saveEntity($entity);
|
||||
}
|
||||
|
||||
$requestTriggerIds = [];
|
||||
$currentEvents = $entity->getEvents();
|
||||
|
||||
// Add events from the request
|
||||
if (!empty($parameters['events']) && is_array($parameters['events'])) {
|
||||
foreach ($parameters['events'] as &$eventParams) {
|
||||
if (empty($eventParams['id'])) {
|
||||
// Create an unique ID if not set - the following code requires one
|
||||
$eventParams['id'] = 'new'.hash('sha1', uniqid(mt_rand()));
|
||||
$triggerEventEntity = $triggerEventModel->getEntity();
|
||||
} else {
|
||||
$triggerEventEntity = $triggerEventModel->getEntity($eventParams['id']);
|
||||
$requestTriggerIds[] = $eventParams['id'];
|
||||
}
|
||||
|
||||
$triggerEventForm = $this->createTriggerEventEntityForm($triggerEventEntity);
|
||||
$triggerEventForm->submit($eventParams, 'PATCH' !== $method);
|
||||
|
||||
if (!($triggerEventForm->isSubmitted() && $triggerEventForm->isValid())) {
|
||||
$formErrors = $this->getFormErrorMessages($triggerEventForm);
|
||||
$msg = $this->getFormErrorMessage($formErrors);
|
||||
|
||||
return $this->returnError('Trigger events: '.$msg, Response::HTTP_BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
|
||||
$this->model->setEvents($entity, $parameters['events']);
|
||||
}
|
||||
|
||||
// Remove events which weren't in the PUT request
|
||||
if (!$isNew && 'PUT' === $method) {
|
||||
foreach ($currentEvents as $currentEvent) {
|
||||
if (!in_array($currentEvent->getId(), $requestTriggerIds)) {
|
||||
$entity->removeTriggerEvent($currentEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return FormInterface<mixed>
|
||||
*/
|
||||
protected function createTriggerEventEntityForm($entity): FormInterface
|
||||
{
|
||||
$triggerEventModel = $this->getModel('point.triggerevent');
|
||||
\assert($triggerEventModel instanceof TriggerEventModel);
|
||||
|
||||
return $triggerEventModel->createForm(
|
||||
$entity,
|
||||
$this->formFactory,
|
||||
null,
|
||||
[
|
||||
'csrf_protection' => false,
|
||||
'allow_extra_fields' => true,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return array of available point trigger event types.
|
||||
*/
|
||||
public function getPointTriggerEventTypesAction()
|
||||
{
|
||||
if (!$this->security->isGranted([$this->permissionBase.':view', $this->permissionBase.':viewown'])) {
|
||||
return $this->accessDenied();
|
||||
}
|
||||
|
||||
$eventTypesRaw = $this->model->getEvents();
|
||||
$eventTypes = [];
|
||||
|
||||
foreach ($eventTypesRaw as $key => $type) {
|
||||
$eventTypes[$key] = $type['label'];
|
||||
}
|
||||
|
||||
$view = $this->view(['eventTypes' => $eventTypes]);
|
||||
|
||||
return $this->handleView($view);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete events from a point trigger.
|
||||
*
|
||||
* @param int $triggerId
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function deletePointTriggerEventsAction($triggerId)
|
||||
{
|
||||
if (!$this->security->isGranted([$this->permissionBase.':editown', $this->permissionBase.':editother'], 'MATCH_ONE')) {
|
||||
return $this->accessDenied();
|
||||
}
|
||||
|
||||
$entity = $this->model->getEntity($triggerId);
|
||||
|
||||
if (null === $entity) {
|
||||
return $this->notFound();
|
||||
}
|
||||
|
||||
$eventsToDelete = $this->requestStack->getCurrentRequest()->get('events');
|
||||
$currentEvents = $entity->getEvents();
|
||||
|
||||
if (!is_array($eventsToDelete)) {
|
||||
return $this->badRequest('The events attribute must be array.');
|
||||
}
|
||||
|
||||
foreach ($currentEvents as $currentEvent) {
|
||||
if (in_array($currentEvent->getId(), $eventsToDelete)) {
|
||||
$entity->removeTriggerEvent($currentEvent);
|
||||
}
|
||||
}
|
||||
|
||||
$view = $this->view([$this->entityNameOne => $entity]);
|
||||
|
||||
return $this->handleView($view);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user