846 lines
33 KiB
PHP
Executable File
846 lines
33 KiB
PHP
Executable File
<?php
|
|
|
|
namespace Mautic\LeadBundle\Controller;
|
|
|
|
use Mautic\CampaignBundle\Membership\MembershipManager;
|
|
use Mautic\CampaignBundle\Model\CampaignModel;
|
|
use Mautic\CoreBundle\Controller\AjaxController as CommonAjaxController;
|
|
use Mautic\CoreBundle\Controller\AjaxLookupControllerTrait;
|
|
use Mautic\CoreBundle\Helper\InputHelper;
|
|
use Mautic\CoreBundle\Helper\Tree\JsPlumbFormatter;
|
|
use Mautic\CoreBundle\Security\Permissions\CorePermissions;
|
|
use Mautic\CoreBundle\Service\FlashBag;
|
|
use Mautic\EmailBundle\Helper\MailHelper;
|
|
use Mautic\EmailBundle\Model\EmailModel;
|
|
use Mautic\LeadBundle\Entity\DoNotContact;
|
|
use Mautic\LeadBundle\Entity\LeadField;
|
|
use Mautic\LeadBundle\Entity\UtmTag;
|
|
use Mautic\LeadBundle\Event\ListTypeaheadEvent;
|
|
use Mautic\LeadBundle\Form\Type\FieldType;
|
|
use Mautic\LeadBundle\Form\Type\FilterPropertiesType;
|
|
use Mautic\LeadBundle\Helper\FormFieldHelper;
|
|
use Mautic\LeadBundle\Model\CompanyModel;
|
|
use Mautic\LeadBundle\Model\DoNotContact as DoNotContactModel;
|
|
use Mautic\LeadBundle\Model\FieldModel;
|
|
use Mautic\LeadBundle\Model\LeadModel;
|
|
use Mautic\LeadBundle\Model\ListModel;
|
|
use Mautic\LeadBundle\Provider\FormAdjustmentsProviderInterface;
|
|
use Mautic\LeadBundle\Segment\SegmentFilterIconTrait;
|
|
use Mautic\LeadBundle\Segment\Stat\SegmentCampaignShare;
|
|
use Mautic\LeadBundle\Services\ContactColumnsDictionary;
|
|
use Mautic\LeadBundle\Services\SegmentDependencyTreeFactory;
|
|
use Mautic\PluginBundle\Helper\IntegrationHelper;
|
|
use Symfony\Component\Form\FormFactoryInterface;
|
|
use Symfony\Component\HttpFoundation\JsonResponse;
|
|
use Symfony\Component\HttpFoundation\Request;
|
|
use Symfony\Component\HttpFoundation\Response;
|
|
|
|
class AjaxController extends CommonAjaxController
|
|
{
|
|
use AjaxLookupControllerTrait;
|
|
use SegmentFilterIconTrait;
|
|
|
|
public function userListAction(Request $request): JsonResponse
|
|
{
|
|
$filter = InputHelper::clean($request->query->get('filter'));
|
|
$leadModel = $this->getModel('lead.lead');
|
|
\assert($leadModel instanceof LeadModel);
|
|
$results = $leadModel->getLookupResults('user', $filter);
|
|
$dataArray = [];
|
|
foreach ($results as $r) {
|
|
$name = $r['firstName'].' '.$r['lastName'];
|
|
$dataArray[] = [
|
|
'label' => $name,
|
|
'value' => $r['id'],
|
|
];
|
|
}
|
|
|
|
return $this->sendJsonResponse($dataArray);
|
|
}
|
|
|
|
public function contactListAction(Request $request, LeadModel $model, CorePermissions $corePermissions): JsonResponse
|
|
{
|
|
$filter['string'] = InputHelper::clean($request->query->get('filter'));
|
|
|
|
// Do not show other's contacts if do not have permission.
|
|
if (!$corePermissions->isGranted(['lead:leads:viewother'], 'MATCH_ONE')) {
|
|
$filter['force'] = ' '.$this->translator->trans('mautic.core.searchcommand.ismine');
|
|
}
|
|
|
|
$results = $model->getLookupResults('contact', $filter);
|
|
|
|
$results['success'] = 1;
|
|
|
|
return $this->sendJsonResponse($results);
|
|
}
|
|
|
|
public function getLeadIdsByFieldValueAction(Request $request, LeadModel $leadModel): JsonResponse
|
|
{
|
|
$field = InputHelper::clean($request->query->get('field'));
|
|
$value = InputHelper::clean($request->query->all()['value'] ?? '');
|
|
$ignore = (int) $request->query->get('ignore');
|
|
$dataArray = ['items' => []];
|
|
|
|
if ($field && $value) {
|
|
$repo = $leadModel->getRepository();
|
|
$leads = $repo->getLeadsByFieldValue($field, $value, $ignore);
|
|
$dataArray['existsMessage'] = $this->translator->trans('mautic.lead.exists.by.field').': ';
|
|
|
|
foreach ($leads as $lead) {
|
|
$fields = $repo->getFieldValues($lead->getId());
|
|
$lead->setFields($fields);
|
|
$name = $lead->getName();
|
|
|
|
if (!$name) {
|
|
$name = $lead->getEmail();
|
|
}
|
|
|
|
if (!$name) {
|
|
$name = $this->translator->trans('mautic.lead.lead.anonymous');
|
|
}
|
|
|
|
$leadLink = $this->generateUrl('mautic_contact_action', ['objectAction' => 'view', 'objectId' => $lead->getId()]);
|
|
|
|
$dataArray['items'][] = [
|
|
'name' => $name,
|
|
'id' => $lead->getId(),
|
|
'link' => $leadLink,
|
|
];
|
|
}
|
|
}
|
|
|
|
return $this->sendJsonResponse($dataArray);
|
|
}
|
|
|
|
public function fieldListAction(Request $request): JsonResponse
|
|
{
|
|
$filter = InputHelper::clean($request->query->get('filter'));
|
|
$fieldAlias = InputHelper::alphanum($request->query->get('field'), false, null, ['_']);
|
|
$event = new ListTypeaheadEvent($fieldAlias, $filter);
|
|
$this->dispatcher->dispatch($event);
|
|
|
|
return $this->sendJsonResponse($event->getDataArray());
|
|
}
|
|
|
|
public function loadSegmentFilterFormAction(
|
|
Request $request,
|
|
FormFactoryInterface $formFactory,
|
|
FormAdjustmentsProviderInterface $formAdjustmentsProvider,
|
|
ListModel $listModel,
|
|
): JsonResponse {
|
|
$fieldAlias = InputHelper::clean($request->request->get('fieldAlias'));
|
|
$fieldObject = InputHelper::clean($request->request->get('fieldObject'));
|
|
$operator = InputHelper::clean($request->request->get('operator'));
|
|
$search = InputHelper::clean($request->request->get('search'));
|
|
$filterNum = (int) $request->request->get('filterNum');
|
|
|
|
$form = $formFactory->createNamed('RENAME', FilterPropertiesType::class);
|
|
|
|
if ($fieldAlias && $operator) {
|
|
$formAdjustmentsProvider->adjustForm(
|
|
$form,
|
|
$fieldAlias,
|
|
$fieldObject,
|
|
$operator,
|
|
$listModel->getChoiceFields($search)[$fieldObject][$fieldAlias]
|
|
);
|
|
}
|
|
|
|
$formHtml = $this->renderView(
|
|
'@MauticLead/List/filterpropform.html.twig',
|
|
[
|
|
// 'form' => $this->setFormTheme($form, '@MauticLead/List/filterpropform.html.twig', []),
|
|
'form' => $form->createView(),
|
|
]
|
|
);
|
|
|
|
$formHtml = str_replace('id="RENAME', "id=\"leadlist_filters_{$filterNum}_properties", $formHtml);
|
|
$formHtml = str_replace('name="RENAME', "name=\"leadlist[filters][{$filterNum}][properties]", $formHtml);
|
|
|
|
return $this->sendJsonResponse(
|
|
[
|
|
'viewParameters' => [
|
|
'form' => $formHtml,
|
|
],
|
|
]
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Updates the cache and gets returns updated HTML.
|
|
*/
|
|
public function updateSocialProfileAction(Request $request, IntegrationHelper $integrationHelper): JsonResponse
|
|
{
|
|
$dataArray = ['success' => 0];
|
|
$network = InputHelper::clean($request->request->get('network'));
|
|
$leadId = InputHelper::clean($request->request->get('lead'));
|
|
|
|
if (!empty($leadId)) {
|
|
// find the lead
|
|
$model = $this->getModel('lead.lead');
|
|
$lead = $model->getEntity($leadId);
|
|
|
|
if (null !== $lead && $this->security->hasEntityAccess('lead:leads:editown', 'lead:leads:editown', $lead->getPermissionUser())) {
|
|
$leadFields = $lead->getFields();
|
|
$socialProfiles = $integrationHelper->getUserProfiles($lead, $leadFields, true, $network);
|
|
$socialProfileUrls = $integrationHelper->getSocialProfileUrlRegex(false);
|
|
$integrations = [];
|
|
$socialCount = count($socialProfiles);
|
|
if (empty($network) || empty($socialCount)) {
|
|
$dataArray['completeProfile'] = $this->renderView(
|
|
'@MauticLead/Social/index.html.twig',
|
|
[
|
|
'socialProfiles' => $socialProfiles,
|
|
'lead' => $lead,
|
|
'socialProfileUrls' => $socialProfileUrls,
|
|
]
|
|
);
|
|
$dataArray['socialCount'] = $socialCount;
|
|
} else {
|
|
foreach ($socialProfiles as $name => $details) {
|
|
if ($integrationObject = $integrationHelper->getIntegrationObject($name)) {
|
|
if ($template = $integrationObject->getSocialProfileTemplate()) {
|
|
$integrations[$name]['newContent'] = $this->renderView(
|
|
$template,
|
|
[
|
|
'lead' => $lead,
|
|
'details' => $details,
|
|
'integrationName' => $name,
|
|
'socialProfileUrls' => $socialProfileUrls,
|
|
]
|
|
);
|
|
}
|
|
}
|
|
}
|
|
$dataArray['profiles'] = $integrations;
|
|
}
|
|
|
|
$dataArray['success'] = 1;
|
|
}
|
|
}
|
|
|
|
return $this->sendJsonResponse($dataArray);
|
|
}
|
|
|
|
/**
|
|
* Clears the cache for a network.
|
|
*/
|
|
public function clearSocialProfileAction(Request $request, IntegrationHelper $helper): JsonResponse
|
|
{
|
|
$dataArray = ['success' => 0];
|
|
$network = InputHelper::clean($request->request->get('network'));
|
|
$leadId = InputHelper::clean($request->request->get('lead'));
|
|
|
|
if (!empty($leadId)) {
|
|
// find the lead
|
|
$model = $this->getModel('lead.lead');
|
|
$lead = $model->getEntity($leadId);
|
|
|
|
if (null !== $lead && $this->security->hasEntityAccess('lead:leads:editown', 'lead:leads:editown', $lead->getPermissionUser())) {
|
|
$dataArray['success'] = 1;
|
|
$socialProfiles = $helper->clearIntegrationCache($lead, $network);
|
|
$socialCount = count($socialProfiles);
|
|
|
|
if (empty($socialCount)) {
|
|
$dataArray['completeProfile'] = $this->renderView(
|
|
'@MauticLead/Social/index.html.twig',
|
|
[
|
|
'socialProfiles' => $socialProfiles,
|
|
'lead' => $lead,
|
|
'socialProfileUrls' => $helper->getSocialProfileUrlRegex(false),
|
|
]
|
|
);
|
|
}
|
|
|
|
$dataArray['socialCount'] = $socialCount;
|
|
}
|
|
}
|
|
|
|
return $this->sendJsonResponse($dataArray);
|
|
}
|
|
|
|
protected function toggleLeadListAction(Request $request): JsonResponse
|
|
{
|
|
$dataArray = ['success' => 0];
|
|
$leadId = (int) $request->request->get('leadId');
|
|
$listId = (int) $request->request->get('listId');
|
|
$action = InputHelper::clean($request->request->get('listAction'));
|
|
|
|
if (!empty($leadId) && !empty($listId) && in_array($action, ['remove', 'add'])) {
|
|
$leadModel = $this->getModel('lead');
|
|
$listModel = $this->getModel('lead.list');
|
|
|
|
$lead = $leadModel->getEntity($leadId);
|
|
$list = $listModel->getEntity($listId);
|
|
|
|
if (null !== $lead && null !== $list) {
|
|
$class = 'add' == $action ? 'addToLists' : 'removeFromLists';
|
|
$leadModel->$class($lead, $list);
|
|
$dataArray['success'] = 1;
|
|
}
|
|
}
|
|
|
|
return $this->sendJsonResponse($dataArray);
|
|
}
|
|
|
|
public function togglePreferredLeadChannelAction(Request $request, LeadModel $leadModel, DoNotContactModel $doNotContact): JsonResponse
|
|
{
|
|
$dataArray = ['success' => 0];
|
|
$leadId = (int) $request->request->get('leadId');
|
|
$channel = InputHelper::clean($request->request->get('channel'));
|
|
$action = InputHelper::clean($request->request->get('channelAction'));
|
|
|
|
if (!empty($leadId) && !empty($channel) && in_array($action, ['remove', 'add'])) {
|
|
$lead = $leadModel->getEntity($leadId);
|
|
|
|
if (null !== $lead) {
|
|
if ('remove' === $action) {
|
|
$doNotContact->addDncForContact($leadId, $channel, DoNotContact::MANUAL, 'user');
|
|
} elseif ('add' === $action) {
|
|
$doNotContact->removeDncForContact($leadId, $channel);
|
|
$this->addFlashMessage('mautic.lead.event.donotcontact_channel_contactable', ['%channel%' => $channel], FlashBag::LEVEL_SUCCESS);
|
|
$dataArray['flashes'] = $this->getFlashContent();
|
|
}
|
|
$dataArray['success'] = 1;
|
|
}
|
|
}
|
|
|
|
return $this->sendJsonResponse($dataArray);
|
|
}
|
|
|
|
public function toggleLeadCampaignAction(Request $request, MembershipManager $membershipManager, LeadModel $leadModel, CampaignModel $campaignModel): JsonResponse
|
|
{
|
|
$dataArray = ['success' => 0];
|
|
$leadId = (int) $request->request->get('leadId');
|
|
$campaignId = (int) $request->request->get('campaignId');
|
|
$action = InputHelper::clean($request->request->get('campaignAction'));
|
|
|
|
if (empty($leadId) || empty($campaignId) || !in_array($action, ['remove', 'add'])) {
|
|
return $this->sendJsonResponse($dataArray);
|
|
}
|
|
$lead = $leadModel->getEntity($leadId);
|
|
$campaign = $campaignModel->getEntity($campaignId);
|
|
|
|
if (null === $lead || null === $campaign) {
|
|
return $this->sendJsonResponse($dataArray);
|
|
}
|
|
|
|
if ('add' === $action) {
|
|
$membershipManager->addContact($lead, $campaign);
|
|
}
|
|
|
|
if ('remove' === $action) {
|
|
$membershipManager->removeContact($lead, $campaign);
|
|
}
|
|
|
|
$dataArray['success'] = 1;
|
|
|
|
return $this->sendJsonResponse($dataArray);
|
|
}
|
|
|
|
public function toggleCompanyLeadAction(Request $request, LeadModel $leadModel, CompanyModel $companyModel): JsonResponse
|
|
{
|
|
$dataArray = ['success' => 0];
|
|
$leadId = (int) $request->request->get('leadId');
|
|
$companyId = (int) $request->request->get('companyId');
|
|
$action = InputHelper::clean($request->request->get('companyAction'));
|
|
|
|
if (!empty($leadId) && !empty($companyId) && in_array($action, ['remove', 'add'])) {
|
|
$lead = $leadModel->getEntity($leadId);
|
|
$company = $companyModel->getEntity($companyId);
|
|
|
|
if (null !== $lead && null !== $company) {
|
|
$class = 'add' == $action ? 'addLeadToCompany' : 'removeLeadFromCompany';
|
|
$companyModel->$class($company, $lead);
|
|
$dataArray['success'] = 1;
|
|
}
|
|
}
|
|
|
|
return $this->sendJsonResponse($dataArray);
|
|
}
|
|
|
|
public function getImportProgressAction(Request $request): JsonResponse
|
|
{
|
|
$dataArray = ['success' => 1];
|
|
|
|
if ($this->security->isGranted('lead:leads:create')) {
|
|
$session = $request->getSession();
|
|
$dataArray['progress'] = $session->get('mautic.lead.import.progress', [0, 0]);
|
|
$dataArray['percent'] = ($dataArray['progress'][1]) ? ceil(($dataArray['progress'][0] / $dataArray['progress'][1]) * 100) : 100;
|
|
}
|
|
|
|
return $this->sendJsonResponse($dataArray);
|
|
}
|
|
|
|
public function removeBounceStatusAction(Request $request, DoNotContactModel $doNotContact, EmailModel $emailModel): JsonResponse
|
|
{
|
|
$dataArray = ['success' => 0];
|
|
$dncId = $request->request->get('id');
|
|
$channel = $request->request->get('channel', 'email');
|
|
|
|
if (!empty($dncId)) {
|
|
/** @var DoNotContact $dnc */
|
|
$dnc = $this->doctrine->getManager()->getRepository(DoNotContact::class)->findOneBy(
|
|
[
|
|
'id' => $dncId,
|
|
]
|
|
);
|
|
|
|
$lead = $dnc->getLead();
|
|
if ($lead) {
|
|
// Use lead model to trigger listeners
|
|
$doNotContact->removeDncForContact($lead->getId(), $channel);
|
|
$this->addFlashMessage('mautic.lead.event.donotcontact_channel_contactable', ['%channel%' => $channel], FlashBag::LEVEL_SUCCESS);
|
|
$dataArray['flashes'] = $this->getFlashContent();
|
|
} else {
|
|
$emailModel->getRepository()->deleteDoNotEmailEntry($dncId);
|
|
}
|
|
|
|
$dataArray['success'] = 1;
|
|
}
|
|
|
|
return $this->sendJsonResponse($dataArray);
|
|
}
|
|
|
|
/**
|
|
* Get the rows for new leads.
|
|
*
|
|
* @return array|JsonResponse|\Symfony\Component\HttpFoundation\RedirectResponse
|
|
*/
|
|
public function getNewLeadsAction(Request $request, ContactColumnsDictionary $contactColumnsDictionary, LeadModel $model)
|
|
{
|
|
$dataArray = ['success' => 0];
|
|
$maxId = $request->get('maxId');
|
|
|
|
if (!empty($maxId)) {
|
|
// set some permissions
|
|
$permissions = $this->security->isGranted(
|
|
[
|
|
'lead:leads:viewown',
|
|
'lead:leads:viewother',
|
|
'lead:leads:create',
|
|
'lead:leads:editown',
|
|
'lead:leads:editother',
|
|
'lead:leads:deleteown',
|
|
'lead:leads:deleteother',
|
|
],
|
|
'RETURN_ARRAY'
|
|
);
|
|
|
|
if (!$permissions['lead:leads:viewown'] && !$permissions['lead:leads:viewother']) {
|
|
return $this->accessDenied(true);
|
|
}
|
|
|
|
$session = $request->getSession();
|
|
$search = $session->get('mautic.lead.filter', '');
|
|
$filter = ['string' => $search, 'force' => []];
|
|
$translator = $this->translator;
|
|
$anonymous = $translator->trans('mautic.lead.lead.searchcommand.isanonymous');
|
|
$mine = $translator->trans('mautic.core.searchcommand.ismine');
|
|
$indexMode = $session->get('mautic.lead.indexmode', 'list');
|
|
|
|
$session->set('mautic.lead.indexmode', $indexMode);
|
|
|
|
// (strpos($search, "$isCommand:$anonymous") === false && strpos($search, "$listCommand:") === false)) ||
|
|
if ('list' != $indexMode) {
|
|
// remove anonymous leads unless requested to prevent clutter
|
|
$filter['force'][] = "!$anonymous";
|
|
}
|
|
|
|
if (!$permissions['lead:leads:viewother']) {
|
|
$filter['force'][] = $mine;
|
|
}
|
|
|
|
$filter['force'][] = [
|
|
'column' => 'l.id',
|
|
'expr' => 'gt',
|
|
'value' => $maxId,
|
|
];
|
|
|
|
$results = $model->getEntities(
|
|
[
|
|
'filter' => $filter,
|
|
'withTotalCount' => true,
|
|
]
|
|
);
|
|
$count = $results['count'];
|
|
|
|
if (!empty($count)) {
|
|
// Get the max ID of the latest lead added
|
|
$maxLeadId = $model->getRepository()->getMaxLeadId();
|
|
|
|
// We need the EmailRepository to check if a lead is flagged as do not contact
|
|
/** @var \Mautic\EmailBundle\Entity\EmailRepository $emailRepo */
|
|
$emailRepo = $this->getModel('email')->getRepository();
|
|
$indexMode = $request->get('view', $session->get('mautic.lead.indexmode', 'list'));
|
|
$template = ('list' == $indexMode) ? 'list_rows' : 'grid_cards';
|
|
$dataArray['leads'] = $this->render(
|
|
"@MauticLead/Lead/{$template}.html.twig",
|
|
[
|
|
'items' => $results['results'],
|
|
'noContactList' => $emailRepo->getDoNotEmailList(array_keys($results['results'])),
|
|
'permissions' => $permissions,
|
|
'security' => $this->security,
|
|
'highlight' => true,
|
|
'currentList' => null,
|
|
'columns' => $contactColumnsDictionary->getColumns(),
|
|
]
|
|
)->getContent();
|
|
$dataArray['indexMode'] = $indexMode;
|
|
$dataArray['maxId'] = $maxLeadId;
|
|
$dataArray['success'] = 1;
|
|
}
|
|
}
|
|
|
|
return $this->sendJsonResponse($dataArray);
|
|
}
|
|
|
|
public function getEmailTemplateAction(Request $request, EmailModel $model, MailHelper $mailHelper): JsonResponse
|
|
{
|
|
$data = ['success' => 1, 'body' => '', 'subject' => ''];
|
|
$emailId = $request->query->get('template');
|
|
|
|
/** @var \Mautic\EmailBundle\Entity\Email $email */
|
|
$email = $model->getEntity($emailId);
|
|
|
|
if (null !== $email
|
|
&& $this->security->hasEntityAccess(
|
|
'email:emails:viewown',
|
|
'email:emails:viewother',
|
|
$email->getCreatedBy()
|
|
)
|
|
) {
|
|
$mailHelper->setEmail($email, true, [], true);
|
|
|
|
$data['body'] = $mailHelper->getBody();
|
|
$data['subject'] = $mailHelper->getSubject();
|
|
}
|
|
|
|
return $this->sendJsonResponse($data);
|
|
}
|
|
|
|
public function updateLeadTagsAction(Request $request, LeadModel $leadModel): JsonResponse
|
|
{
|
|
$post = $request->request->all()['lead_tags'] ?? [];
|
|
$lead = $leadModel->getEntity((int) $post['id']);
|
|
$updatedTags = (!empty($post['tags']) && is_array($post['tags'])) ? $post['tags'] : [];
|
|
$data = ['success' => 0];
|
|
|
|
if (null !== $lead && $this->security->hasEntityAccess('lead:leads:editown', 'lead:leads:editother', $lead->getPermissionUser())) {
|
|
$leadModel->setTags($lead, $updatedTags, true);
|
|
|
|
/** @var \Doctrine\ORM\PersistentCollection $leadTags */
|
|
$leadTags = $lead->getTags();
|
|
$leadTagKeys = $leadTags->getKeys();
|
|
|
|
// Get an updated list of tags
|
|
$tags = $leadModel->getTagRepository()->getSimpleList(null, [], 'tag');
|
|
$tagOptions = '';
|
|
|
|
foreach ($tags as $tag) {
|
|
$selected = (in_array($tag['label'], $leadTagKeys)) ? ' selected="selected"' : '';
|
|
$tagOptions .= '<option'.$selected.' value="'.$tag['value'].'">'.$tag['label'].'</option>';
|
|
}
|
|
|
|
$data['success'] = 1;
|
|
$data['tags'] = $tagOptions;
|
|
}
|
|
|
|
return $this->sendJsonResponse($data);
|
|
}
|
|
|
|
public function addLeadTagsAction(Request $request, LeadModel $leadModel): JsonResponse
|
|
{
|
|
$tags = $request->request->get('tags');
|
|
$tags = json_decode($tags, true);
|
|
|
|
if (is_array($tags)) {
|
|
$newTags = [];
|
|
|
|
foreach ($tags as $tag) {
|
|
if (!is_numeric($tag)) {
|
|
$newTags[] = $leadModel->getTagRepository()->getTagByNameOrCreateNewOne($tag);
|
|
}
|
|
}
|
|
|
|
if (!empty($newTags)) {
|
|
$leadModel->getTagRepository()->saveEntities($newTags);
|
|
}
|
|
|
|
// Get an updated list of tags
|
|
$allTags = $leadModel->getTagRepository()->getSimpleList(null, [], 'tag');
|
|
$tagOptions = '';
|
|
|
|
foreach ($allTags as $tag) {
|
|
$selected = (in_array($tag['value'], $tags) || in_array($tag['label'], $tags)) ? ' selected="selected"' : '';
|
|
$tagOptions .= '<option'.$selected.' value="'.$tag['value'].'">'.$tag['label'].'</option>';
|
|
}
|
|
|
|
$data = [
|
|
'success' => 1,
|
|
'tags' => $tagOptions,
|
|
];
|
|
} else {
|
|
$data = ['success' => 0];
|
|
}
|
|
|
|
return $this->sendJsonResponse($data);
|
|
}
|
|
|
|
public function addLeadUtmTagsAction(Request $request, LeadModel $leadModel): JsonResponse
|
|
{
|
|
$utmTags = $request->request->get('utmtags');
|
|
$utmTags = json_decode($utmTags, true);
|
|
|
|
if (is_array($utmTags)) {
|
|
$newUtmTags = [];
|
|
foreach ($utmTags as $utmTag) {
|
|
if (!is_numeric($utmTag)) {
|
|
// New tag
|
|
$utmTagEntity = new UtmTag();
|
|
$utmTagEntity->setUtmTag(InputHelper::clean($utmTag));
|
|
$newUtmTags[] = $utmTagEntity;
|
|
}
|
|
}
|
|
|
|
if (!empty($newUtmTags)) {
|
|
$leadModel->getUtmTagRepository()->saveEntities($newUtmTags);
|
|
}
|
|
|
|
// Get an updated list of tags
|
|
$allUtmTags = $leadModel->getUtmTagRepository()->getSimpleList(null, [], 'utmtag');
|
|
$utmTagOptions = '';
|
|
|
|
foreach ($allUtmTags as $utmTag) {
|
|
$selected = (in_array($utmTag['value'], $utmTags) || in_array($utmTag['label'], $utmTags)) ? ' selected="selected"' : '';
|
|
$utmTagOptions .= '<option'.$selected.' value="'.$utmTag['value'].'">'.$utmTag['label'].'</option>';
|
|
}
|
|
|
|
$data = [
|
|
'success' => 1,
|
|
'tags' => $utmTagOptions,
|
|
];
|
|
} else {
|
|
$data = ['success' => 0];
|
|
}
|
|
|
|
return $this->sendJsonResponse($data);
|
|
}
|
|
|
|
public function reorderAction(Request $request, FieldModel $model): JsonResponse
|
|
{
|
|
$dataArray = ['success' => 0];
|
|
$order = InputHelper::clean($request->request->get('field'));
|
|
$page = (int) $request->get('page');
|
|
$limit = (int) $request->get('limit');
|
|
|
|
if (!empty($order)) {
|
|
$startAt = ($page > 1) ? ($page * $limit) + 1 : 1;
|
|
$model->reorderFieldsByList($order, $startAt);
|
|
$dataArray['success'] = 1;
|
|
}
|
|
|
|
return $this->sendJsonResponse($dataArray);
|
|
}
|
|
|
|
public function updateLeadFieldValuesAction(Request $request, LeadModel $leadModel): JsonResponse
|
|
{
|
|
$alias = InputHelper::clean($request->request->get('alias'));
|
|
$operator = InputHelper::clean($request->request->get('operator'));
|
|
$changed = InputHelper::clean($request->request->get('changed'));
|
|
$dataArray = ['success' => 0, 'options' => null, 'optionsAttr' => [], 'operators' => null, 'disabled' => false];
|
|
$leadField = $this->getModel('lead.field')->getRepository()->findOneBy(['alias' => $alias]);
|
|
|
|
if ($leadField) {
|
|
$options = null;
|
|
$leadFieldType = $leadField->getType();
|
|
|
|
$properties = $leadField->getProperties();
|
|
if (!empty($properties['list'])) {
|
|
// Lookup/Select options
|
|
$options = FormFieldHelper::parseList($properties['list']);
|
|
} elseif (!empty($properties) && 'boolean' == $leadFieldType) {
|
|
// Boolean options
|
|
$options = [
|
|
0 => $properties['no'],
|
|
1 => $properties['yes'],
|
|
];
|
|
} else {
|
|
switch ($leadFieldType) {
|
|
case 'country':
|
|
$options = FormFieldHelper::getCountryChoices();
|
|
break;
|
|
case 'region':
|
|
$options = FormFieldHelper::getRegionChoices();
|
|
break;
|
|
case 'timezone':
|
|
$options = FormFieldHelper::getTimezonesChoices();
|
|
break;
|
|
case 'locale':
|
|
$options = array_flip(FormFieldHelper::getLocaleChoices());
|
|
break;
|
|
case 'date':
|
|
case 'datetime':
|
|
if ('date' == $operator) {
|
|
$fieldHelper = new FormFieldHelper();
|
|
$fieldHelper->setTranslator($this->translator);
|
|
$options = $fieldHelper->getDateChoices();
|
|
$options = array_merge(
|
|
[
|
|
'custom' => $this->translator->trans('mautic.campaign.event.timed.choice.custom'),
|
|
],
|
|
$options
|
|
);
|
|
|
|
$dataArray['optionsAttr']['custom'] = [
|
|
'data-custom' => 1,
|
|
];
|
|
}
|
|
break;
|
|
default:
|
|
$options = (!empty($properties)) ? $properties : [];
|
|
}
|
|
}
|
|
|
|
$dataArray['fieldType'] = $leadFieldType;
|
|
$dataArray['options'] = $options;
|
|
|
|
if ('field' === $changed) {
|
|
$dataArray['operators'] = $leadModel->getOperatorsForFieldType($leadFieldType, ['date']);
|
|
foreach ($dataArray['operators'] as $value => $label) {
|
|
$dataArray['operators'][$value] = $this->translator->trans($label);
|
|
}
|
|
$operator = array_key_first($dataArray['operators']);
|
|
}
|
|
|
|
$disabled = false;
|
|
switch ($operator) {
|
|
case 'empty':
|
|
case '!empty':
|
|
$disabled = true;
|
|
$dataArray['options'] = null;
|
|
break;
|
|
case 'regexp':
|
|
case '!regexp':
|
|
$dataArray['options'] = null;
|
|
break;
|
|
}
|
|
$dataArray['disabled'] = $disabled;
|
|
}
|
|
|
|
$dataArray['success'] = 1;
|
|
|
|
return $this->sendJsonResponse($dataArray);
|
|
}
|
|
|
|
public function setAsPrimaryCompanyAction(Request $request, LeadModel $leadModel): JsonResponse
|
|
{
|
|
$dataArray['success'] = 1;
|
|
$companyId = InputHelper::clean($request->request->get('companyId'));
|
|
$leadId = InputHelper::clean($request->request->get('leadId'));
|
|
|
|
$primaryCompany = $leadModel->setPrimaryCompany($companyId, $leadId);
|
|
|
|
$dataArray = array_merge($dataArray, $primaryCompany);
|
|
|
|
return $this->sendJsonResponse($dataArray);
|
|
}
|
|
|
|
public function getCampaignShareStatsAction(Request $request, SegmentCampaignShare $segmentCampaignShareService): JsonResponse
|
|
{
|
|
$ids = $request->query->all()['ids'] ?? [];
|
|
$entityid = $request->query->get('entityId');
|
|
|
|
$data = $segmentCampaignShareService->getCampaignsSegmentShare((int) $entityid, $ids);
|
|
|
|
$data = [
|
|
'success' => 1,
|
|
'stats' => $data,
|
|
];
|
|
|
|
return new JsonResponse($data);
|
|
}
|
|
|
|
/**
|
|
* @throws \Exception
|
|
*/
|
|
public function getLeadCountAction(Request $request, ListModel $model): JsonResponse
|
|
{
|
|
$id = (int) InputHelper::clean($request->get('id'));
|
|
|
|
$leadList = $model->getEntity($id);
|
|
if (!$leadList) {
|
|
return new JsonResponse($this->prepareJsonResponse(0, false), Response::HTTP_NOT_FOUND);
|
|
}
|
|
|
|
$leadCounts = $model->getSegmentContactCount([$id]);
|
|
$leadCount = $leadCounts[$id];
|
|
|
|
return new JsonResponse(
|
|
$this->prepareJsonResponse(
|
|
$leadCount,
|
|
$leadList->needsRebuild(),
|
|
)
|
|
);
|
|
}
|
|
|
|
public function getSegmentDependencyTreeAction(Request $request, SegmentDependencyTreeFactory $segmentDependencyTreeFactory, ListModel $model): JsonResponse
|
|
{
|
|
$id = (int) $request->get('id');
|
|
$segment = $model->getEntity($id);
|
|
|
|
if (!$segment) {
|
|
return new JsonResponse(['message' => "Segment {$id} could not be found."], Response::HTTP_NOT_FOUND);
|
|
}
|
|
|
|
$parentNode = $segmentDependencyTreeFactory->buildTree($segment);
|
|
$formatter = new JsPlumbFormatter();
|
|
|
|
return new JsonResponse($formatter->format($parentNode));
|
|
}
|
|
|
|
/**
|
|
* @return array<string, mixed>
|
|
*/
|
|
private function prepareJsonResponse(int $leadCount, bool $needsRebuild): array
|
|
{
|
|
return [
|
|
'html' => $this->translator->trans(
|
|
$needsRebuild ? 'mautic.lead.list.building' : 'mautic.lead.list.viewleads_count',
|
|
['%count%' => $leadCount]
|
|
),
|
|
'className' => sprintf('label %s col-count', $needsRebuild ? 'label-info' : 'label-gray'),
|
|
'leadCount' => $leadCount,
|
|
];
|
|
}
|
|
|
|
public function removeTagFromLeadAction(Request $request, LeadModel $leadModel): JsonResponse
|
|
{
|
|
$leadId = (int) $request->request->get('leadId');
|
|
$tagId = (int) $request->request->get('tagId');
|
|
|
|
if (!empty($leadId) && !empty($tagId)) {
|
|
$leadModel->removeTagFromLead($leadId, $tagId);
|
|
}
|
|
|
|
return $this->sendJsonResponse([]);
|
|
}
|
|
|
|
public function updateLeadFieldOrderChoiceListAction(Request $request): Response
|
|
{
|
|
$object = InputHelper::clean($request->request->get('object'));
|
|
$group = InputHelper::clean($request->request->get('group'));
|
|
$field = new LeadField();
|
|
$field->setObject($object);
|
|
$field->setGroup($group);
|
|
$form = $this->createForm(FieldType::class, $field);
|
|
|
|
return $this->render(
|
|
'@MauticLead/Field/_field_order.html.twig',
|
|
[
|
|
'form' => $form->createView(),
|
|
]
|
|
);
|
|
}
|
|
}
|