Controller/TriggerCampaignController.php
<?php
namespace MauticPlugin\LeuchtfeuerPrintmailingBundle\Controller;
use Doctrine\ORM\EntityNotFoundException;
use Mautic\CoreBundle\Controller\AbstractFormController;
use Mautic\CoreBundle\Helper\CoreParametersHelper;
use MauticPlugin\LeuchtfeuerPrintmailingBundle\Entity\TriggerCampaign;
use MauticPlugin\LeuchtfeuerPrintmailingBundle\Entity\TriggerCampaignRepository;
use MauticPlugin\LeuchtfeuerPrintmailingBundle\Model\TriggerCampaignModel;
use MauticPlugin\LeuchtfeuerPrintmailingBundle\Utility\SingleSignOnUtility;
use Symfony\Component\Form\Form;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
class TriggerCampaignController extends AbstractFormController
{
public const PERMISSIONS = [
'create' => 'printmailing:campaigns:create',
'delete' => 'printmailing:campaigns:delete',
'edit' => 'printmailing:campaigns:edit',
'publish' => 'printmailing:campaigns:publish',
'view' => 'printmailing:campaigns:view',
];
public const ROUTES = [
'action' => 'mautic_printmailing_action',
'index' => 'mautic_printmailing_index',
];
public const SESSION_VARS = [
'limit' => 'plugin.printmailing.limit',
'orderBy' => 'plugin.printmailing.orderby',
'orderByDir' => 'plugin.printmailing.orderbydir',
'page' => 'plugin.printmailing.page',
'search' => 'plugin.printmailing.search',
];
public const THEMES = [
'variables' => 'LeuchtfeuerPrintmailingBundle:FormTheme\Variables',
];
public const TEMPLATES = [
'form' => 'LeuchtfeuerPrintmailingBundle:TriggerCampaign:form.html.php',
'index' => 'LeuchtfeuerPrintmailingBundle:TriggerCampaign:index',
'list' => 'LeuchtfeuerPrintmailingBundle:TriggerCampaign:list.html.php',
];
public const ACTIVE_LINK = '#mautic_printmailing_index';
public const MAUTIC_CONTENT = 'printmailing';
protected $session;
/**
* @param int $page
*
* @return Response
*/
public function indexAction($page = 1)
{
//set some permissions
$permissions = $this->getPermissions();
if (!$permissions[self::PERMISSIONS['view']]) {
return $this->accessDenied();
}
$viewParameters = [];
$viewParameters['permissions'] = $permissions;
$this->setSession();
$coreParametersHelper = $this->getCoreParametersHelper();
$viewParameters['ssoUrl'] = (new SingleSignOnUtility($coreParametersHelper, $this->container->get('mautic.helper.user')))->getSingleSignOnUrl();
$viewParameters['template'] = $this->request->isXmlHttpRequest() ? $this->request->get('tmpl', 'index') : 'index';
$viewParameters['configInvalid'] = !$this->checkConfiguration($coreParametersHelper);
$limit = $this->getLimit();
$start = $this->getStart($limit, $page);
$search = $this->getSearch();
$orderBy = $this->getOrderBy();
$orderByDir = $this->getOrderByDir();
$triggerCampaigns = $this->getTriggerCampaigns($this->getFilter($search), $start, $limit, $orderBy, $orderByDir);
$count = count($triggerCampaigns);
if ($count && $count < ($start + 1)) {
return $this->redirectToLastPage($count, $limit);
}
$this->setPage($page);
$viewParameters['searchValue'] = $search;
$viewParameters['items'] = $triggerCampaigns;
$viewParameters['searchValue'] = $search;
$viewParameters['page'] = $page;
$viewParameters['limit'] = $limit;
return $this->delegateView([
'viewParameters' => $viewParameters,
'contentTemplate' => self::TEMPLATES['list'],
'passthroughVars' => [
'activeLink' => self::ACTIVE_LINK,
'mauticContent' => self::MAUTIC_CONTENT,
'route' => $this->generateUrl(self::ROUTES['index'], ['page' => $page]),
],
]);
}
/**
* @return Response
*/
public function newAction()
{
$this->setSession();
if (!$this->get('mautic.security')->isGranted(self::PERMISSIONS['create'])) {
return $this->accessDenied();
}
$model = $this->getModel(TriggerCampaignModel::NAME);
$triggerCampaign = $model->getEntity();
$form = $model->createForm(
$triggerCampaign,
$this->get('form.factory'),
$this->generateUrl(self::ROUTES['action'], ['objectAction' => 'new'])
);
if ('POST' === $this->request->getMethod()) {
$template = self::TEMPLATES['index'];
$viewParameters = ['page' => $this->session->get(self::SESSION_VARS['page'], 1)];
$returnUrl = $this->generateUrl(self::ROUTES['index'], $viewParameters);
$valid = false;
if (!$cancelled = $this->isFormCancelled($form)) {
if ($valid = $this->isFormValid($form)) {
$model->saveEntity($triggerCampaign);
$this->addFlash('mautic.core.notice.created', [
'%name%' => $triggerCampaign->getName(),
'%menu_link%' => self::ROUTES['index'],
'%url%' => $this->generateUrl(self::ROUTES['index'], [
'objectAction' => 'edit',
'objectId' => $triggerCampaign->getId(),
]),
]);
if (!$form->get('buttons')->get('save')->isClicked()) {
//return edit view so that all the session stuff is loaded
return $this->editAction($triggerCampaign->getId(), true);
}
}
}
if ($cancelled || ($valid && $form->get('buttons')->get('save')->isClicked())) {
return $this->postActionRedirect(
[
'returnUrl' => $returnUrl,
'viewParameters' => $viewParameters,
'contentTemplate' => $template,
'passthroughVars' => [
'activeLink' => self::ACTIVE_LINK,
'mauticContent' => self::MAUTIC_CONTENT,
],
]
);
}
}
return $this->delegateView([
'viewParameters' => [
'form' => $this->setFormTheme($form, self::TEMPLATES['form'], self::THEMES['variables']),
],
'contentTemplate' => self::TEMPLATES['form'],
'passthroughVars' => [
'activeLink' => self::ACTIVE_LINK,
'mauticContent' => self::MAUTIC_CONTENT,
'route' => $this->generateUrl(self::ROUTES['action'], ['objectAction' => 'new']),
],
]);
}
/**
* @param int $objectId
* @param bool $ignorePost
* @param bool $clone
*
* @return Response
*/
public function editAction($objectId, $ignorePost = false, $clone = false)
{
$this->setSession();
$postActionVars = $this->getPostActionVars();
try {
$triggerCampaign = $this->getTriggerCampaign($objectId);
$objectAction = 'edit';
if (true === $clone) {
$triggerCampaign = clone $triggerCampaign;
$objectAction = 'clone';
}
return $this->createTriggerCampaignModifyRequest(
$triggerCampaign,
$postActionVars,
$this->generateUrl(self::ROUTES['action'], ['objectAction' => $objectAction, 'objectId' => $objectId]),
$ignorePost
);
} catch (AccessDeniedException $exception) {
return $this->accessDenied();
} catch (EntityNotFoundException $exception) {
return $this->postActionRedirect(array_merge($postActionVars, [
'flashes' => [
[
'type' => 'error',
'msg' => 'plugin.printmailing.campaign.error.notfound',
'msgVars' => ['%id%' => $objectId],
],
],
]));
}
}
/**
* @param int $objectId
* @param bool $ignorePost
*
* @return Response
*/
public function cloneAction($objectId, $ignorePost = false)
{
return $this->editAction($objectId, $ignorePost, true);
}
/**
* @param int $objectId
* @param mixed $batch
*
* @return Response
*/
public function deleteAction($objectId, $batch = false)
{
$this->setSession();
$page = $this->session->get(self::SESSION_VARS['page'], 1);
$viewParameters = ['page' => $page];
$returnUrl = $this->generateUrl(self::ROUTES['index'], $viewParameters);
$flashes = [];
$postActionVars = [
'returnUrl' => $returnUrl,
'viewParameters' => $viewParameters,
'contentTemplate' => self::TEMPLATES['index'],
'passthroughVars' => [
'activeLink' => self::ACTIVE_LINK,
'mauticContent' => self::MAUTIC_CONTENT,
],
];
if ('POST' === $this->request->getMethod()) {
if (true === $batch) {
$this->deleteMultipleCampaigns($postActionVars, $flashes);
} else {
$response = $this->deleteSingleCampaign($objectId, $postActionVars, $flashes);
if (null !== $response) {
return $response;
}
}
}
return $this->postActionRedirect(array_merge($postActionVars, [
'flashes' => $flashes,
]));
}
/**
* @return Response
*/
public function batchDeleteAction()
{
return $this->deleteAction(0, true);
}
/**
* {@inheritdoc}
*/
protected function getPermissions()
{
$security = $this->get('mautic.security');
return $security->isGranted([
self::PERMISSIONS['view'],
self::PERMISSIONS['create'],
self::PERMISSIONS['edit'],
self::PERMISSIONS['delete'],
self::PERMISSIONS['publish'],
], 'RETURN_ARRAY');
}
/**
* @return bool
*/
protected function checkConfiguration(CoreParametersHelper $coreParametersHelper)
{
if (!$coreParametersHelper->has('printmailing_rest_user') || empty($coreParametersHelper->get('printmailing_rest_user'))) {
return false;
}
if (!$coreParametersHelper->has('printmailing_rest_password') || empty($coreParametersHelper->get('printmailing_rest_password'))) {
return false;
}
return true;
}
protected function setSession()
{
$this->session = $this->get('session');
}
/**
* @return CoreParametersHelper
*/
protected function getCoreParametersHelper()
{
return $this->get('mautic.helper.core_parameters');
}
protected function getLimit()
{
return $this->session->get(self::SESSION_VARS['limit'], $this->coreParametersHelper->get('default_pagelimit'));
}
/**
* @param int $limit
* @param int $page
*
* @return float|int
*/
protected function getStart($limit, $page)
{
$start = (1 === $page) ? 0 : (($page - 1) * $limit);
if ($start < 0) {
$start = 0;
}
return $start;
}
/**
* @return string
*/
protected function getSearch()
{
$search = $this->request->get('search', $this->session->get(self::SESSION_VARS['search'], ''));
$this->setSearch($search);
return $search;
}
/**
* @param string $search
*/
protected function setSearch($search)
{
$this->session->set(self::SESSION_VARS['search'], $search);
}
/**
* @param string $search
*
* @return array
*/
protected function getFilter($search)
{
return [
'string' => $search,
'force' => [],
];
}
/**
* @return string
*/
protected function getOrderBy()
{
return $this->session->get(self::SESSION_VARS['orderBy'], TriggerCampaignRepository::ALIAS.'.name');
}
/**
* @return string
*/
protected function getOrderByDir()
{
return $this->session->get(self::SESSION_VARS['orderByDir'], 'ASC');
}
/**
* @param string $filter
* @param int $start
* @param int $limit
* @param string $orderBy
* @param string $orderByDir
*
* @return array|\Doctrine\ORM\Tools\Pagination\Paginator
*/
protected function getTriggerCampaigns($filter, $start, $limit, $orderBy, $orderByDir)
{
return $this->getModel(TriggerCampaignModel::NAME)
->getEntities([
'start' => $start,
'limit' => $limit,
'filter' => $filter,
'orderBy' => $orderBy,
'orderByDir' => $orderByDir,
]);
}
protected function redirectToLastPage(int $count, int $limit): Response
{
$lastPage = ((1 === $count) ? 1 : (ceil($count / $limit))) ?: 1;
$this->session->set(self::SESSION_VARS['search'], $lastPage);
$viewParameters = ['page' => $lastPage];
return $this->postActionRedirect(
[
'returnUrl' => $this->generateUrl(self::ROUTES['index'], $viewParameters),
'viewParameters' => $viewParameters,
'contentTemplate' => self::TEMPLATES['index'],
'passthroughVars' => [
'activeLink' => self::ACTIVE_LINK,
'mauticContent' => self::MAUTIC_CONTENT,
],
]
);
}
/**
* Set what page currently on so that we can return here after form submission/cancellation.
*/
protected function setPage(int $page): void
{
$this->session->set(self::SESSION_VARS['page'], $page);
}
/**
* Get variables for POST action.
*/
protected function getPostActionVars(): array
{
$viewParameters = ['page' => $this->session->get(self::SESSION_VARS['page'], 1)];
return [
'returnUrl' => $this->generateUrl(self::ROUTES['index'], $viewParameters),
'viewParameters' => $viewParameters,
'contentTemplate' => self::TEMPLATES['index'],
'passthroughVars' => [
'activeLink' => self::ACTIVE_LINK,
'mauticContent' => self::MAUTIC_CONTENT,
],
];
}
/**
* Return trigger campaign if exists and user has access.
*
* @throws EntityNotFoundException
* @throws AccessDeniedException
*/
private function getTriggerCampaign(int $triggerCampaignId): TriggerCampaign
{
/** @var TriggerCampaign $triggerCampaign */
$triggerCampaign = $this->getModel(TriggerCampaignModel::NAME)->getEntity($triggerCampaignId);
// Check if exists
if (!$triggerCampaign instanceof TriggerCampaign) {
throw new EntityNotFoundException(sprintf('Trigger campaign with ID %d not found.', $triggerCampaignId), 1569248601);
}
if (!$this->get('mautic.security')->hasEntityAccess(true, self::PERMISSIONS['edit'], $triggerCampaign->getCreatedBy())) {
throw new AccessDeniedException(sprintf('User has not access on segment with ID %d', $triggerCampaignId));
}
return $triggerCampaign;
}
/**
* @param bool $action
* @param string $ignorePost
*
* @return Response
*/
protected function createTriggerCampaignModifyRequest(TriggerCampaign $triggerCampaign, array $postActionVars, $action, $ignorePost)
{
/** @var TriggerCampaignModel $triggerCampaignModel */
$triggerCampaignModel = $this->getModel(TriggerCampaignModel::NAME);
if ($triggerCampaignModel->isLocked($triggerCampaign)) {
return $this->isLocked($postActionVars, $triggerCampaign, TriggerCampaignModel::NAME);
}
/** @var Form $form */
$form = $triggerCampaignModel->createForm($triggerCampaign, $this->get('form.factory'), $action);
// Check for a submitted form and process it
if (!$ignorePost && 'POST' === $this->request->getMethod()) {
if ($this->isFormCancelled($form)) {
$triggerCampaignModel->unlockEntity($triggerCampaign);
return $this->postActionRedirect($postActionVars);
}
if ($this->isFormValid($form)) {
$triggerCampaign->getChanges(false);
//form is valid so process the data
$triggerCampaignModel->saveEntity($triggerCampaign, $form->get('buttons')->get('save')->isClicked());
$this->addFlash('mautic.core.notice.updated', [
'%name%' => $triggerCampaign->getName(),
'%menu_link%' => self::ROUTES['index'],
'%url%' => $this->generateUrl(self::ROUTES['action'], [
'objectAction' => 'edit',
'objectId' => $triggerCampaign->getId(),
]),
]);
if ($form->get('buttons')->get('apply')->isClicked()) {
$contentTemplate = self::TEMPLATES['form'];
$postActionVars['contentTemplate'] = $contentTemplate;
$postActionVars['forwardController'] = false;
$postActionVars['returnUrl'] = $this->generateUrl(
self::ROUTES['action'],
[
'objectAction' => 'edit',
'objectId' => $triggerCampaign->getId(),
]
);
// Re-create the form once more with the fresh segment and action.
// The alias was empty on redirect after cloning.
$form = $triggerCampaignModel->createForm(
$triggerCampaign,
$this->get('form.factory'),
$this->generateUrl(
self::ROUTES['action'],
[
'objectAction' => 'edit',
'objectId' => $triggerCampaign->getId(),
]
)
);
$postActionVars['viewParameters'] = [
'objectAction' => 'edit',
'objectId' => $triggerCampaign->getId(),
'form' => $this->setFormTheme($form, $contentTemplate, self::THEMES['variables']),
];
return $this->postActionRedirect($postActionVars);
} elseif ($form->get('buttons')->get('save')->isClicked()) {
return $this->postActionRedirect($postActionVars);
}
}
} else {
//lock the entity
$triggerCampaignModel->lockEntity($triggerCampaign);
}
return $this->delegateView([
'viewParameters' => [
'form' => $this->setFormTheme($form, self::TEMPLATES['form'], self::THEMES['variables']),
'currentListId' => $triggerCampaign->getId(),
],
'contentTemplate' => self::TEMPLATES['form'],
'passthroughVars' => [
'activeLink' => self::ACTIVE_LINK,
'route' => $action,
'mauticContent' => self::MAUTIC_CONTENT,
],
]);
}
/**
* @param array $postActionVars
* @param array $flashes
*/
protected function deleteMultipleCampaigns($postActionVars, &$flashes)
{
/** @var TriggerCampaignModel $triggerCampaignModel */
$triggerCampaignModel = $this->getModel(TriggerCampaignModel::NAME);
$triggerCampaignIds = json_decode($this->request->query->get('ids', '{}'));
$deleteIds = [];
// Loop over the IDs to perform access checks pre-delete
foreach ($triggerCampaignIds as $triggerCampaignId) {
$triggerCampaign = $triggerCampaignModel->getEntity($triggerCampaignId);
if (null === $triggerCampaign) {
$flashes[] = [
'type' => 'error',
'msg' => 'plugin.printmailing.campaign.error.notfound',
'msgVars' => ['%id%' => $triggerCampaignId],
];
} elseif (!$this->get('mautic.security')->hasEntityAccess(true, self::PERMISSIONS['delete'], $triggerCampaign->getCreatedBy())) {
$flashes[] = $this->accessDenied(true);
} elseif ($triggerCampaignModel->isLocked($triggerCampaign)) {
$flashes[] = $this->isLocked($postActionVars, $triggerCampaign, TriggerCampaignModel::NAME, true);
} else {
$deleteIds[] = $triggerCampaignId;
}
}
// Delete everything we are able to
if (!empty($deleteIds)) {
$triggerCampaigns = $triggerCampaignModel->deleteEntities($deleteIds);
$flashes[] = [
'type' => 'notice',
'msg' => 'plugin.printmailing.campaign.notice.batch_deleted',
'msgVars' => [
'%count%' => count($triggerCampaigns),
],
];
}
}
/**
* @param int $objectId
* @param array $postActionVars
* @param array $flashes
*
* @return Response
*/
protected function deleteSingleCampaign($objectId, $postActionVars, &$flashes)
{
/** @var TriggerCampaignModel $triggerCampaignModel */
$triggerCampaignModel = $this->getModel(TriggerCampaignModel::NAME);
$triggerCampaign = $triggerCampaignModel->getEntity($objectId);
if (null === $triggerCampaign) {
$flashes[] = [
'type' => 'error',
'msg' => 'plugin.printmailing.campaign.error.notfound',
'msgVars' => ['%id%' => $objectId],
];
} elseif (!$this->get('mautic.security')->hasEntityAccess(true, self::PERMISSIONS['delete'], $triggerCampaign->getCreatedBy())) {
return $this->accessDenied();
} elseif ($triggerCampaignModel->isLocked($triggerCampaign)) {
return $this->isLocked($postActionVars, $triggerCampaign, TriggerCampaignModel::NAME);
}
$triggerCampaignModel->deleteEntity($triggerCampaign);
$flashes[] = [
'type' => 'notice',
'msg' => 'mautic.core.notice.deleted',
'msgVars' => [
'%name%' => $triggerCampaign->getName(),
'%id%' => $objectId,
],
];
return null;
}
}