Spaces:
No application file
No application file
| 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\EmailBundle\Model\EmailModel; | |
| use Mautic\LeadBundle\Entity\DoNotContact; | |
| use Mautic\LeadBundle\Entity\UtmTag; | |
| use Mautic\LeadBundle\Event\LeadTimelineEvent; | |
| use Mautic\LeadBundle\Form\Type\FilterPropertiesType; | |
| use Mautic\LeadBundle\Helper\FormFieldHelper; | |
| use Mautic\LeadBundle\LeadEvents; | |
| 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\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; | |
| use Symfony\Component\HttpFoundation\Session\Session; | |
| class AjaxController extends CommonAjaxController | |
| { | |
| use AjaxLookupControllerTrait; | |
| 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): JsonResponse | |
| { | |
| $filter = InputHelper::clean($request->query->get('filter')); | |
| $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->get('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 | |
| { | |
| $dataArray = ['success' => 1]; | |
| $filter = InputHelper::clean($request->query->get('filter')); | |
| $fieldAlias = InputHelper::alphanum($request->query->get('field'), false, null, ['_']); | |
| /** @var FieldModel $fieldModel */ | |
| $fieldModel = $this->getModel('lead.field'); | |
| /** @var LeadModel $contactModel */ | |
| $contactModel = $this->getModel('lead.lead'); | |
| /** @var CompanyModel $companyModel */ | |
| $companyModel = $this->getModel('lead.company'); | |
| if (empty($fieldAlias)) { | |
| $dataArray['error'] = 'Alias cannot be empty'; | |
| $dataArray['success'] = 0; | |
| return $this->sendJsonResponse($dataArray); | |
| } | |
| if ('owner_id' === $fieldAlias) { | |
| $results = $contactModel->getLookupResults('user', $filter); | |
| foreach ($results as $r) { | |
| $name = $r['firstName'].' '.$r['lastName']; | |
| $dataArray[] = [ | |
| 'value' => $name, | |
| 'id' => $r['id'], | |
| ]; | |
| } | |
| return $this->sendJsonResponse($dataArray); | |
| } | |
| $field = $fieldModel->getEntityByAlias($fieldAlias); | |
| $isBehavior = empty($field); | |
| if ($isBehavior) { | |
| return $this->sendJsonResponse($dataArray); | |
| } | |
| // Selet field types that make sense to provide typeahead for. | |
| $isLookup = in_array($field->getType(), ['lookup']); | |
| $shouldLookup = in_array($field->getAlias(), ['city', 'company', 'title']); | |
| if (!$isLookup && !$shouldLookup) { | |
| return $this->sendJsonResponse($dataArray); | |
| } | |
| if ($isLookup && !empty($field->getProperties()['list'])) { | |
| foreach ($field->getProperties()['list'] as $predefinedValue) { | |
| $dataArray[] = ['value' => $predefinedValue]; | |
| } | |
| } | |
| if ('company' === $field->getObject()) { | |
| $results = $companyModel->getLookupResults('companyfield', [$fieldAlias, $filter]); | |
| foreach ($results as $r) { | |
| $dataArray[] = ['value' => $r['label']]; | |
| } | |
| } elseif ('lead' === $field->getObject()) { | |
| $results = $fieldModel->getLookupResults($fieldAlias, $filter); | |
| foreach ($results as $r) { | |
| $dataArray[] = ['value' => $r[$fieldAlias]]; | |
| } | |
| } | |
| return $this->sendJsonResponse($dataArray); | |
| } | |
| 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): 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(); | |
| /** @var IntegrationHelper $integrationHelper */ | |
| $integrationHelper = $this->factory->getHelper('integration'); | |
| $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): 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; | |
| /** @var IntegrationHelper $helper */ | |
| $helper = $this->factory->getHelper('integration'); | |
| $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); | |
| } | |
| /** | |
| * Updates the timeline events and gets returns updated HTML. | |
| */ | |
| protected function updateTimelineAction(Request $request, Session $session): JsonResponse | |
| { | |
| $dataArray = ['success' => 0]; | |
| $includeEvents = InputHelper::clean($request->request->get('includeEvents') ?? []); | |
| $excludeEvents = InputHelper::clean($request->request->get('excludeEvents') ?? []); | |
| $search = InputHelper::clean($request->request->get('search')); | |
| $leadId = (int) $request->request->get('leadId'); | |
| if (!empty($leadId)) { | |
| // find the lead | |
| $model = $this->getModel('lead.lead'); | |
| $lead = $model->getEntity($leadId); | |
| if (null !== $lead) { | |
| $filter = [ | |
| 'search' => $search, | |
| 'includeEvents' => $includeEvents, | |
| 'excludeEvents' => $excludeEvents, | |
| ]; | |
| $session->set('mautic.lead.'.$leadId.'.timeline.filters', $filter); | |
| // Trigger the TIMELINE_ON_GENERATE event to fetch the timeline events from subscribed bundles | |
| $dispatcher = $this->dispatcher; | |
| $event = new LeadTimelineEvent($lead, $filter); | |
| $dispatcher->dispatch($event, LeadEvents::TIMELINE_ON_GENERATE); | |
| $events = $event->getEvents(); | |
| $eventTypes = $event->getEventTypes(); | |
| $timeline = $this->renderView( | |
| 'MauticLeadBundle:Lead:history.html.php', | |
| [ | |
| 'events' => $events, | |
| 'eventTypes' => $eventTypes, | |
| 'eventFilters' => $filter, | |
| 'lead' => $lead, | |
| ] | |
| ); | |
| $dataArray['success'] = 1; | |
| $dataArray['timeline'] = $timeline; | |
| $dataArray['historyCount'] = count($events); | |
| } | |
| } | |
| 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): 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'])) { | |
| $leadModel = $this->getModel('lead'); | |
| /** @var DoNotContactModel $doNotContact */ | |
| $doNotContact = $this->getModel('lead.dnc'); | |
| $lead = $leadModel->getEntity($leadId); | |
| if (null !== $lead && null !== $channel) { | |
| if ('remove' === $action) { | |
| $doNotContact->addDncForContact($leadId, $channel, DoNotContact::MANUAL, 'user'); | |
| } elseif ('add' === $action) { | |
| $doNotContact->removeDncForContact($leadId, $channel); | |
| } | |
| $dataArray['success'] = 1; | |
| } | |
| } | |
| return $this->sendJsonResponse($dataArray); | |
| } | |
| public function toggleLeadCampaignAction(Request $request, MembershipManager $membershipManager): 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); | |
| } | |
| /** @var LeadModel $leadModel */ | |
| $leadModel = $this->getModel('lead'); | |
| /** @var CampaignModel $campaignModel */ | |
| $campaignModel = $this->getModel('campaign'); | |
| $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): 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'])) { | |
| $leadModel = $this->getModel('lead'); | |
| $companyModel = $this->getModel('lead.company'); | |
| $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): JsonResponse | |
| { | |
| $dataArray = ['success' => 0]; | |
| $dncId = $request->request->get('id'); | |
| $channel = $request->request->get('channel', 'email'); | |
| if (!empty($dncId)) { | |
| /** @var LeadModel $model */ | |
| /** @var DoNotContactModel $doNotContact */ | |
| $doNotContact = $this->getModel('lead.dnc'); | |
| /** @var DoNotContactModel $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); | |
| } else { | |
| $emailModel = $this->getModel('email'); | |
| \assert($emailModel instanceof EmailModel); | |
| $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) | |
| { | |
| $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); | |
| } | |
| /** @var LeadModel $model */ | |
| $model = $this->getModel('lead.lead'); | |
| $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): JsonResponse | |
| { | |
| $data = ['success' => 1, 'body' => '', 'subject' => '']; | |
| $emailId = $request->query->get('template'); | |
| /** @var EmailModel $model */ | |
| $model = $this->getModel('email'); | |
| /** @var \Mautic\EmailBundle\Entity\Email $email */ | |
| $email = $model->getEntity($emailId); | |
| if (null !== $email | |
| && $this->security->hasEntityAccess( | |
| 'email:emails:viewown', | |
| 'email:emails:viewother', | |
| $email->getCreatedBy() | |
| ) | |
| ) { | |
| $mailer = $this->factory->getMailer(); | |
| $mailer->setEmail($email, true, [], [], true); | |
| $data['body'] = $mailer->getBody(); | |
| $data['subject'] = $mailer->getSubject(); | |
| } | |
| return $this->sendJsonResponse($data); | |
| } | |
| public function updateLeadTagsAction(Request $request): JsonResponse | |
| { | |
| /** @var LeadModel $leadModel */ | |
| $leadModel = $this->getModel('lead'); | |
| $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): JsonResponse | |
| { | |
| $tags = $request->request->get('tags'); | |
| $tags = json_decode($tags, true); | |
| if (is_array($tags)) { | |
| $leadModel = $this->getModel('lead'); | |
| \assert($leadModel instanceof LeadModel); | |
| $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): 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; | |
| } | |
| } | |
| $leadModel = $this->getModel('lead'); | |
| \assert($leadModel instanceof LeadModel); | |
| 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): JsonResponse | |
| { | |
| $dataArray = ['success' => 0]; | |
| $order = InputHelper::clean($request->request->get('field')); | |
| $page = (int) $request->get('page'); | |
| $limit = (int) $request->get('limit'); | |
| if (!empty($order)) { | |
| /** @var FieldModel $model */ | |
| $model = $this->getModel('lead.field'); | |
| $startAt = ($page > 1) ? ($page * $limit) + 1 : 1; | |
| $model->reorderFieldsByList($order, $startAt); | |
| $dataArray['success'] = 1; | |
| } | |
| return $this->sendJsonResponse($dataArray); | |
| } | |
| public function updateLeadFieldValuesAction(Request $request): 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) { | |
| $leadModel = $this->getModel('lead'); | |
| \assert($leadModel instanceof LeadModel); | |
| $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): JsonResponse | |
| { | |
| $dataArray['success'] = 1; | |
| $companyId = InputHelper::clean($request->request->get('companyId')); | |
| $leadId = InputHelper::clean($request->request->get('leadId')); | |
| $leadModel = $this->getModel('lead'); | |
| \assert($leadModel instanceof LeadModel); | |
| $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($entityid, $ids); | |
| $data = [ | |
| 'success' => 1, | |
| 'stats' => $data, | |
| ]; | |
| return new JsonResponse($data); | |
| } | |
| /** | |
| * @throws \Exception | |
| */ | |
| public function getLeadCountAction(Request $request): JsonResponse | |
| { | |
| $id = (int) InputHelper::clean($request->get('id')); | |
| /** @var ListModel $model */ | |
| $model = $this->getModel('lead.list'); | |
| $leadListExists = $model->leadListExists($id); | |
| if (!$leadListExists) { | |
| return new JsonResponse($this->prepareJsonResponse(0), Response::HTTP_NOT_FOUND); | |
| } | |
| $leadCounts = $model->getSegmentContactCount([$id]); | |
| $leadCount = $leadCounts[$id]; | |
| return new JsonResponse($this->prepareJsonResponse($leadCount)); | |
| } | |
| public function getSegmentDependencyTreeAction(Request $request, SegmentDependencyTreeFactory $segmentDependencyTreeFactory): JsonResponse | |
| { | |
| /** @var ListModel $model */ | |
| $model = $this->getModel('lead.list'); | |
| $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): array | |
| { | |
| return [ | |
| 'html' => $this->translator->trans( | |
| 'mautic.lead.list.viewleads_count', | |
| ['%count%' => $leadCount] | |
| ), | |
| '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([]); | |
| } | |
| } | |