/** * @param MauticEvents\GlobalSearchEvent $event */ public function onGlobalSearch(MauticEvents\GlobalSearchEvent $event) { if ($this->security->isGranted('campaign:campaigns:view')) { $str = $event->getSearchString(); if (empty($str)) { return; } $campaigns = $this->campaignModel->getEntities(['limit' => 5, 'filter' => $str]); if (count($campaigns) > 0) { $campaignResults = []; foreach ($campaigns as $campaign) { $campaignResults[] = $this->templating->renderResponse('MauticCampaignBundle:SubscribedEvents\\Search:global.html.php', ['campaign' => $campaign])->getContent(); } if (count($campaigns) > 5) { $campaignResults[] = $this->templating->renderResponse('MauticCampaignBundle:SubscribedEvents\\Search:global.html.php', ['showMore' => true, 'searchString' => $str, 'remaining' => count($campaigns) - 5])->getContent(); } $campaignResults['count'] = count($campaigns); $event->addResults('mautic.campaign.campaigns', $campaignResults); } } }
/** * Triggers an event. * * @param $type * @param null $eventDetails * @param null $channel * @param null $channelId * * @return array|bool */ public function triggerEvent($type, $eventDetails = null, $channel = null, $channelId = null) { static $leadCampaigns = [], $eventList = [], $availableEventSettings = [], $leadsEvents = [], $examinedEvents = []; $this->logger->debug('CAMPAIGN: Campaign triggered for event type ' . $type . '(' . $channel . ' / ' . $channelId . ')'); // Skip the anonymous check to force actions to fire for subsequent triggers $systemTriggered = defined('MAUTIC_CAMPAIGN_SYSTEM_TRIGGERED'); if (!$systemTriggered) { defined('MAUTIC_CAMPAIGN_NOT_SYSTEM_TRIGGERED') or define('MAUTIC_CAMPAIGN_NOT_SYSTEM_TRIGGERED', 1); } //only trigger events for anonymous users (to prevent populating full of user/company data) if (!$systemTriggered && !$this->security->isAnonymous()) { $this->logger->debug('CAMPAIGN: contact not anonymous; abort'); return false; } //get the current lead $lead = $this->leadModel->getCurrentLead(); $leadId = $lead->getId(); $this->logger->debug('CAMPAIGN: Current Lead ID# ' . $leadId); //get the lead's campaigns so we have when the lead was added if (empty($leadCampaigns[$leadId])) { $leadCampaigns[$leadId] = $this->campaignModel->getLeadCampaigns($lead, true); } if (empty($leadCampaigns[$leadId])) { $this->logger->debug('CAMPAIGN: no campaigns found so abort'); return false; } //get the list of events that match the triggering event and is in the campaigns this lead belongs to /** @var \Mautic\CampaignBundle\Entity\EventRepository $eventRepo */ $eventRepo = $this->getRepository(); if (empty($eventList[$leadId][$type])) { $eventList[$leadId][$type] = $eventRepo->getPublishedByType($type, $leadCampaigns[$leadId], $lead->getId()); } $events = $eventList[$leadId][$type]; //get event settings from the bundles if (empty($availableEventSettings)) { $availableEventSettings = $this->campaignModel->getEvents(); } //make sure there are events before continuing if (!count($availableEventSettings) || empty($events)) { $this->logger->debug('CAMPAIGN: no events found so abort'); return false; } //get campaign list $campaigns = $this->campaignModel->getEntities(['force' => ['filter' => [['column' => 'c.id', 'expr' => 'in', 'value' => array_keys($events)]]], 'ignore_paginator' => true]); //get a list of events that has already been executed for this lead if (empty($leadsEvents[$leadId])) { $leadsEvents[$leadId] = $eventRepo->getLeadTriggeredEvents($leadId); } if (!isset($examinedEvents[$leadId])) { $examinedEvents[$leadId] = []; } $this->triggeredResponses = []; foreach ($events as $campaignId => $campaignEvents) { if (empty($campaigns[$campaignId])) { $this->logger->debug('CAMPAIGN: Campaign entity for ID# ' . $campaignId . ' not found'); continue; } foreach ($campaignEvents as $k => $event) { //has this event already been examined via a parent's children? //all events of this triggering type has to be queried since this particular event could be anywhere in the dripflow if (in_array($event['id'], $examinedEvents[$leadId])) { $this->logger->debug('CAMPAIGN: ' . ucfirst($event['eventType']) . ' ID# ' . $event['id'] . ' already processed this round'); continue; } $examinedEvents[$leadId][] = $event['id']; //check to see if this has been fired sequentially if (!empty($event['parent'])) { if (!isset($leadsEvents[$leadId][$event['parent']['id']])) { //this event has a parent that has not been triggered for this lead so break out $this->logger->debug('CAMPAIGN: parent (ID# ' . $event['parent']['id'] . ') for ID# ' . $event['id'] . ' has not been triggered yet or was triggered with this batch'); continue; } $parentLog = $leadsEvents[$leadId][$event['parent']['id']]['log'][0]; if ($parentLog['isScheduled']) { //this event has a parent that is scheduled and thus not triggered $this->logger->debug('CAMPAIGN: parent (ID# ' . $event['parent']['id'] . ') for ID# ' . $event['id'] . ' has not been triggered yet because it\'s scheduled'); continue; } else { $parentTriggeredDate = $parentLog['dateTriggered']; } } else { $parentTriggeredDate = new \DateTime(); } if (isset($availableEventSettings[$event['eventType']][$type])) { $decisionEventSettings = $availableEventSettings[$event['eventType']][$type]; } else { // Not found maybe it's no longer available? $this->logger->debug('CAMPAIGN: ' . $type . ' does not exist. (#' . $event['id'] . ')'); continue; } //check the callback function for the event to make sure it even applies based on its settings if (!($response = $this->invokeEventCallback($event, $decisionEventSettings, $lead, $eventDetails, $systemTriggered))) { $this->logger->debug('CAMPAIGN: ' . ucfirst($event['eventType']) . ' ID# ' . $event['id'] . ' callback check failed with a response of ' . var_export($response, true)); continue; } if (!empty($event['children'])) { $this->logger->debug('CAMPAIGN: ' . ucfirst($event['eventType']) . ' ID# ' . $event['id'] . ' has children'); $childrenTriggered = false; foreach ($event['children'] as $child) { if (isset($leadsEvents[$leadId][$child['id']])) { //this child event has already been fired for this lead so move on to the next event $this->logger->debug('CAMPAIGN: ' . ucfirst($child['eventType']) . ' ID# ' . $child['id'] . ' already triggered'); continue; } elseif ($child['eventType'] == 'decision') { //hit a triggering type event so move on $this->logger->debug('CAMPAIGN: ID# ' . $child['id'] . ' is a decision'); continue; } elseif ($child['decisionPath'] == 'no') { // non-action paths should not be processed by this because the contact already took action in order to get here $childrenTriggered = true; } else { $this->logger->debug('CAMPAIGN: ' . ucfirst($child['eventType']) . ' ID# ' . $child['id'] . ' is being processed'); } //store in case a child was pulled with events $examinedEvents[$leadId][] = $child['id']; if ($this->executeEvent($child, $campaigns[$campaignId], $lead, $availableEventSettings, false, $parentTriggeredDate)) { $childrenTriggered = true; } } if ($childrenTriggered) { $this->logger->debug('CAMPAIGN: Decision ID# ' . $event['id'] . ' successfully executed and logged.'); //a child of this event was triggered or scheduled so make not of the triggering event in the log $log = $this->getLogEntity($event['id'], $campaigns[$campaignId], $lead, null, $systemTriggered); $log->setChannel($channel)->setChannelId($channelId); $this->getRepository()->saveEntity($log); } else { $this->logger->debug('CAMPAIGN: Decision not logged'); } } else { $this->logger->debug('CAMPAIGN: No children for this event.'); } } } if ($lead->getChanges()) { $this->leadModel->saveEntity($lead, false); } if ($this->dispatcher->hasListeners(CampaignEvents::ON_EVENT_DECISION_TRIGGER)) { $this->dispatcher->dispatch(CampaignEvents::ON_EVENT_DECISION_TRIGGER, new CampaignDecisionEvent($lead, $type, $eventDetails, $events, $availableEventSettings)); } $actionResponses = $this->triggeredResponses; $this->triggeredResponses = false; return $actionResponses; }