Initial commit: CloudOps infrastructure platform
This commit is contained in:
@@ -0,0 +1,190 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\CampaignBundle\Tests\Command;
|
||||
|
||||
use Doctrine\DBAL\Connection;
|
||||
use Mautic\CampaignBundle\Entity\Campaign;
|
||||
use Mautic\CampaignBundle\Entity\Event;
|
||||
use Mautic\CampaignBundle\Entity\Lead as CampaignLead;
|
||||
use Mautic\CampaignBundle\Entity\LeadEventLog;
|
||||
use Mautic\CoreBundle\Test\MauticMysqlTestCase;
|
||||
use Mautic\InstallBundle\InstallFixtures\ORM\LeadFieldData;
|
||||
use Mautic\LeadBundle\DataFixtures\ORM\LoadLeadData;
|
||||
use Mautic\LeadBundle\Entity\Lead;
|
||||
use Mautic\LeadBundle\Entity\LeadList;
|
||||
use Mautic\LeadBundle\Entity\ListLead;
|
||||
|
||||
class AbstractCampaignCommand extends MauticMysqlTestCase
|
||||
{
|
||||
public const SEND_EMAIL_SECONDS = 3;
|
||||
|
||||
public const CONDITION_SECONDS = 6;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $defaultClientServer = [];
|
||||
|
||||
/**
|
||||
* @var Connection
|
||||
*/
|
||||
protected $db;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $prefix;
|
||||
|
||||
/**
|
||||
* @var \DateTimeInterface
|
||||
*/
|
||||
protected $eventDate;
|
||||
|
||||
/**
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function setUp(): void
|
||||
{
|
||||
// Everything needs to happen anonymously
|
||||
$this->defaultClientServer = $this->clientServer;
|
||||
$this->clientServer = [];
|
||||
|
||||
parent::setUp();
|
||||
|
||||
$this->db = $this->em->getConnection();
|
||||
$this->prefix = static::getContainer()->getParameter('mautic.db_table_prefix');
|
||||
|
||||
// Populate contacts
|
||||
$this->installDatabaseFixtures([LeadFieldData::class, LoadLeadData::class]);
|
||||
|
||||
// Campaigns are so complex that we are going to load a SQL file rather than build with entities
|
||||
$sql = file_get_contents(__DIR__.'/campaign_schema.sql');
|
||||
|
||||
// Update table prefix
|
||||
$sql = str_replace('#__', static::getContainer()->getParameter('mautic.db_table_prefix'), $sql);
|
||||
|
||||
// Schedule event
|
||||
date_default_timezone_set('UTC');
|
||||
$this->eventDate = new \DateTime();
|
||||
$this->eventDate->modify('+'.self::SEND_EMAIL_SECONDS.' seconds');
|
||||
$sql = str_replace('{SEND_EMAIL_1_TIMESTAMP}', $this->eventDate->format('Y-m-d H:i:s'), $sql);
|
||||
|
||||
$this->eventDate->modify('+'.self::CONDITION_SECONDS.' seconds');
|
||||
$sql = str_replace('{CONDITION_TIMESTAMP}', $this->eventDate->format('Y-m-d H:i:s'), $sql);
|
||||
|
||||
$this->em->getConnection()->executeStatement($sql);
|
||||
}
|
||||
|
||||
public function beforeTearDown(): void
|
||||
{
|
||||
$this->clientServer = $this->defaultClientServer;
|
||||
}
|
||||
|
||||
protected function beforeBeginTransaction(): void
|
||||
{
|
||||
$this->resetAutoincrement([
|
||||
'leads',
|
||||
'emails',
|
||||
'lead_tags',
|
||||
'campaigns',
|
||||
'campaign_events',
|
||||
'lead_lists',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
protected function getCampaignEventLogs(array $ids)
|
||||
{
|
||||
$logs = $this->db->createQueryBuilder()
|
||||
->select('l.email, l.country, event.name, event.event_type, event.type, log.*')
|
||||
->from($this->prefix.'campaign_lead_event_log', 'log')
|
||||
->join('log', $this->prefix.'campaign_events', 'event', 'event.id = log.event_id')
|
||||
->join('log', $this->prefix.'leads', 'l', 'l.id = log.lead_id')
|
||||
->where('log.campaign_id = 1')
|
||||
->andWhere('log.event_id IN ('.implode(',', $ids).')')
|
||||
->executeQuery()
|
||||
->fetchAllAssociative();
|
||||
|
||||
$byEvent = [];
|
||||
foreach ($ids as $id) {
|
||||
$byEvent[$id] = [];
|
||||
}
|
||||
|
||||
foreach ($logs as $log) {
|
||||
$byEvent[$log['event_id']][] = $log;
|
||||
}
|
||||
|
||||
return $byEvent;
|
||||
}
|
||||
|
||||
protected function createLead(string $leadName): Lead
|
||||
{
|
||||
$lead = new Lead();
|
||||
$lead->setFirstname($leadName);
|
||||
$this->em->persist($lead);
|
||||
|
||||
return $lead;
|
||||
}
|
||||
|
||||
protected function createCampaign(string $campaignName): Campaign
|
||||
{
|
||||
$campaign = new Campaign();
|
||||
$campaign->setName($campaignName);
|
||||
$campaign->setIsPublished(true);
|
||||
$this->em->persist($campaign);
|
||||
|
||||
return $campaign;
|
||||
}
|
||||
|
||||
protected function createCampaignLead(Campaign $campaign, Lead $lead, bool $manuallyRemoved = false): CampaignLead
|
||||
{
|
||||
$campaignLead = new CampaignLead();
|
||||
$campaignLead->setCampaign($campaign);
|
||||
$campaignLead->setLead($lead);
|
||||
$campaignLead->setDateAdded(new \DateTime());
|
||||
$campaignLead->setManuallyRemoved($manuallyRemoved);
|
||||
$this->em->persist($campaignLead);
|
||||
|
||||
return $campaignLead;
|
||||
}
|
||||
|
||||
protected function createSegmentMember(LeadList $segment, Lead $lead): ListLead
|
||||
{
|
||||
$segmentMember = new ListLead();
|
||||
$segmentMember->setLead($lead);
|
||||
$segmentMember->setList($segment);
|
||||
$segmentMember->setDateAdded(new \DateTime());
|
||||
$this->em->persist($segmentMember);
|
||||
|
||||
return $segmentMember;
|
||||
}
|
||||
|
||||
protected function createEvent(string $name, Campaign $campaign, string $type, string $eventType, ?array $property = null): Event
|
||||
{
|
||||
$event = new Event();
|
||||
$event->setName($name);
|
||||
$event->setCampaign($campaign);
|
||||
$event->setType($type);
|
||||
$event->setEventType($eventType);
|
||||
$event->setTriggerInterval(1);
|
||||
$event->setProperties($property);
|
||||
$event->setTriggerMode('immediate');
|
||||
$this->em->persist($event);
|
||||
|
||||
return $event;
|
||||
}
|
||||
|
||||
protected function createEventLog(Lead $lead, Event $event, Campaign $campaign): LeadEventLog
|
||||
{
|
||||
$leadEventLog = new LeadEventLog();
|
||||
$leadEventLog->setLead($lead);
|
||||
$leadEventLog->setEvent($event);
|
||||
$leadEventLog->setCampaign($campaign);
|
||||
$leadEventLog->setRotation(0);
|
||||
$this->em->persist($leadEventLog);
|
||||
|
||||
return $leadEventLog;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\CampaignBundle\Tests\Command\Api;
|
||||
|
||||
use Mautic\CampaignBundle\Entity\Campaign;
|
||||
use Mautic\CampaignBundle\Entity\Event;
|
||||
use Mautic\CampaignBundle\Entity\Lead as CampaignMember;
|
||||
use Mautic\CoreBundle\Test\MauticMysqlTestCase;
|
||||
use Mautic\LeadBundle\Entity\Lead;
|
||||
use PHPUnit\Framework\Assert;
|
||||
|
||||
final class EventLogApiControllerTest extends MauticMysqlTestCase
|
||||
{
|
||||
public function testBatchEditEventsPut(): void
|
||||
{
|
||||
$contact1 = new Lead();
|
||||
$contact1->setEmail('johana@doe.nohama');
|
||||
|
||||
$contact2 = new Lead();
|
||||
$contact2->setEmail('johana@doe.mohana');
|
||||
|
||||
$contact3 = new Lead();
|
||||
$contact3->setEmail('johana@doe.monana');
|
||||
|
||||
$campaign = new Campaign();
|
||||
$campaign->setName('Test Campaign');
|
||||
|
||||
$campaignMember1 = new CampaignMember();
|
||||
$campaignMember1->setLead($contact1);
|
||||
$campaignMember1->setCampaign($campaign);
|
||||
$campaignMember1->setManuallyAdded(true);
|
||||
$campaignMember1->setDateAdded(new \DateTime());
|
||||
|
||||
$campaignMember2 = new CampaignMember();
|
||||
$campaignMember2->setLead($contact2);
|
||||
$campaignMember2->setCampaign($campaign);
|
||||
$campaignMember2->setManuallyAdded(true);
|
||||
$campaignMember2->setDateAdded(new \DateTime());
|
||||
|
||||
$event1 = new Event();
|
||||
$event1->setCampaign($campaign);
|
||||
$event1->setType('lead.changepoints');
|
||||
$event1->setEventType('action');
|
||||
$event1->setName('Test Event 1');
|
||||
|
||||
$event2 = new Event();
|
||||
$event2->setCampaign($campaign);
|
||||
$event2->setType('lead.changepoints');
|
||||
$event2->setEventType('action');
|
||||
$event2->setName('Test Event 2');
|
||||
|
||||
$event3 = new Event();
|
||||
$event3->setCampaign($campaign);
|
||||
$event3->setType('asset.download');
|
||||
$event3->setEventType('decision');
|
||||
$event3->setName('Test Event 3');
|
||||
|
||||
$campaign->addEvent(0, $event1);
|
||||
$campaign->addEvent(1, $event2);
|
||||
$campaign->addEvent(1, $event3);
|
||||
|
||||
$this->em->persist($contact1);
|
||||
$this->em->persist($contact2);
|
||||
$this->em->persist($contact3);
|
||||
$this->em->persist($event1);
|
||||
$this->em->persist($event2);
|
||||
$this->em->persist($event3);
|
||||
$this->em->persist($campaign);
|
||||
$this->em->persist($campaignMember1);
|
||||
$this->em->persist($campaignMember2);
|
||||
$this->em->flush();
|
||||
$this->em->detach($contact1);
|
||||
$this->em->detach($contact2);
|
||||
$this->em->detach($contact3);
|
||||
$this->em->detach($event1);
|
||||
$this->em->detach($event2);
|
||||
$this->em->detach($event3);
|
||||
$this->em->detach($campaign);
|
||||
$this->em->detach($campaignMember1);
|
||||
$this->em->detach($campaignMember2);
|
||||
|
||||
$payload = [
|
||||
// This will fail because it already has dateTriggered.
|
||||
[
|
||||
'contactId' => $contact1->getId(),
|
||||
'eventId' => $event1->getId(),
|
||||
'dateTriggered' => '2016-01-10 00:00:00',
|
||||
],
|
||||
[
|
||||
'contactId' => $contact2->getId(),
|
||||
'eventId' => $event1->getId(),
|
||||
'triggerDate' => '2017-01-10 00:00:00',
|
||||
],
|
||||
[
|
||||
'contactId' => $contact1->getId(),
|
||||
'eventId' => $event2->getId(),
|
||||
'triggerDate' => '2016-01-11 00:00:00',
|
||||
],
|
||||
[
|
||||
'contactId' => $contact2->getId(),
|
||||
'eventId' => $event2->getId(),
|
||||
'triggerDate' => '2016-01-11 00:00:00',
|
||||
],
|
||||
// This will fail because this contact isn't a campaign member.
|
||||
[
|
||||
'contactId' => $contact3->getId(),
|
||||
'eventId' => $event2->getId(),
|
||||
'triggerDate' => '2017-01-10 00:00:00',
|
||||
],
|
||||
// This will fail because decision cannot be scheduled.
|
||||
[
|
||||
'contactId' => $contact1->getId(),
|
||||
'eventId' => $event3->getId(),
|
||||
'triggerDate' => '2016-01-11 00:00:00',
|
||||
],
|
||||
];
|
||||
|
||||
$this->client->request('PUT', '/api/campaigns/events/batch/edit', $payload);
|
||||
$clientResponse = $this->client->getResponse();
|
||||
$response = json_decode($clientResponse->getContent(), true);
|
||||
|
||||
Assert::assertCount(1, $response['events'][$event1->getId()]['contactLog']);
|
||||
Assert::assertCount(2, $response['events'][$event2->getId()]['contactLog']);
|
||||
Assert::assertCount(0, $response['events'][$event3->getId()]['contactLog']);
|
||||
|
||||
$errorMessages = array_map(
|
||||
fn (array $error) => $error['message'],
|
||||
$response['errors']
|
||||
);
|
||||
|
||||
Assert::assertContains("The event {$event1->getId()} in the campaign {$campaign->getId()} has already been executed at 2016-01-10T00:00:00+00:00 for the contact {$contact2->getId()}.", $errorMessages);
|
||||
Assert::assertContains("The contact {$contact3->getId()} is not in the campaign {$campaign->getId()}.", $errorMessages);
|
||||
Assert::assertContains("A decision type event cannot be scheduled. Event: {$event3->getId()}, campaign: {$campaign->getId()}, contact: {$contact1->getId()}.", $errorMessages);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\CampaignBundle\Tests\Command;
|
||||
|
||||
use Mautic\CampaignBundle\Command\CampaignDeleteEventLogsCommand;
|
||||
use Mautic\CampaignBundle\Entity\Campaign;
|
||||
use Mautic\CampaignBundle\Entity\Event;
|
||||
use Mautic\CampaignBundle\Entity\LeadEventLog;
|
||||
use Mautic\CoreBundle\Test\MauticMysqlTestCase;
|
||||
use Mautic\LeadBundle\Entity\Lead;
|
||||
use PHPUnit\Framework\Assert;
|
||||
use Symfony\Bundle\FrameworkBundle\Console\Application;
|
||||
use Symfony\Component\Console\Tester\ApplicationTester;
|
||||
|
||||
class CampaignDeleteEventLogsCommandFunctionalTest extends MauticMysqlTestCase
|
||||
{
|
||||
public function testWithEventIds(): void
|
||||
{
|
||||
$exitCode = $this->createDataAndRunCommand(false);
|
||||
Assert::assertSame(0, $exitCode);
|
||||
|
||||
$campaign = $this->em->getRepository(Campaign::class)->findAll();
|
||||
Assert::assertCount(1, $campaign);
|
||||
|
||||
$eventLogs = $this->em->getRepository(LeadEventLog::class)->findAll();
|
||||
Assert::assertCount(0, $eventLogs);
|
||||
}
|
||||
|
||||
public function testWithCampaignId(): void
|
||||
{
|
||||
$exitCode = $this->createDataAndRunCommand(true);
|
||||
|
||||
Assert::assertSame(0, $exitCode);
|
||||
|
||||
$campaign = $this->em->getRepository(Campaign::class)->findAll();
|
||||
Assert::assertCount(0, $campaign);
|
||||
|
||||
$eventLogs = $this->em->getRepository(LeadEventLog::class)->findAll();
|
||||
Assert::assertCount(0, $eventLogs);
|
||||
}
|
||||
|
||||
private function createApplicationTester(): ApplicationTester
|
||||
{
|
||||
$application = new Application(self::$kernel);
|
||||
$application->setAutoExit(false);
|
||||
|
||||
return new ApplicationTester($application);
|
||||
}
|
||||
|
||||
private function createDataAndRunCommand(bool $usingCampaign): int
|
||||
{
|
||||
$applicationTester = $this->createApplicationTester();
|
||||
$lead = $this->createLead();
|
||||
$campaign = $this->createCampaign();
|
||||
$event1 = $this->createEvent('Event 1', $campaign);
|
||||
$event2 = $this->createEvent('Event 2', $campaign);
|
||||
$this->createEventLog($lead, $event1);
|
||||
$this->createEventLog($lead, $event2);
|
||||
|
||||
$commandData = ['command' => CampaignDeleteEventLogsCommand::COMMAND_NAME];
|
||||
if ($usingCampaign) {
|
||||
$commandData['--campaign-id'] = $campaign->getId();
|
||||
} else {
|
||||
$commandData['campaign_event_ids'] = [$event1->getId(), $event2->getId()];
|
||||
}
|
||||
|
||||
$exitCode = $applicationTester->run($commandData);
|
||||
|
||||
return $exitCode;
|
||||
}
|
||||
|
||||
private function createLead(): Lead
|
||||
{
|
||||
$lead = new Lead();
|
||||
$lead->setFirstname('Test');
|
||||
$this->em->persist($lead);
|
||||
$this->em->flush();
|
||||
|
||||
return $lead;
|
||||
}
|
||||
|
||||
private function createCampaign(): Campaign
|
||||
{
|
||||
$campaign = new Campaign();
|
||||
$campaign->setName('My campaign');
|
||||
$this->em->persist($campaign);
|
||||
$this->em->flush();
|
||||
|
||||
return $campaign;
|
||||
}
|
||||
|
||||
private function createEvent(string $name, Campaign $campaign): Event
|
||||
{
|
||||
$event = new Event();
|
||||
$event->setName($name);
|
||||
$event->setCampaign($campaign);
|
||||
$event->setType('email.send');
|
||||
$event->setEventType('action');
|
||||
$this->em->persist($event);
|
||||
$this->em->flush();
|
||||
|
||||
return $event;
|
||||
}
|
||||
|
||||
private function createEventLog(Lead $lead, Event $event): LeadEventLog
|
||||
{
|
||||
$leadEventLog = new LeadEventLog();
|
||||
$leadEventLog->setLead($lead);
|
||||
$leadEventLog->setEvent($event);
|
||||
$this->em->persist($leadEventLog);
|
||||
$this->em->flush();
|
||||
|
||||
return $leadEventLog;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\CampaignBundle\Tests\Command;
|
||||
|
||||
use Mautic\CampaignBundle\Entity\Campaign;
|
||||
use Mautic\CampaignBundle\Entity\Event;
|
||||
use Mautic\CampaignBundle\Entity\Lead as CampaignLead;
|
||||
use Mautic\CampaignBundle\Entity\LeadEventLog;
|
||||
use Mautic\CampaignBundle\Entity\Summary;
|
||||
use Mautic\CoreBundle\Test\MauticMysqlTestCase;
|
||||
use Mautic\EmailBundle\Entity\Email;
|
||||
use Mautic\LeadBundle\Entity\Lead;
|
||||
use PHPUnit\Framework\Assert;
|
||||
|
||||
class CampaignSummarizationFunctionalTest extends MauticMysqlTestCase
|
||||
{
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->configParams['campaign_use_summary'] = 'testExecuteCampaignEventWithSummarization' === $this->name();
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
public function testExecuteCampaignEventWithoutSummarization(): void
|
||||
{
|
||||
$this->createDataAndExecuteCommand();
|
||||
$campaignSummary = $this->em->getRepository(Summary::class)->findAll();
|
||||
Assert::assertCount(0, $campaignSummary);
|
||||
}
|
||||
|
||||
public function testExecuteCampaignEventWithSummarization(): void
|
||||
{
|
||||
$this->createDataAndExecuteCommand();
|
||||
$campaignSummary = $this->em->getRepository(Summary::class)->findAll();
|
||||
Assert::assertCount(1, $campaignSummary);
|
||||
}
|
||||
|
||||
private function createDataAndExecuteCommand(): void
|
||||
{
|
||||
$lead = $this->createLead();
|
||||
$campaign = $this->createCampaign();
|
||||
$email = $this->createEmail('Email 1');
|
||||
$properties = [
|
||||
'canvasSettings' => [
|
||||
'droppedX' => '549',
|
||||
'droppedY' => '155',
|
||||
],
|
||||
'name' => '',
|
||||
'triggerMode' => 'immediate',
|
||||
'triggerDate' => null,
|
||||
'triggerInterval' => '1',
|
||||
'triggerIntervalUnit' => 'd',
|
||||
'triggerHour' => '',
|
||||
'triggerRestrictedStartHour' => '',
|
||||
'triggerRestrictedStopHour' => '',
|
||||
'anchor' => 'leadsource',
|
||||
'properties' => [
|
||||
'email' => $email->getId(),
|
||||
'email_type' => 'transactional',
|
||||
'priority' => '2',
|
||||
'attempts' => '3',
|
||||
],
|
||||
'type' => 'email.send',
|
||||
'eventType' => 'action',
|
||||
'anchorEventType' => 'source',
|
||||
'buttons' => [
|
||||
'save' => '',
|
||||
],
|
||||
'email' => $email->getId(),
|
||||
'email_type' => 'transactional',
|
||||
'priority' => 2,
|
||||
'attempts' => 3.0,
|
||||
];
|
||||
$event = $this->createEvent('Event 1', $campaign, $properties);
|
||||
$this->createCampaignLead($campaign, $lead);
|
||||
$this->createEventLog($lead, $event, $campaign);
|
||||
$this->em->flush();
|
||||
$this->em->clear();
|
||||
|
||||
$this->testSymfonyCommand('mautic:campaigns:trigger', ['--campaign-id' => $campaign->getId(), '--kickoff-only' => true]);
|
||||
}
|
||||
|
||||
private function createLead(): Lead
|
||||
{
|
||||
$lead = new Lead();
|
||||
$lead->setFirstname('Test');
|
||||
$this->em->persist($lead);
|
||||
|
||||
return $lead;
|
||||
}
|
||||
|
||||
private function createCampaign(): Campaign
|
||||
{
|
||||
$campaign = new Campaign();
|
||||
$campaign->setName('My campaign');
|
||||
$campaign->setIsPublished(true);
|
||||
$this->em->persist($campaign);
|
||||
|
||||
return $campaign;
|
||||
}
|
||||
|
||||
private function createCampaignLead(Campaign $campaign, Lead $lead): CampaignLead
|
||||
{
|
||||
$campaignLead = new CampaignLead();
|
||||
$campaignLead->setCampaign($campaign);
|
||||
$campaignLead->setLead($lead);
|
||||
$campaignLead->setDateAdded(new \DateTime());
|
||||
$this->em->persist($campaignLead);
|
||||
|
||||
return $campaignLead;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed[] $properties
|
||||
*/
|
||||
private function createEvent(string $name, Campaign $campaign, array $properties = []): Event
|
||||
{
|
||||
$event = new Event();
|
||||
$event->setName($name);
|
||||
$event->setCampaign($campaign);
|
||||
$event->setType('email.send');
|
||||
$event->setProperties($properties);
|
||||
$event->setEventType('action');
|
||||
$event->setTriggerInterval(1);
|
||||
$event->setTriggerMode('immediate');
|
||||
$this->em->persist($event);
|
||||
|
||||
return $event;
|
||||
}
|
||||
|
||||
private function createEmail(string $name): Email
|
||||
{
|
||||
$email = new Email();
|
||||
$email->setName($name);
|
||||
$email->setSubject('Test Subject');
|
||||
$email->setIsPublished(true);
|
||||
|
||||
$this->em->persist($email);
|
||||
|
||||
return $email;
|
||||
}
|
||||
|
||||
private function createEventLog(Lead $lead, Event $event, Campaign $campaign): LeadEventLog
|
||||
{
|
||||
$leadEventLog = new LeadEventLog();
|
||||
$leadEventLog->setLead($lead);
|
||||
$leadEventLog->setEvent($event);
|
||||
$leadEventLog->setCampaign($campaign);
|
||||
$leadEventLog->setRotation(0);
|
||||
$this->em->persist($leadEventLog);
|
||||
|
||||
return $leadEventLog;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\CampaignBundle\Tests\Command;
|
||||
|
||||
use Mautic\CampaignBundle\Entity\LeadEventLog;
|
||||
use Mautic\CampaignBundle\Entity\LeadEventLogRepository;
|
||||
use Mautic\CampaignBundle\Executioner\ScheduledExecutioner;
|
||||
use Mautic\CampaignBundle\Tests\Functional\Fixtures\FixtureHelper;
|
||||
use Mautic\CoreBundle\Helper\DateTimeHelper;
|
||||
use PHPUnit\Framework\Assert;
|
||||
|
||||
class ExecuteEventCommandTest extends AbstractCampaignCommand
|
||||
{
|
||||
public function testEventsAreExecutedForInactiveEventWithSingleContact(): void
|
||||
{
|
||||
putenv('CAMPAIGN_EXECUTIONER_SCHEDULER_ACKNOWLEDGE_SECONDS=1');
|
||||
|
||||
$this->testSymfonyCommand('mautic:campaigns:trigger', ['-i' => 1, '--contact-ids' => '1,2,3']);
|
||||
|
||||
// There should be three events scheduled
|
||||
$byEvent = $this->getCampaignEventLogs([2]);
|
||||
$this->assertCount(3, $byEvent[2]);
|
||||
|
||||
$logIds = [];
|
||||
foreach ($byEvent[2] as $log) {
|
||||
if (0 === (int) $log['is_scheduled']) {
|
||||
$this->fail('Event is not scheduled for lead ID '.$log['lead_id']);
|
||||
}
|
||||
|
||||
$logIds[] = $log['id'];
|
||||
}
|
||||
|
||||
$this->testSymfonyCommand('mautic:campaigns:execute', ['--scheduled-log-ids' => implode(',', $logIds)]);
|
||||
|
||||
// There should still be three events scheduled
|
||||
$byEvent = $this->getCampaignEventLogs([2]);
|
||||
$this->assertCount(3, $byEvent[2]);
|
||||
|
||||
foreach ($byEvent[2] as $log) {
|
||||
if (0 === (int) $log['is_scheduled']) {
|
||||
$this->fail('Event is not scheduled for lead ID '.$log['lead_id']);
|
||||
}
|
||||
}
|
||||
|
||||
// Pop off the last so we can test that only the two given are executed
|
||||
$lastId = array_pop($logIds);
|
||||
|
||||
// Wait 6 seconds to go past scheduled time
|
||||
static::getContainer()->get(ScheduledExecutioner::class)->setNowTime(new \DateTime('+'.self::CONDITION_SECONDS.' seconds'));
|
||||
|
||||
$this->testSymfonyCommand('mautic:campaigns:execute', ['--scheduled-log-ids' => implode(',', $logIds)]);
|
||||
|
||||
// The events should have executed
|
||||
$byEvent = $this->getCampaignEventLogs([2]);
|
||||
$this->assertCount(3, $byEvent[2]);
|
||||
|
||||
foreach ($byEvent[2] as $log) {
|
||||
// Lasta
|
||||
if ($log['id'] === $lastId) {
|
||||
if (0 === (int) $log['is_scheduled']) {
|
||||
$this->fail('Event is not scheduled when it should be for lead ID '.$log['lead_id']);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (1 === (int) $log['is_scheduled']) {
|
||||
$this->fail('Event is still scheduled for lead ID '.$log['lead_id']);
|
||||
}
|
||||
}
|
||||
|
||||
putenv('CAMPAIGN_EXECUTIONER_SCHEDULER_ACKNOWLEDGE_SECONDS=0');
|
||||
}
|
||||
|
||||
public function testRepublishScheduledCampaignEventActionWhenEventFailedBecauseCampaignWasUnpublished(): void
|
||||
{
|
||||
$fixtureHelper = new FixtureHelper($this->em);
|
||||
$contact = $fixtureHelper->createContact('some@contact.email');
|
||||
$campaign = $fixtureHelper->createCampaign('Scheduled event test');
|
||||
$fixtureHelper->addContactToCampaign($contact, $campaign);
|
||||
$fixtureHelper->createCampaignWithScheduledEvent($campaign);
|
||||
|
||||
$this->em->flush();
|
||||
|
||||
$commandResult = $this->testSymfonyCommand('mautic:campaigns:trigger', ['--campaign-id' => $campaign->getId()]);
|
||||
|
||||
Assert::assertStringContainsString('1 total event was scheduled', $commandResult->getDisplay());
|
||||
|
||||
$campaign->setIsPublished(false);
|
||||
$this->em->persist($campaign);
|
||||
$this->em->flush();
|
||||
$this->em->clear();
|
||||
|
||||
$leadEventLogRepository = $this->em->getRepository(LeadEventLog::class);
|
||||
\assert($leadEventLogRepository instanceof LeadEventLogRepository);
|
||||
|
||||
$log = $leadEventLogRepository->findOneBy(['lead' => $contact, 'campaign' => $campaign]);
|
||||
\assert($log instanceof LeadEventLog);
|
||||
|
||||
Assert::assertTrue($log->getIsScheduled());
|
||||
|
||||
// Time machine so we don't have to wait for that long.
|
||||
$log->setTriggerDate(new \DateTime('2 days ago'));
|
||||
$log->setDateTriggered(new \DateTime('2 days ago'));
|
||||
$log->setIsScheduled(true);
|
||||
$this->em->persist($log);
|
||||
$this->em->flush();
|
||||
$this->em->clear();
|
||||
|
||||
$commandResult = $this->testSymfonyCommand('mautic:campaigns:execute', ['--scheduled-log-ids' => $log->getId()]);
|
||||
|
||||
Assert::assertStringContainsString('0 total events(s) to be processed', $commandResult->getDisplay());
|
||||
Assert::assertStringContainsString('0 total events were executed', $commandResult->getDisplay());
|
||||
Assert::assertStringContainsString('0 total events were scheduled', $commandResult->getDisplay());
|
||||
|
||||
$log = $leadEventLogRepository->findOneBy(['lead' => $contact, 'campaign' => $campaign]);
|
||||
\assert($log instanceof LeadEventLog);
|
||||
|
||||
Assert::assertTrue($log->getIsScheduled());
|
||||
Assert::assertSame([], $log->getMetadata());
|
||||
}
|
||||
|
||||
public function testRepublishScheduledCampaignEventActionWhenEventFailedBecauseCampaignPublishDownIsInThePast(): void
|
||||
{
|
||||
$fixtureHelper = new FixtureHelper($this->em);
|
||||
$contact = $fixtureHelper->createContact('some@contact.email');
|
||||
$campaign = $fixtureHelper->createCampaign('Scheduled event test');
|
||||
$fixtureHelper->addContactToCampaign($contact, $campaign);
|
||||
$fixtureHelper->createCampaignWithScheduledEvent($campaign);
|
||||
|
||||
$this->em->flush();
|
||||
|
||||
$commandResult = $this->testSymfonyCommand('mautic:campaigns:trigger', ['--campaign-id' => $campaign->getId()]);
|
||||
|
||||
Assert::assertStringContainsString('1 total event was scheduled', $commandResult->getDisplay());
|
||||
|
||||
$campaign->setPublishUp(new \DateTime('3 days ago'));
|
||||
$campaign->setPublishDown(new \DateTime('1 days ago'));
|
||||
$this->em->persist($campaign);
|
||||
$this->em->flush();
|
||||
$this->em->clear();
|
||||
|
||||
$leadEventLogRepository = $this->em->getRepository(LeadEventLog::class);
|
||||
\assert($leadEventLogRepository instanceof LeadEventLogRepository);
|
||||
|
||||
$log = $leadEventLogRepository->findOneBy(['lead' => $contact, 'campaign' => $campaign]);
|
||||
\assert($log instanceof LeadEventLog);
|
||||
|
||||
Assert::assertTrue($log->getIsScheduled());
|
||||
|
||||
// Time machine so we don't have to wait for that long.
|
||||
$log->setTriggerDate(new \DateTime('2 days ago'));
|
||||
$log->setDateTriggered(new \DateTime('2 days ago'));
|
||||
$log->setIsScheduled(true);
|
||||
$this->em->persist($log);
|
||||
$this->em->flush();
|
||||
$this->em->clear();
|
||||
|
||||
$commandResult = $this->testSymfonyCommand('mautic:campaigns:execute', ['--scheduled-log-ids' => $log->getId()]);
|
||||
|
||||
Assert::assertStringContainsString('1 total events(s) to be processed', $commandResult->getDisplay());
|
||||
Assert::assertStringContainsString('0 total events were executed', $commandResult->getDisplay());
|
||||
Assert::assertStringContainsString('0 total events were scheduled', $commandResult->getDisplay());
|
||||
}
|
||||
|
||||
public function testScheduledCampaignEventActionIfScheduledAtDefined(): void
|
||||
{
|
||||
$interval = 5;
|
||||
$unit = 'i';
|
||||
$fixtureHelper = new FixtureHelper($this->em);
|
||||
$contact = $fixtureHelper->createContact('some@contact.email');
|
||||
$campaign = $fixtureHelper->createCampaign('Scheduled event test');
|
||||
$fixtureHelper->addContactToCampaign($contact, $campaign);
|
||||
$hour = new \DateTime();
|
||||
$hour->add((new DateTimeHelper())->buildInterval($interval, $unit));
|
||||
$fixtureHelper->createCampaignWithScheduledEvent($campaign, $interval, $unit, $hour);
|
||||
|
||||
$this->em->flush();
|
||||
|
||||
$commandResult = $this->testSymfonyCommand('mautic:campaigns:trigger', ['--campaign-id' => $campaign->getId()]);
|
||||
|
||||
Assert::assertStringContainsString('1 total event was scheduled', $commandResult->getDisplay());
|
||||
|
||||
$leadEventLogRepository = $this->em->getRepository(LeadEventLog::class);
|
||||
\assert($leadEventLogRepository instanceof LeadEventLogRepository);
|
||||
|
||||
$log = $leadEventLogRepository->findOneBy(['lead' => $contact, 'campaign' => $campaign]);
|
||||
\assert($log instanceof LeadEventLog);
|
||||
|
||||
Assert::assertTrue($log->getIsScheduled());
|
||||
|
||||
$commandResult = $this->testSymfonyCommand('mautic:campaigns:execute', ['--scheduled-log-ids' => $log->getId()]);
|
||||
|
||||
Assert::assertStringContainsString('1 total events(s) to be processed', $commandResult->getDisplay());
|
||||
Assert::assertStringContainsString('1 total event was scheduled', $commandResult->getDisplay());
|
||||
Assert::assertStringContainsString('0 total events were executed', $commandResult->getDisplay());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\CampaignBundle\Tests\Command;
|
||||
|
||||
use Mautic\CampaignBundle\Command\SummarizeCommand;
|
||||
use Mautic\CampaignBundle\Entity\Summary;
|
||||
use Mautic\CampaignBundle\Entity\SummaryRepository;
|
||||
use Mautic\CampaignBundle\Tests\Campaign\AbstractCampaignTestCase;
|
||||
use PHPUnit\Framework\Assert;
|
||||
|
||||
final class SummarizeCommandTest extends AbstractCampaignTestCase
|
||||
{
|
||||
/**
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function testBackwardSummarizationWhenThereAreNoCampaignEventLogs(): void
|
||||
{
|
||||
$commandResult = $this->testSymfonyCommand(
|
||||
SummarizeCommand::NAME,
|
||||
[
|
||||
'--env' => 'test',
|
||||
'--max-hours' => 768,
|
||||
]
|
||||
);
|
||||
|
||||
/** @var SummaryRepository $summaryRepo */
|
||||
$summaryRepo = $this->em->getRepository(Summary::class);
|
||||
Assert::assertCount(0, $summaryRepo->findAll());
|
||||
Assert::assertStringContainsString(
|
||||
'There are no records in the campaign lead event log table. Nothing to summarize.',
|
||||
$commandResult->getDisplay()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function testBackwardSummarizationWhenThereAreLogs(): void
|
||||
{
|
||||
$relativeDate = date('Y-m-d', strtotime('-1 month'));
|
||||
|
||||
$campaign = $this->saveSomeCampaignLeadEventLogs();
|
||||
|
||||
$this->testSymfonyCommand(
|
||||
SummarizeCommand::NAME,
|
||||
[
|
||||
'--env' => 'test',
|
||||
'--max-hours' => 768,
|
||||
]
|
||||
);
|
||||
|
||||
/** @var SummaryRepository $summaryRepo */
|
||||
$summaryRepo = $this->em->getRepository(Summary::class);
|
||||
|
||||
/** @var Summary[] $summaries */
|
||||
$summaries = $summaryRepo->findAll();
|
||||
|
||||
Assert::assertCount(3, $summaries);
|
||||
|
||||
Assert::assertSame($relativeDate.'T17:00:00+00:00', $summaries[0]->getDateTriggered()->format(DATE_ATOM));
|
||||
Assert::assertSame(1, $summaries[0]->getTriggeredCount());
|
||||
Assert::assertSame($campaign->getId(), $summaries[0]->getCampaign()->getId());
|
||||
Assert::assertSame('Event B', $summaries[0]->getEvent()->getName());
|
||||
|
||||
Assert::assertSame($relativeDate.'T16:00:00+00:00', $summaries[1]->getDateTriggered()->format(DATE_ATOM));
|
||||
Assert::assertSame(2, $summaries[1]->getTriggeredCount());
|
||||
Assert::assertSame($campaign->getId(), $summaries[1]->getCampaign()->getId());
|
||||
Assert::assertSame('Event A', $summaries[1]->getEvent()->getName());
|
||||
|
||||
Assert::assertSame($relativeDate.'T16:00:00+00:00', $summaries[2]->getDateTriggered()->format(DATE_ATOM));
|
||||
Assert::assertSame(1, $summaries[2]->getTriggeredCount());
|
||||
Assert::assertSame($campaign->getId(), $summaries[2]->getCampaign()->getId());
|
||||
Assert::assertSame('Event B', $summaries[2]->getEvent()->getName());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,806 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\CampaignBundle\Tests\Command;
|
||||
|
||||
use Mautic\CampaignBundle\Entity\Campaign;
|
||||
use Mautic\CampaignBundle\Entity\Lead;
|
||||
use Mautic\CampaignBundle\Entity\LeadEventLog;
|
||||
use Mautic\CampaignBundle\Executioner\InactiveExecutioner;
|
||||
use Mautic\CampaignBundle\Executioner\ScheduledExecutioner;
|
||||
use Mautic\LeadBundle\Command\SegmentCountCacheCommand;
|
||||
use Mautic\LeadBundle\Entity\ListLead;
|
||||
use Mautic\LeadBundle\Helper\SegmentCountCacheHelper;
|
||||
use PHPUnit\Framework\Assert;
|
||||
|
||||
class TriggerCampaignCommandTest extends AbstractCampaignCommand
|
||||
{
|
||||
private ?SegmentCountCacheHelper $segmentCountCacheHelper = null;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->configParams['update_segment_contact_count_in_background'] = 'testSegmentCacheCountInBackground' === $this->name();
|
||||
parent::setUp();
|
||||
|
||||
putenv('CAMPAIGN_EXECUTIONER_SCHEDULER_ACKNOWLEDGE_SECONDS=1');
|
||||
|
||||
$this->segmentCountCacheHelper = static::getContainer()->get('mautic.helper.segment.count.cache');
|
||||
}
|
||||
|
||||
public function beforeTearDown(): void
|
||||
{
|
||||
parent::beforeTearDown();
|
||||
|
||||
putenv('CAMPAIGN_EXECUTIONER_SCHEDULER_ACKNOWLEDGE_SECONDS=0');
|
||||
|
||||
$this->segmentCountCacheHelper = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function testCampaignExecutionForAll(): void
|
||||
{
|
||||
// Process in batches of 10 to ensure batching is working as expected
|
||||
$this->testSymfonyCommand('mautic:campaigns:trigger', ['-i' => 1, '-l' => 10]);
|
||||
|
||||
// Let's analyze
|
||||
$byEvent = $this->getCampaignEventLogs([1, 2, 11, 12, 13, 16]);
|
||||
$tags = $this->getTagCounts();
|
||||
|
||||
// Everyone should have been tagged with CampaignTest and have been sent Campaign Test Email 1
|
||||
$this->assertCount(50, $byEvent[1]);
|
||||
$this->assertCount(50, $byEvent[2]);
|
||||
|
||||
// Sending Campaign Test Email 1 should be scheduled
|
||||
foreach ($byEvent[2] as $log) {
|
||||
if (0 === (int) $log['is_scheduled']) {
|
||||
$this->fail('Sending Campaign Test Email 1 was not scheduled for lead ID '.$log['lead_id']);
|
||||
}
|
||||
}
|
||||
|
||||
// Everyone should have had the Is US condition processed
|
||||
$this->assertCount(50, $byEvent[11]);
|
||||
|
||||
// 42 should have been send down the non-action path (red) of the condition
|
||||
$nonActionCount = $this->getNonActionPathTakenCount($byEvent[11]);
|
||||
$this->assertEquals(42, $nonActionCount);
|
||||
|
||||
// 8 contacts are from the US and should be labeled with US:Action
|
||||
$this->assertCount(8, $byEvent[12]);
|
||||
$this->assertEquals(8, $tags['US:Action']);
|
||||
|
||||
// Those tagged with US:Action should also be tagged with ChainedAction by a chained event.
|
||||
$this->assertCount(8, $byEvent[16]);
|
||||
$this->assertEquals(8, $tags['ChainedAction']);
|
||||
|
||||
// The rest (42) contacts are not from the US and should be labeled with NonUS:Action
|
||||
$this->assertCount(42, $byEvent[13]);
|
||||
$this->assertEquals(42, $tags['NonUS:Action']);
|
||||
|
||||
// No emails should be sent till after 5 seconds and the command is ran again
|
||||
$stats = $this->db->createQueryBuilder()
|
||||
->select('*')
|
||||
->from($this->prefix.'email_stats', 'stat')
|
||||
->where('stat.lead_id <= 25')
|
||||
->executeQuery()
|
||||
->fetchAllAssociative();
|
||||
$this->assertCount(0, $stats);
|
||||
|
||||
// Wait 6 seconds then execute the campaign again to send scheduled events
|
||||
static::getContainer()->get(ScheduledExecutioner::class)->setNowTime(new \DateTime('+'.self::CONDITION_SECONDS.' seconds'));
|
||||
$this->testSymfonyCommand('mautic:campaigns:trigger', ['-i' => 1, '-l' => 10]);
|
||||
|
||||
// Send email 1 should no longer be scheduled
|
||||
$byEvent = $this->getCampaignEventLogs([2, 4]);
|
||||
$this->assertCount(50, $byEvent[2]);
|
||||
foreach ($byEvent[2] as $log) {
|
||||
if (1 === (int) $log['is_scheduled']) {
|
||||
$this->fail('Sending Campaign Test Email 1 is still scheduled for lead ID '.$log['lead_id']);
|
||||
}
|
||||
}
|
||||
|
||||
// The non-action events attached to the decision should have no logs entries
|
||||
$this->assertCount(0, $byEvent[4]);
|
||||
|
||||
// Check that the emails actually sent
|
||||
$stats = $this->db->createQueryBuilder()
|
||||
->select('*')
|
||||
->from($this->prefix.'email_stats', 'stat')
|
||||
->where('stat.lead_id <= 25')
|
||||
->executeQuery()
|
||||
->fetchAllAssociative();
|
||||
|
||||
$this->assertCount(25, $stats);
|
||||
|
||||
// Now let's simulate email opens
|
||||
foreach ($stats as $stat) {
|
||||
$this->client->request('GET', '/email/'.$stat['tracking_hash'].'.gif');
|
||||
$this->assertEquals(200, $this->client->getResponse()->getStatusCode(), var_export($this->client->getResponse()->getContent(), true));
|
||||
}
|
||||
|
||||
$byEvent = $this->getCampaignEventLogs([3, 4, 5, 10, 14, 15]);
|
||||
|
||||
// The non-action events attached to the decision should have no logs entries
|
||||
$this->assertCount(0, $byEvent[4]);
|
||||
$this->assertCount(0, $byEvent[5]);
|
||||
$this->assertCount(0, $byEvent[14]);
|
||||
$this->assertCount(0, $byEvent[15]);
|
||||
|
||||
// Those 25 should now have open email decisions logged and the next email sent
|
||||
$this->assertCount(25, $byEvent[3]);
|
||||
$this->assertCount(25, $byEvent[10]);
|
||||
|
||||
// Wait another 6 seconds to go beyond the inaction timeframe
|
||||
static::getContainer()->get(InactiveExecutioner::class)->setNowTime(new \DateTime('+'.(self::CONDITION_SECONDS * 2).' seconds'));
|
||||
|
||||
// Execute the command again to trigger inaction related events
|
||||
$this->testSymfonyCommand('mautic:campaigns:trigger', ['-i' => 1, '-l' => 10]);
|
||||
|
||||
// Now we should have 50 email open decisions
|
||||
$byEvent = $this->getCampaignEventLogs([3, 4, 5, 14, 15]);
|
||||
$this->assertCount(50, $byEvent[3]);
|
||||
|
||||
// 25 should be marked as non_action_path_taken
|
||||
$nonActionCount = $this->getNonActionPathTakenCount($byEvent[3]);
|
||||
$this->assertEquals(25, $nonActionCount);
|
||||
|
||||
// A condition should be logged as evaluated for each of the 25 contacts
|
||||
$this->assertCount(25, $byEvent[4]);
|
||||
$this->assertCount(25, $byEvent[5]);
|
||||
|
||||
// Tag EmailNotOpen should all be scheduled for these 25 contacts because the condition's timeframe was shorter and therefore the
|
||||
// contact was sent down the inaction path
|
||||
$this->assertCount(25, $byEvent[14]);
|
||||
$this->assertCount(25, $byEvent[15]);
|
||||
|
||||
$utcTimezone = new \DateTimeZone('UTC');
|
||||
foreach ($byEvent[14] as $log) {
|
||||
if (0 === (int) $log['is_scheduled']) {
|
||||
$this->fail('Tag EmailNotOpen is not scheduled for lead ID '.$log['lead_id']);
|
||||
}
|
||||
|
||||
$scheduledFor = new \DateTime($log['trigger_date'], $utcTimezone);
|
||||
$diff = $this->eventDate->diff($scheduledFor);
|
||||
|
||||
if (2 !== $diff->i) {
|
||||
$this->fail('Tag EmailNotOpen should be scheduled for around 2 minutes ('.$diff->i.' minutes)');
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($byEvent[15] as $log) {
|
||||
if (0 === (int) $log['is_scheduled']) {
|
||||
$this->fail('Tag EmailNotOpen Again is not scheduled for lead ID '.$log['lead_id']);
|
||||
}
|
||||
|
||||
$scheduledFor = new \DateTime($log['trigger_date'], $utcTimezone);
|
||||
$diff = $this->eventDate->diff($scheduledFor);
|
||||
|
||||
if (6 !== $diff->i) {
|
||||
$this->fail('Tag EmailNotOpen Again should be scheduled for around 6 minutes ('.$diff->i.' minutes)');
|
||||
}
|
||||
}
|
||||
$byEvent = $this->getCampaignEventLogs([6, 7, 8, 9]);
|
||||
$tags = $this->getTagCounts();
|
||||
|
||||
// Of those that did not open the email, 6 should be tagged US:NotOpen
|
||||
$this->assertCount(6, $byEvent[6]);
|
||||
$this->assertEquals(6, $tags['US:NotOpen']);
|
||||
|
||||
// And 19 should be tagged NonUS:NotOpen
|
||||
$this->assertCount(19, $byEvent[7]);
|
||||
$this->assertEquals(19, $tags['NonUS:NotOpen']);
|
||||
|
||||
// And 4 should be tagged UK:NotOpen
|
||||
$this->assertCount(4, $byEvent[8]);
|
||||
$this->assertEquals(4, $tags['UK:NotOpen']);
|
||||
|
||||
// And 21 should be tagged NonUK:NotOpen
|
||||
$this->assertCount(21, $byEvent[9]);
|
||||
$this->assertEquals(21, $tags['NonUK:NotOpen']);
|
||||
|
||||
// No one should be tagged as EmailNotOpen because the actions are still scheduled
|
||||
$this->assertFalse(isset($tags['EmailNotOpen']));
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function testCampaignExecutionForOne(): void
|
||||
{
|
||||
$this->testSymfonyCommand('mautic:campaigns:trigger', ['-i' => 1, '--contact-id' => 1]);
|
||||
|
||||
// Let's analyze
|
||||
$byEvent = $this->getCampaignEventLogs([1, 2, 11, 12, 13, 16]);
|
||||
$tags = $this->getTagCounts();
|
||||
|
||||
// Everyone should have been tagged with CampaignTest and have been sent Campaign Test Email 1
|
||||
$this->assertCount(1, $byEvent[1]);
|
||||
$this->assertCount(1, $byEvent[2]);
|
||||
|
||||
// Sending Campaign Test Email 1 should be scheduled
|
||||
foreach ($byEvent[2] as $log) {
|
||||
if (0 === (int) $log['is_scheduled']) {
|
||||
$this->fail('Sending Campaign Test Email 1 was not scheduled for lead ID '.$log['lead_id']);
|
||||
}
|
||||
}
|
||||
|
||||
// Everyone should have had the Is US condition processed
|
||||
$this->assertCount(1, $byEvent[11]);
|
||||
|
||||
// 1 should have been send down the non-action path (red) of the condition
|
||||
$nonActionCount = $this->getNonActionPathTakenCount($byEvent[11]);
|
||||
$this->assertEquals(1, $nonActionCount);
|
||||
|
||||
// 0 contacts are from the US and should be labeled with US:Action
|
||||
$this->assertCount(0, $byEvent[12]);
|
||||
$this->assertTrue(empty($tags['US:Action']));
|
||||
|
||||
// None tagged with US:Action, so none should be tagged with ChainedAction by a chained event.
|
||||
$this->assertCount(0, $byEvent[16]);
|
||||
$this->assertTrue(empty($tags['ChainedAction']));
|
||||
|
||||
// The rest (1) contacts are not from the US and should be labeled with NonUS:Action
|
||||
$this->assertCount(1, $byEvent[13]);
|
||||
$this->assertEquals(1, $tags['NonUS:Action']);
|
||||
|
||||
// No emails should be sent till after 5 seconds and the command is ran again
|
||||
$stats = $this->db->createQueryBuilder()
|
||||
->select('*')
|
||||
->from($this->prefix.'email_stats', 'stat')
|
||||
->where('stat.lead_id = 1')
|
||||
->executeQuery()
|
||||
->fetchAllAssociative();
|
||||
|
||||
$this->assertCount(0, $stats);
|
||||
|
||||
// Wait 6 seconds then execute the campaign again to send scheduled events
|
||||
static::getContainer()->get(ScheduledExecutioner::class)->setNowTime(new \DateTime('+'.self::CONDITION_SECONDS.' seconds'));
|
||||
$this->testSymfonyCommand('mautic:campaigns:trigger', ['-i' => 1, '--contact-id' => 1]);
|
||||
|
||||
// Send email 1 should no longer be scheduled
|
||||
$byEvent = $this->getCampaignEventLogs([2, 4]);
|
||||
$this->assertCount(1, $byEvent[2]);
|
||||
foreach ($byEvent[2] as $log) {
|
||||
if (1 === (int) $log['is_scheduled']) {
|
||||
$this->fail('Sending Campaign Test Email 1 is still scheduled for lead ID '.$log['lead_id']);
|
||||
}
|
||||
}
|
||||
|
||||
// The non-action events attached to the decision should have no logs entries
|
||||
$this->assertCount(0, $byEvent[4]);
|
||||
|
||||
// Check that the emails actually sent
|
||||
$stats = $this->db->createQueryBuilder()
|
||||
->select('*')
|
||||
->from($this->prefix.'email_stats', 'stat')
|
||||
->where('stat.lead_id = 1')
|
||||
->executeQuery()
|
||||
->fetchAllAssociative();
|
||||
|
||||
$this->assertCount(1, $stats);
|
||||
|
||||
// Now let's simulate email opens
|
||||
foreach ($stats as $stat) {
|
||||
$this->client->request('GET', '/email/'.$stat['tracking_hash'].'.gif');
|
||||
$this->assertEquals(200, $this->client->getResponse()->getStatusCode(), var_export($this->client->getResponse()->getContent(), true));
|
||||
}
|
||||
|
||||
$byEvent = $this->getCampaignEventLogs([3, 4, 5, 10, 14, 15]);
|
||||
|
||||
// The non-action events attached to the decision should have no logs entries
|
||||
$this->assertCount(0, $byEvent[4]);
|
||||
$this->assertCount(0, $byEvent[5]);
|
||||
$this->assertCount(0, $byEvent[14]);
|
||||
$this->assertCount(0, $byEvent[15]);
|
||||
|
||||
// The 1 should now have open email decisions logged and the next email sent
|
||||
$this->assertCount(1, $byEvent[3]);
|
||||
$this->assertCount(1, $byEvent[10]);
|
||||
|
||||
// Wait 6 seconds to go beyond the inaction timeframe
|
||||
static::getContainer()->get(InactiveExecutioner::class)->setNowTime(new \DateTime('+'.(self::CONDITION_SECONDS * 2).' seconds'));
|
||||
|
||||
// Execute the command again to trigger inaction related events
|
||||
$this->testSymfonyCommand('mautic:campaigns:trigger', ['-i' => 1, '--contact-id' => 1]);
|
||||
|
||||
// Now we should have 1 email open decisions
|
||||
$byEvent = $this->getCampaignEventLogs([3, 4, 5, 14, 15]);
|
||||
$this->assertCount(1, $byEvent[3]);
|
||||
|
||||
// 0 should be marked as non_action_path_taken
|
||||
$nonActionCount = $this->getNonActionPathTakenCount($byEvent[3]);
|
||||
$this->assertEquals(0, $nonActionCount);
|
||||
|
||||
// There should be no inactive events
|
||||
$this->assertCount(0, $byEvent[4]);
|
||||
$this->assertCount(0, $byEvent[5]);
|
||||
$this->assertCount(0, $byEvent[14]);
|
||||
$this->assertCount(0, $byEvent[15]);
|
||||
|
||||
$utcTimezone = new \DateTimeZone('UTC');
|
||||
foreach ($byEvent[14] as $log) {
|
||||
if (0 === (int) $log['is_scheduled']) {
|
||||
$this->fail('Tag EmailNotOpen is not scheduled for lead ID '.$log['lead_id']);
|
||||
}
|
||||
|
||||
$scheduledFor = new \DateTime($log['trigger_date'], $utcTimezone);
|
||||
$diff = $this->eventDate->diff($scheduledFor);
|
||||
|
||||
if (2 !== $diff->i) {
|
||||
$this->fail('Tag EmailNotOpen should be scheduled for around 2 minutes ('.$diff->i.' minutes)');
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($byEvent[15] as $log) {
|
||||
if (0 === (int) $log['is_scheduled']) {
|
||||
$this->fail('Tag EmailNotOpen Again is not scheduled for lead ID '.$log['lead_id']);
|
||||
}
|
||||
|
||||
$scheduledFor = new \DateTime($log['trigger_date'], $utcTimezone);
|
||||
$diff = $this->eventDate->diff($scheduledFor);
|
||||
|
||||
if (6 !== $diff->i) {
|
||||
$this->fail('Tag EmailNotOpen Again should be scheduled for around 6 minutes ('.$diff->i.' minutes)');
|
||||
}
|
||||
}
|
||||
$byEvent = $this->getCampaignEventLogs([6, 7, 8, 9]);
|
||||
$tags = $this->getTagCounts();
|
||||
|
||||
// Of those that did not open the email, 0 should be tagged US:NotOpen
|
||||
$this->assertCount(0, $byEvent[6]);
|
||||
$this->assertTrue(empty($tags['US:NotOpen']));
|
||||
|
||||
// And 0 should be tagged NonUS:NotOpen
|
||||
$this->assertCount(0, $byEvent[7]);
|
||||
$this->assertTrue(empty($tags['NonUS:NotOpen']));
|
||||
|
||||
// And 0 should be tagged UK:NotOpen
|
||||
$this->assertCount(0, $byEvent[8]);
|
||||
$this->assertTrue(empty($tags['UK:NotOpen']));
|
||||
|
||||
// And 0 should be tagged NonUK:NotOpen
|
||||
$this->assertCount(0, $byEvent[9]);
|
||||
$this->assertTrue(empty($tags['NonUK:NotOpen']));
|
||||
|
||||
// No one should be tagged as EmailNotOpen because the actions are still scheduled
|
||||
$this->assertTrue(empty($tags['EmailNotOpen']));
|
||||
}
|
||||
|
||||
public function testCampaignExecutionForSome(): void
|
||||
{
|
||||
$this->testSymfonyCommand('mautic:campaigns:trigger', ['-i' => 1, '--contact-ids' => '1,2,3,4,19']);
|
||||
|
||||
// Let's analyze
|
||||
$byEvent = $this->getCampaignEventLogs([1, 2, 11, 12, 13, 16]);
|
||||
$tags = $this->getTagCounts();
|
||||
|
||||
// Everyone should have been tagged with CampaignTest and have been sent Campaign Test Email 1
|
||||
$this->assertCount(5, $byEvent[1]);
|
||||
$this->assertCount(5, $byEvent[2]);
|
||||
|
||||
// Sending Campaign Test Email 1 should be scheduled
|
||||
foreach ($byEvent[2] as $log) {
|
||||
if (0 === (int) $log['is_scheduled']) {
|
||||
$this->fail('Sending Campaign Test Email 1 was not scheduled for lead ID '.$log['lead_id']);
|
||||
}
|
||||
}
|
||||
|
||||
// Everyone should have had the Is US condition processed
|
||||
$this->assertCount(5, $byEvent[11]);
|
||||
|
||||
// 4 should have been send down the non-action path (red) of the condition
|
||||
$nonActionCount = $this->getNonActionPathTakenCount($byEvent[11]);
|
||||
$this->assertEquals(4, $nonActionCount);
|
||||
|
||||
// 1 contacts are from the US and should be labeled with US:Action
|
||||
$this->assertCount(1, $byEvent[12]);
|
||||
$this->assertEquals(1, $tags['US:Action']);
|
||||
|
||||
// Those tagged with US:Action should also be tagged with ChainedAction by a chained event.
|
||||
$this->assertCount(1, $byEvent[16]);
|
||||
$this->assertEquals(1, $tags['ChainedAction']);
|
||||
|
||||
// The rest (4) contacts are not from the US and should be labeled with NonUS:Action
|
||||
$this->assertCount(4, $byEvent[13]);
|
||||
$this->assertEquals(4, $tags['NonUS:Action']);
|
||||
|
||||
// No emails should be sent till after 5 seconds and the command is ran again
|
||||
$stats = $this->db->createQueryBuilder()
|
||||
->select('*')
|
||||
->from($this->prefix.'email_stats', 'stat')
|
||||
->where('stat.lead_id <= 2')
|
||||
->executeQuery()
|
||||
->fetchAllAssociative();
|
||||
|
||||
$this->assertCount(0, $stats);
|
||||
|
||||
// Wait 6 seconds then execute the campaign again to send scheduled events
|
||||
static::getContainer()->get(ScheduledExecutioner::class)->setNowTime(new \DateTime('+'.self::CONDITION_SECONDS.' seconds'));
|
||||
$this->testSymfonyCommand('mautic:campaigns:trigger', ['-i' => 1, '--contact-ids' => '1,2,3,4,19']);
|
||||
|
||||
// Send email 1 should no longer be scheduled
|
||||
$byEvent = $this->getCampaignEventLogs([2, 4]);
|
||||
$this->assertCount(5, $byEvent[2]);
|
||||
foreach ($byEvent[2] as $log) {
|
||||
if (1 === (int) $log['is_scheduled']) {
|
||||
$this->fail('Sending Campaign Test Email 1 is still scheduled for lead ID '.$log['lead_id']);
|
||||
}
|
||||
}
|
||||
|
||||
// The non-action events attached to the decision should have no logs entries
|
||||
$this->assertCount(0, $byEvent[4]);
|
||||
|
||||
// Check that the emails actually sent
|
||||
$stats = $this->db->createQueryBuilder()
|
||||
->select('*')
|
||||
->from($this->prefix.'email_stats', 'stat')
|
||||
->where('stat.lead_id <= 2')
|
||||
->executeQuery()
|
||||
->fetchAllAssociative();
|
||||
$this->assertCount(2, $stats);
|
||||
|
||||
// Now let's simulate email opens
|
||||
foreach ($stats as $stat) {
|
||||
$this->client->request('GET', '/email/'.$stat['tracking_hash'].'.gif');
|
||||
$this->assertEquals(200, $this->client->getResponse()->getStatusCode(), var_export($this->client->getResponse()->getContent(), true));
|
||||
}
|
||||
|
||||
$byEvent = $this->getCampaignEventLogs([3, 4, 5, 10, 14, 15]);
|
||||
|
||||
// The non-action events attached to the decision should have no logs entries
|
||||
$this->assertCount(0, $byEvent[4]);
|
||||
$this->assertCount(0, $byEvent[5]);
|
||||
$this->assertCount(0, $byEvent[14]);
|
||||
$this->assertCount(0, $byEvent[15]);
|
||||
|
||||
// Those 25 should now have open email decisions logged and the next email sent
|
||||
$this->assertCount(2, $byEvent[3]);
|
||||
$this->assertCount(2, $byEvent[10]);
|
||||
|
||||
// Wait 6 seconds to go beyond the inaction timeframe
|
||||
static::getContainer()->get(InactiveExecutioner::class)->setNowTime(new \DateTime('+'.(self::CONDITION_SECONDS * 2).' seconds'));
|
||||
|
||||
// Execute the command again to trigger inaction related events
|
||||
$this->testSymfonyCommand('mautic:campaigns:trigger', ['-i' => 1, '--contact-ids' => '1,2,3,4,19']);
|
||||
|
||||
// Now we should have 5 email open decisions
|
||||
$byEvent = $this->getCampaignEventLogs([3, 4, 5, 14, 15]);
|
||||
$this->assertCount(5, $byEvent[3]);
|
||||
|
||||
// 3 should be marked as non_action_path_taken
|
||||
$nonActionCount = $this->getNonActionPathTakenCount($byEvent[3]);
|
||||
$this->assertEquals(3, $nonActionCount);
|
||||
|
||||
// A condition should be logged as evaluated for each of the 3 contacts
|
||||
$this->assertCount(3, $byEvent[4]);
|
||||
$this->assertCount(3, $byEvent[5]);
|
||||
|
||||
// Tag EmailNotOpen should all be scheduled for these 3 contacts because the condition's timeframe was shorter and therefore the
|
||||
// contact was sent down the inaction path
|
||||
$this->assertCount(3, $byEvent[14]);
|
||||
$this->assertCount(3, $byEvent[15]);
|
||||
|
||||
$utcTimezone = new \DateTimeZone('UTC');
|
||||
foreach ($byEvent[14] as $log) {
|
||||
if (0 === (int) $log['is_scheduled']) {
|
||||
$this->fail('Tag EmailNotOpen is not scheduled for lead ID '.$log['lead_id']);
|
||||
}
|
||||
|
||||
$scheduledFor = new \DateTime($log['trigger_date'], $utcTimezone);
|
||||
$diff = $this->eventDate->diff($scheduledFor);
|
||||
|
||||
if (2 !== $diff->i) {
|
||||
$this->fail('Tag EmailNotOpen should be scheduled for around 2 minutes ('.$diff->i.' minutes)');
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($byEvent[15] as $log) {
|
||||
if (0 === (int) $log['is_scheduled']) {
|
||||
$this->fail('Tag EmailNotOpen Again is not scheduled for lead ID '.$log['lead_id']);
|
||||
}
|
||||
|
||||
$scheduledFor = new \DateTime($log['trigger_date'], $utcTimezone);
|
||||
$diff = $this->eventDate->diff($scheduledFor);
|
||||
|
||||
if (6 !== $diff->i) {
|
||||
$this->fail('Tag EmailNotOpen Again should be scheduled for around 6 minutes ('.$diff->i.' minutes)');
|
||||
}
|
||||
}
|
||||
$byEvent = $this->getCampaignEventLogs([6, 7, 8, 9]);
|
||||
$tags = $this->getTagCounts();
|
||||
|
||||
// Of those that did not open the email, 1 should be tagged US:NotOpen
|
||||
$this->assertCount(1, $byEvent[6]);
|
||||
$this->assertEquals(1, $tags['US:NotOpen']);
|
||||
|
||||
// And 2 should be tagged NonUS:NotOpen
|
||||
$this->assertCount(2, $byEvent[7]);
|
||||
$this->assertEquals(2, $tags['NonUS:NotOpen']);
|
||||
|
||||
// And 2 should be tagged UK:NotOpen
|
||||
$this->assertCount(2, $byEvent[8]);
|
||||
$this->assertEquals(2, $tags['UK:NotOpen']);
|
||||
|
||||
// And 1 should be tagged NonUK:NotOpen
|
||||
$this->assertCount(1, $byEvent[9]);
|
||||
$this->assertEquals(1, $tags['NonUK:NotOpen']);
|
||||
|
||||
// No one should be tagged as EmailNotOpen because the actions are still scheduled
|
||||
$this->assertFalse(isset($tags['EmailNotOpen']));
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \Psr\Cache\InvalidArgumentException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function testSegmentCacheCountInBackground(): void
|
||||
{
|
||||
// remove redis key if exist
|
||||
$this->segmentCountCacheHelper->deleteSegmentContactCount(1);
|
||||
|
||||
// Execute the command again to trigger related events.
|
||||
$this->testSymfonyCommand('mautic:campaigns:trigger', ['-i' => 1]);
|
||||
|
||||
$count = $this->segmentCountCacheHelper->getSegmentContactCount(1);
|
||||
self::assertEquals(0, $count);
|
||||
|
||||
$this->testSymfonyCommand(SegmentCountCacheCommand::COMMAND_NAME);
|
||||
|
||||
// Segment cache count should be 50.
|
||||
$count = $this->segmentCountCacheHelper->getSegmentContactCount(1);
|
||||
self::assertEquals(50, $count);
|
||||
}
|
||||
|
||||
public function testCampaignActionChangeMembership(): void
|
||||
{
|
||||
$campaign1 = $this->createCampaign('Campaign 1');
|
||||
$campaign2 = $this->createCampaign('Campaign 2');
|
||||
$lead = $this->createLead('Lead');
|
||||
$this->createCampaignLead($campaign1, $lead);
|
||||
$this->em->flush();
|
||||
$property = ['addTo' => [$campaign2->getId()], 'removeFrom' => ['this']];
|
||||
$this->createEvent('Event', $campaign1, 'campaign.addremovelead', 'action', $property);
|
||||
$this->em->flush();
|
||||
$this->em->clear();
|
||||
|
||||
$this->testSymfonyCommand('mautic:campaigns:trigger', ['--campaign-id' => $campaign1->getId(), '--contact-id' => $lead->getId(), '--kickoff-only' => true]);
|
||||
|
||||
$campaignLeads = $this->em->getRepository(Lead::class)->findBy(['lead' => $lead], ['campaign' => 'ASC']);
|
||||
|
||||
Assert::assertCount(2, $campaignLeads);
|
||||
Assert::assertSame($campaign1->getId(), $campaignLeads[0]->getCampaign()->getId());
|
||||
Assert::assertTrue($campaignLeads[0]->getManuallyRemoved());
|
||||
Assert::assertSame($campaign2->getId(), $campaignLeads[1]->getCampaign()->getId());
|
||||
Assert::assertFalse($campaignLeads[1]->getManuallyRemoved());
|
||||
}
|
||||
|
||||
public function testCampaignActionChangeMembershipRestartRotation(): void
|
||||
{
|
||||
$campaign1 = $this->createCampaign('Campaign 1');
|
||||
// create campaign with restart allowed
|
||||
$campaign2 = $this->createCampaign('Campaign 2');
|
||||
$campaign2->setAllowRestart(true);
|
||||
$this->em->persist($campaign2);
|
||||
|
||||
$lead = $this->createLead('Lead');
|
||||
|
||||
// add lead to both campaigns
|
||||
$this->createCampaignLead($campaign1, $lead);
|
||||
$this->createCampaignLead($campaign2, $lead);
|
||||
$this->em->flush();
|
||||
|
||||
// add action changeCampaigns to add the lead again to campaign2
|
||||
$property = ['addTo' => [$campaign2->getId()], 'removeFrom' => ['this']];
|
||||
$this->createEvent('Event', $campaign1, 'campaign.addremovelead', 'action', $property);
|
||||
$this->em->flush();
|
||||
$this->em->clear();
|
||||
|
||||
$this->testSymfonyCommand('mautic:campaigns:trigger', ['--campaign-id' => $campaign1->getId(), '--contact-id' => $lead->getId(), '--kickoff-only' => true]);
|
||||
|
||||
$campaignLeads = $this->em->getRepository(Lead::class)->findBy(['lead' => $lead], ['campaign' => 'ASC']);
|
||||
|
||||
Assert::assertCount(2, $campaignLeads);
|
||||
Assert::assertSame($campaign1->getId(), $campaignLeads[0]->getCampaign()->getId());
|
||||
Assert::assertTrue($campaignLeads[0]->getManuallyRemoved());
|
||||
Assert::assertSame($campaign2->getId(), $campaignLeads[1]->getCampaign()->getId());
|
||||
Assert::assertFalse($campaignLeads[1]->getManuallyRemoved());
|
||||
Assert::assertSame(2, $campaignLeads[1]->getRotation()); // assert it's the second rotation
|
||||
}
|
||||
|
||||
public function testCampaignActionAfterChangeMembership(): void
|
||||
{
|
||||
$campaign = $this->createCampaign('Campaign 1');
|
||||
$lead = $this->createLead('Lead');
|
||||
$this->createCampaignLead($campaign, $lead);
|
||||
$this->em->flush();
|
||||
$property = ['removeFrom' => ['this']];
|
||||
$event1 = $this->createEvent('Event', $campaign, 'campaign.addremovelead', 'action', $property);
|
||||
$property = ['points' => 1];
|
||||
$event2 = $this->createEvent('Event', $campaign, 'lead.changepoints', 'action', $property);
|
||||
$this->em->flush();
|
||||
$this->em->clear();
|
||||
|
||||
$this->testSymfonyCommand('mautic:campaigns:trigger', ['--campaign-id' => $campaign->getId(), '--contact-id' => $lead->getId(), '--kickoff-only' => true]);
|
||||
|
||||
$campaignLeads = $this->em->getRepository(Lead::class)->findBy(['lead' => $lead]);
|
||||
Assert::assertCount(1, $campaignLeads);
|
||||
Assert::assertSame($campaign->getId(), $campaignLeads[0]->getCampaign()->getId());
|
||||
Assert::assertTrue($campaignLeads[0]->getManuallyRemoved());
|
||||
|
||||
$campaignEventLogs = $this->em->getRepository(LeadEventLog::class)->findBy(['campaign' => $campaign, 'lead' => $lead], ['event' => 'ASC']);
|
||||
Assert::assertCount(1, $campaignEventLogs);
|
||||
Assert::assertSame($campaign->getId(), $campaignEventLogs[0]->getCampaign()->getId());
|
||||
Assert::assertSame($event1->getId(), $campaignEventLogs[0]->getEvent()->getId());
|
||||
}
|
||||
|
||||
public function testCampaignActionBeforeChangeMembership(): void
|
||||
{
|
||||
$campaign = $this->createCampaign('Campaign 1');
|
||||
$lead = $this->createLead('Lead');
|
||||
$this->createCampaignLead($campaign, $lead);
|
||||
$this->em->flush();
|
||||
$property = ['points' => 1];
|
||||
$event1 = $this->createEvent('Event', $campaign, 'lead.changepoints', 'action', $property);
|
||||
$property = ['removeFrom' => ['this']];
|
||||
$event2 = $this->createEvent('Event', $campaign, 'campaign.addremovelead', 'action', $property);
|
||||
$this->em->flush();
|
||||
$this->em->clear();
|
||||
|
||||
$this->testSymfonyCommand('mautic:campaigns:trigger', ['--campaign-id' => $campaign->getId(), '--contact-id' => $lead->getId(), '--kickoff-only' => true]);
|
||||
|
||||
$campaignLeads = $this->em->getRepository(Lead::class)->findBy(['lead' => $lead]);
|
||||
Assert::assertCount(1, $campaignLeads);
|
||||
Assert::assertSame($campaign->getId(), $campaignLeads[0]->getCampaign()->getId());
|
||||
Assert::assertTrue($campaignLeads[0]->getManuallyRemoved());
|
||||
|
||||
$campaignEventLogs = $this->em->getRepository(LeadEventLog::class)->findBy(['campaign' => $campaign, 'lead' => $lead], ['event' => 'ASC']);
|
||||
Assert::assertCount(2, $campaignEventLogs);
|
||||
Assert::assertSame($campaign->getId(), $campaignEventLogs[0]->getCampaign()->getId());
|
||||
Assert::assertSame($event1->getId(), $campaignEventLogs[0]->getEvent()->getId());
|
||||
Assert::assertSame($campaign->getId(), $campaignEventLogs[1]->getCampaign()->getId());
|
||||
Assert::assertSame($event2->getId(), $campaignEventLogs[1]->getEvent()->getId());
|
||||
}
|
||||
|
||||
public function testCampaignExclusion(): void
|
||||
{
|
||||
$campaign1 = $this->createCampaign('Campaign 1');
|
||||
$campaign2 = $this->createCampaign('Campaign 2');
|
||||
$lead = $this->createLead('Lead');
|
||||
$this->createCampaignLead($campaign1, $lead);
|
||||
$this->createCampaignLead($campaign2, $lead);
|
||||
$this->em->flush();
|
||||
$property = ['addTo' => [$campaign2->getId()], 'removeFrom' => ['this']];
|
||||
$this->createEvent('Event', $campaign1, 'campaign.addremovelead', 'action', $property);
|
||||
$this->em->flush();
|
||||
$this->em->clear();
|
||||
|
||||
$this->testSymfonyCommand('mautic:campaigns:trigger', ['--exclude' => [$campaign1->getId()], '--contact-id' => $lead->getId(), '--kickoff-only' => true]);
|
||||
|
||||
$campaignLeads = $this->em->getRepository(Lead::class)->findBy(['lead' => $lead], ['campaign' => 'ASC']);
|
||||
|
||||
Assert::assertCount(2, $campaignLeads);
|
||||
Assert::assertSame($campaign1->getId(), $campaignLeads[0]->getCampaign()->getId());
|
||||
Assert::assertFalse($campaignLeads[0]->getManuallyRemoved(), 'Test not executed campaign does not have Contact removed.');
|
||||
Assert::assertSame($campaign2->getId(), $campaignLeads[1]->getCampaign()->getId());
|
||||
Assert::assertFalse($campaignLeads[1]->getManuallyRemoved());
|
||||
Assert::assertFalse($campaignLeads[1]->getManuallyAdded());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see https://github.com/mautic/mautic/issues/11061
|
||||
*
|
||||
* This test will not fail if the infinite loop returns and instead run indefinitelly until a PHPUNIT timeout is reached.
|
||||
* I couldn't find an easy way to test for an infinite loop. But we'll know if it returns again.
|
||||
* We'll just spend more time figuring out which test is taking so long.
|
||||
*/
|
||||
public function testCampaignInfiniteLoop(): void
|
||||
{
|
||||
$campaignMemberRepo = $this->em->getRepository(Lead::class);
|
||||
|
||||
$segmentMemberRepo = $this->em->getRepository(ListLead::class);
|
||||
|
||||
$campaignRepo = $this->em->getRepository(Campaign::class);
|
||||
|
||||
// Clear the campaign and segment members as those are manually_added.
|
||||
$campaignMemberRepo->deleteEntities($campaignMemberRepo->findAll());
|
||||
$segmentMemberRepo->deleteEntities($segmentMemberRepo->findAll());
|
||||
|
||||
$campaign = $campaignRepo->find(1); // Created in parent::setUp()
|
||||
\assert($campaign instanceof Campaign);
|
||||
|
||||
$campaign->setAllowRestart(true);
|
||||
|
||||
$campaignRepo->saveEntity($campaign);
|
||||
|
||||
$john = $this->createLead('John');
|
||||
$jane = $this->createLead('Jane');
|
||||
$this->createSegmentMember($campaign->getLists()->first(), $john);
|
||||
$this->createSegmentMember($campaign->getLists()->first(), $jane);
|
||||
$this->createCampaignLead($campaign, $john);
|
||||
$this->createCampaignLead($campaign, $jane, true); // Manually removed.
|
||||
$this->em->flush();
|
||||
$this->em->detach($campaign);
|
||||
$this->em->detach($campaignRepo);
|
||||
|
||||
$tStart = microtime(true);
|
||||
|
||||
$this->testSymfonyCommand('mautic:campaigns:update', ['--campaign-id' => $campaign->getId()]);
|
||||
|
||||
$tDiff = microtime(true) - $tStart;
|
||||
|
||||
$this->assertLessThan(10, $tDiff, 'The campaign rebuild takes more than 10 seconds, probably an infinite loop.');
|
||||
}
|
||||
|
||||
public function testCampaignExecuteOrderByDateCreatedDesc(): void
|
||||
{
|
||||
$oldCampaign = $this->createCampaign('Some old campaign');
|
||||
$oldCampaign->setDateAdded(new \DateTime('2019-01-03 03:54:25'));
|
||||
$newCampaign = $this->createCampaign('New campaign');
|
||||
$newCampaign->setDateAdded(new \DateTime());
|
||||
$this->em->flush();
|
||||
|
||||
$commandTester = $this->testSymfonyCommand('mautic:campaigns:trigger');
|
||||
$commandTester->assertCommandIsSuccessful();
|
||||
$lines = preg_split('/\r\n|\r|\n/', $commandTester->getDisplay());
|
||||
|
||||
$campaignStartLines = [];
|
||||
foreach ($lines as $line) {
|
||||
if (str_starts_with($line, 'Triggering events for campaign')) {
|
||||
$campaignStartLines[] = $line;
|
||||
}
|
||||
}
|
||||
|
||||
// check if the new campaign processed first
|
||||
$this->assertEquals("Triggering events for campaign {$newCampaign->getId()}", $campaignStartLines[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function testSegmentCacheCount(): void
|
||||
{
|
||||
// Execute the command again to trigger related events.
|
||||
$this->testSymfonyCommand('mautic:campaigns:trigger', ['-i' => 1]);
|
||||
// Segment cache count should be 50.
|
||||
$count = $this->segmentCountCacheHelper->getSegmentContactCount(1);
|
||||
self::assertEquals(50, $count);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
private function getTagCounts()
|
||||
{
|
||||
$tags = $this->db->createQueryBuilder()
|
||||
->select('t.tag, count(*) as the_count')
|
||||
->from($this->prefix.'lead_tags', 't')
|
||||
->join('t', $this->prefix.'lead_tags_xref', 'l', 't.id = l.tag_id')
|
||||
->groupBy('t.tag')
|
||||
->executeQuery()
|
||||
->fetchAllAssociative();
|
||||
|
||||
$tagCounts = [];
|
||||
foreach ($tags as $tag) {
|
||||
$tagCounts[$tag['tag']] = (int) $tag['the_count'];
|
||||
}
|
||||
|
||||
return $tagCounts;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
private function getNonActionPathTakenCount(array $logs)
|
||||
{
|
||||
$nonActionCount = 0;
|
||||
foreach ($logs as $log) {
|
||||
if ((int) $log['non_action_path_taken']) {
|
||||
++$nonActionCount;
|
||||
}
|
||||
}
|
||||
|
||||
return $nonActionCount;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\CampaignBundle\Tests\Command;
|
||||
|
||||
use Mautic\CampaignBundle\Executioner\InactiveExecutioner;
|
||||
use Mautic\CampaignBundle\Executioner\ScheduledExecutioner;
|
||||
|
||||
class ValidateEventCommandTest extends AbstractCampaignCommand
|
||||
{
|
||||
public function testEventsAreExecutedForInactiveEventWithSingleContact(): void
|
||||
{
|
||||
$this->testSymfonyCommand('mautic:campaigns:trigger', ['-i' => 1, '--contact-id' => 1]);
|
||||
|
||||
// Wait 6 seconds then execute the campaign again to send scheduled events
|
||||
static::getContainer()->get(ScheduledExecutioner::class)->setNowTime(new \DateTime('+'.self::CONDITION_SECONDS.' seconds'));
|
||||
$this->testSymfonyCommand('mautic:campaigns:trigger', ['-i' => 1, '--contact-id' => 1]);
|
||||
|
||||
// No open email decisions should be recorded yet
|
||||
$byEvent = $this->getCampaignEventLogs([3]);
|
||||
$this->assertCount(0, $byEvent[3]);
|
||||
|
||||
// Wait 6 seconds to go beyond the inaction timeframe
|
||||
static::getContainer()->get(InactiveExecutioner::class)->setNowTime(new \DateTime('+'.(self::CONDITION_SECONDS * 2).' seconds'));
|
||||
|
||||
// Now they should be inactive
|
||||
$this->testSymfonyCommand('mautic:campaigns:validate', ['--decision-id' => 3, '--contact-id' => 1]);
|
||||
|
||||
$byEvent = $this->getCampaignEventLogs([3, 7, 10]);
|
||||
$this->assertCount(1, $byEvent[3]); // decision recorded
|
||||
$this->assertCount(1, $byEvent[7]); // inactive event executed
|
||||
$this->assertCount(0, $byEvent[10]); // the positive path should be 0
|
||||
}
|
||||
|
||||
public function testEventsAreExecutedForInactiveEventWithMultipleContact(): void
|
||||
{
|
||||
$this->testSymfonyCommand('mautic:campaigns:trigger', ['-i' => 1, '--contact-ids' => '1,2,3']);
|
||||
|
||||
// Wait 6 seconds then execute the campaign again to send scheduled events
|
||||
static::getContainer()->get(ScheduledExecutioner::class)->setNowTime(new \DateTime('+'.self::CONDITION_SECONDS.' seconds'));
|
||||
$this->testSymfonyCommand('mautic:campaigns:trigger', ['-i' => 1, '--contact-ids' => '1,2,3']);
|
||||
|
||||
// No open email decisions should be recorded yet
|
||||
$byEvent = $this->getCampaignEventLogs([3]);
|
||||
$this->assertCount(0, $byEvent[3]);
|
||||
|
||||
// Wait 6 seconds to go beyond the inaction timeframe
|
||||
static::getContainer()->get(InactiveExecutioner::class)->setNowTime(new \DateTime('+'.(self::CONDITION_SECONDS * 2).' seconds'));
|
||||
|
||||
// Now they should be inactive
|
||||
$this->testSymfonyCommand('mautic:campaigns:validate', ['--decision-id' => 3, '--contact-ids' => '1,2,3']);
|
||||
|
||||
$byEvent = $this->getCampaignEventLogs([3, 7, 10]);
|
||||
$this->assertCount(3, $byEvent[3]); // decision recorded
|
||||
$this->assertCount(3, $byEvent[7]); // inactive event executed
|
||||
$this->assertCount(0, $byEvent[10]); // the positive path should be 0
|
||||
}
|
||||
|
||||
public function testContactsRemovedFromTheCampaignAreNotExecutedForInactiveEvents(): void
|
||||
{
|
||||
$this->testSymfonyCommand('mautic:campaigns:trigger', ['-i' => 1, '--contact-ids' => '1,2,3']);
|
||||
|
||||
// Wait 6 seconds then execute the campaign again to send scheduled events
|
||||
static::getContainer()->get(ScheduledExecutioner::class)->setNowTime(new \DateTime('+'.self::CONDITION_SECONDS.' seconds'));
|
||||
$this->testSymfonyCommand('mautic:campaigns:trigger', ['-i' => 1, '--contact-ids' => '1,2,3']);
|
||||
|
||||
// No open email decisions should be recorded yet
|
||||
$byEvent = $this->getCampaignEventLogs([3]);
|
||||
$this->assertCount(0, $byEvent[3]);
|
||||
|
||||
// Wait 6 seconds to go beyond the inaction timeframe
|
||||
static::getContainer()->get(InactiveExecutioner::class)->setNowTime(new \DateTime('+'.(self::CONDITION_SECONDS * 2).' seconds'));
|
||||
|
||||
// Remove a contact from the campaign
|
||||
$this->db->createQueryBuilder()->update(MAUTIC_TABLE_PREFIX.'campaign_leads')
|
||||
->set('manually_removed', 1)
|
||||
->where('lead_id = 1')
|
||||
->executeStatement();
|
||||
|
||||
// Now they should be inactive
|
||||
$this->testSymfonyCommand('mautic:campaigns:validate', ['--decision-id' => 3, '--contact-ids' => '1,2,3']);
|
||||
|
||||
// Only two contacts should have been considered inactive because one was marked as manually removed
|
||||
$byEvent = $this->getCampaignEventLogs([3, 7, 10]);
|
||||
$this->assertCount(2, $byEvent[3]); // decision recorded
|
||||
$this->assertCount(2, $byEvent[7]); // inactive event executed
|
||||
$this->assertCount(0, $byEvent[10]); // the positive path should be 0
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
INSERT INTO `#__emails` (`headers`, `id`,`category_id`,`translation_parent_id`,`variant_parent_id`,`unsubscribeform_id`,`is_published`,`date_added`,`created_by`,`created_by_user`,`date_modified`,`modified_by`,`modified_by_user`,`checked_out`,`checked_out_by`,`checked_out_by_user`,`name`,`description`,`subject`,`from_address`,`from_name`,`reply_to_address`,`bcc_address`,`template`,`content`,`utm_tags`,`plain_text`,`custom_html`,`email_type`,`publish_up`,`publish_down`,`read_count`,`sent_count`,`revision`,`lang`,`variant_settings`,`variant_start_date`,`dynamic_content`,`variant_sent_count`,`variant_read_count`,`preference_center_id`)
|
||||
VALUES
|
||||
('[]',1,NULL,NULL,NULL,NULL,1,'2018-01-04 21:20:25',1,'Admin',NULL,NULL,NULL,NULL,NULL,NULL,'Campaign Test Email 1',NULL,'Campaign Test Email 1',NULL,NULL,NULL,NULL,'blank','a:0:{}','a:4:{s:9:\"utmSource\";N;s:9:\"utmMedium\";N;s:11:\"utmCampaign\";N;s:10:\"utmContent\";N;}',NULL,'<!DOCTYPE html><html xmlns=\"http://www.w3.org/1999/xhtml\" style=\"\" class=\" js flexbox flexboxlegacy canvas canvastext webgl no-touch geolocation postmessage websqldatabase indexeddb hashchange history draganddrop websockets rgba hsla multiplebgs backgroundsize borderimage borderradius boxshadow textshadow opacity cssanimations csscolumns cssgradients cssreflections csstransforms csstransforms3d csstransitions fontface generatedcontent video audio localstorage sessionstorage webworkers applicationcache svg inlinesvg smil svgclippaths js csstransforms csstransforms3d csstransitions responsejs \"><head>\n <title>{subject}</title>\n <meta name=\"viewport\" content=\"width=device-width,initial-scale=1.0\" />\n <style type=\"text/css\" media=\"only screen and (max-width: 480px)\">\n /* Mobile styles */\n @media only screen and (max-width: 480px) {\n [class=\"w320\"] {\n width: 320px !important;\n }\n [class=\"mobile-block\"] {\n width: 100% !important;\n display: block !important;\n }\n }\n </style>\n </head>\n <body style=\"margin:0\" class=\"ui-sortable\">\n <div data-section-wrapper=\"1\">\n <center>\n <table data-section=\"1\" style=\"width: 600;\" width=\"600\" cellpadding=\"0\" cellspacing=\"0\">\n <tbody>\n <tr>\n <td>\n <div data-slot-container=\"1\" style=\"min-height: 30px\" class=\"ui-sortable\">\n <div data-slot=\"text\">\n <br />\n <h2>Hello there!</h2>\n <br />\n We haven\'t heard from you for a while...\n <br />\n <br />\n {unsubscribe_text} | {webview_text}\n <br />\n </div>\n </div>\n </td>\n </tr>\n </tbody>\n </table>\n </center>\n </div>\n</body></html>','template',NULL,NULL,0,0,1,'en','a:0:{}',NULL,'a:1:{i:0;a:3:{s:9:\"tokenName\";s:17:\"Dynamic Content 1\";s:7:\"content\";s:23:\"Default Dynamic Content\";s:7:\"filters\";a:1:{i:0;a:2:{s:7:\"content\";N;s:7:\"filters\";a:0:{}}}}}',0,0,NULL),
|
||||
('[]',2,NULL,NULL,NULL,NULL,1,'2018-01-04 21:21:07',1,'Admin',NULL,NULL,NULL,NULL,NULL,NULL,'Campaign Test Email 2',NULL,'Campaign Test Email 2',NULL,NULL,NULL,NULL,'blank','a:0:{}','a:4:{s:9:\"utmSource\";N;s:9:\"utmMedium\";N;s:11:\"utmCampaign\";N;s:10:\"utmContent\";N;}',NULL,'<!DOCTYPE html>\n<html>\n <head>\n <title>{subject}</title>\n <meta name=\"viewport\" content=\"width=device-width,initial-scale=1.0\" />\n <style type=\"text/css\" media=\"only screen and (max-width: 480px)\">\n /* Mobile styles */\n @media only screen and (max-width: 480px) {\n\n [class=\"w320\"] {\n width: 320px !important;\n }\n\n [class=\"mobile-block\"] {\n width: 100% !important;\n display: block !important;\n }\n }\n </style>\n </head>\n <body style=\"margin:0\">\n <div data-section-wrapper=\"1\">\n <center>\n <table data-section=\"1\" style=\"width: 600;\" width=\"600\" cellpadding=\"0\" cellspacing=\"0\">\n <tbody>\n <tr>\n <td>\n <div data-slot-container=\"1\" style=\"min-height: 30px\">\n <div data-slot=\"text\">\n <br />\n <h2>Hello there!</h2>\n <br />\n We haven\'t heard from you for a while...\n <br />\n <br />\n {unsubscribe_text} | {webview_text}\n <br />\n </div>\n </div>\n </td>\n </tr>\n </tbody>\n </table>\n </center>\n </div>\n </body>\n</html>','template',NULL,NULL,0,0,1,'en','a:0:{}',NULL,'a:1:{i:0;a:3:{s:9:\"tokenName\";s:17:\"Dynamic Content 1\";s:7:\"content\";s:23:\"Default Dynamic Content\";s:7:\"filters\";a:1:{i:0;a:2:{s:7:\"content\";N;s:7:\"filters\";a:0:{}}}}}',0,0,NULL);
|
||||
|
||||
INSERT INTO `#__lead_tags` (`id`,`tag`)
|
||||
VALUES
|
||||
(1,'CampaignTest'),
|
||||
(2,'US:NotOpen'),
|
||||
(3,'NonUS:NotOpen'),
|
||||
(4,'UK:NotOpen'),
|
||||
(5,'NonUK:NotOpen'),
|
||||
(6,'US:Action'),
|
||||
(7,'NonUS:Action'),
|
||||
(8,'Campaign Test'),
|
||||
(9,'EmailNotOpen'),
|
||||
(10,'ChainedAction');
|
||||
|
||||
INSERT INTO `#__campaigns` (`allow_restart`,`id`,`category_id`,`is_published`,`date_added`,`created_by`,`created_by_user`,`date_modified`,`modified_by`,`modified_by_user`,`checked_out`,`checked_out_by`,`checked_out_by_user`,`name`,`description`,`publish_up`,`publish_down`,`canvas_settings`)
|
||||
VALUES
|
||||
(0, 1, NULL, 1, '2018-01-04 21:41:05', 1, 'Admin', '2018-03-08 23:27:28', 1, 'Admin User', NULL, NULL, 'Admin User', 'Campaign Test', NULL, NULL, NULL, 'a:2:{s:5:\"nodes\";a:16:{i:0;a:3:{s:2:\"id\";s:1:\"1\";s:9:\"positionX\";s:3:\"577\";s:9:\"positionY\";s:3:\"155\";}i:1;a:3:{s:2:\"id\";s:1:\"2\";s:9:\"positionX\";s:3:\"842\";s:9:\"positionY\";s:3:\"164\";}i:2;a:3:{s:2:\"id\";s:1:\"3\";s:9:\"positionX\";s:3:\"842\";s:9:\"positionY\";s:3:\"269\";}i:3;a:3:{s:2:\"id\";s:2:\"11\";s:9:\"positionX\";s:3:\"389\";s:9:\"positionY\";s:3:\"252\";}i:4;a:3:{s:2:\"id\";s:1:\"4\";s:9:\"positionX\";s:4:\"1132\";s:9:\"positionY\";s:3:\"373\";}i:5;a:3:{s:2:\"id\";s:1:\"5\";s:9:\"positionX\";s:3:\"841\";s:9:\"positionY\";s:3:\"378\";}i:6;a:3:{s:2:\"id\";s:2:\"10\";s:9:\"positionX\";s:3:\"597\";s:9:\"positionY\";s:3:\"378\";}i:7;a:3:{s:2:\"id\";s:2:\"12\";s:9:\"positionX\";s:3:\"168\";s:9:\"positionY\";s:3:\"334\";}i:8;a:3:{s:2:\"id\";s:2:\"13\";s:9:\"positionX\";s:3:\"391\";s:9:\"positionY\";s:3:\"335\";}i:9;a:3:{s:2:\"id\";s:2:\"14\";s:9:\"positionX\";s:4:\"1372\";s:9:\"positionY\";s:3:\"364\";}i:10;a:3:{s:2:\"id\";s:1:\"6\";s:9:\"positionX\";s:3:\"649\";s:9:\"positionY\";s:3:\"496\";}i:11;a:3:{s:2:\"id\";s:1:\"7\";s:9:\"positionX\";s:3:\"874\";s:9:\"positionY\";s:3:\"488\";}i:12;a:3:{s:2:\"id\";s:1:\"8\";s:9:\"positionX\";s:4:\"1097\";s:9:\"positionY\";s:3:\"486\";}i:13;a:3:{s:2:\"id\";s:1:\"9\";s:9:\"positionX\";s:4:\"1313\";s:9:\"positionY\";s:3:\"491\";}i:14;a:3:{s:2:\"id\";s:2:\"15\";s:9:\"positionX\";s:4:\"1563\";s:9:\"positionY\";s:3:\"291\";}i:15;a:3:{s:2:\"id\";s:5:\"lists\";s:9:\"positionX\";s:3:\"677\";s:9:\"positionY\";s:2:\"50\";}}s:11:\"connections\";a:15:{i:0;a:3:{s:8:\"sourceId\";s:5:\"lists\";s:8:\"targetId\";s:1:\"1\";s:7:\"anchors\";a:2:{s:6:\"source\";s:10:\"leadsource\";s:6:\"target\";s:3:\"top\";}}i:1;a:3:{s:8:\"sourceId\";s:5:\"lists\";s:8:\"targetId\";s:1:\"2\";s:7:\"anchors\";a:2:{s:6:\"source\";s:10:\"leadsource\";s:6:\"target\";s:3:\"top\";}}i:2;a:3:{s:8:\"sourceId\";s:1:\"2\";s:8:\"targetId\";s:1:\"3\";s:7:\"anchors\";a:2:{s:6:\"source\";s:6:\"bottom\";s:6:\"target\";s:3:\"top\";}}i:3;a:3:{s:8:\"sourceId\";s:1:\"3\";s:8:\"targetId\";s:1:\"4\";s:7:\"anchors\";a:2:{s:6:\"source\";s:2:\"no\";s:6:\"target\";s:3:\"top\";}}i:4;a:3:{s:8:\"sourceId\";s:1:\"3\";s:8:\"targetId\";s:1:\"5\";s:7:\"anchors\";a:2:{s:6:\"source\";s:2:\"no\";s:6:\"target\";s:3:\"top\";}}i:5;a:3:{s:8:\"sourceId\";s:1:\"5\";s:8:\"targetId\";s:1:\"6\";s:7:\"anchors\";a:2:{s:6:\"source\";s:3:\"yes\";s:6:\"target\";s:3:\"top\";}}i:6;a:3:{s:8:\"sourceId\";s:1:\"5\";s:8:\"targetId\";s:1:\"7\";s:7:\"anchors\";a:2:{s:6:\"source\";s:2:\"no\";s:6:\"target\";s:3:\"top\";}}i:7;a:3:{s:8:\"sourceId\";s:1:\"4\";s:8:\"targetId\";s:1:\"8\";s:7:\"anchors\";a:2:{s:6:\"source\";s:3:\"yes\";s:6:\"target\";s:3:\"top\";}}i:8;a:3:{s:8:\"sourceId\";s:1:\"4\";s:8:\"targetId\";s:1:\"9\";s:7:\"anchors\";a:2:{s:6:\"source\";s:2:\"no\";s:6:\"target\";s:3:\"top\";}}i:9;a:3:{s:8:\"sourceId\";s:1:\"3\";s:8:\"targetId\";s:2:\"10\";s:7:\"anchors\";a:2:{s:6:\"source\";s:3:\"yes\";s:6:\"target\";s:3:\"top\";}}i:10;a:3:{s:8:\"sourceId\";s:1:\"1\";s:8:\"targetId\";s:2:\"11\";s:7:\"anchors\";a:2:{s:6:\"source\";s:6:\"bottom\";s:6:\"target\";s:3:\"top\";}}i:11;a:3:{s:8:\"sourceId\";s:2:\"11\";s:8:\"targetId\";s:2:\"12\";s:7:\"anchors\";a:2:{s:6:\"source\";s:3:\"yes\";s:6:\"target\";s:3:\"top\";}}i:12;a:3:{s:8:\"sourceId\";s:2:\"11\";s:8:\"targetId\";s:2:\"13\";s:7:\"anchors\";a:2:{s:6:\"source\";s:2:\"no\";s:6:\"target\";s:3:\"top\";}}i:13;a:3:{s:8:\"sourceId\";s:1:\"3\";s:8:\"targetId\";s:2:\"14\";s:7:\"anchors\";a:2:{s:6:\"source\";s:2:\"no\";s:6:\"target\";s:3:\"top\";}}i:14;a:3:{s:8:\"sourceId\";s:1:\"3\";s:8:\"targetId\";s:2:\"15\";s:7:\"anchors\";a:2:{s:6:\"source\";s:2:\"no\";s:6:\"target\";s:3:\"top\";}}}}');
|
||||
|
||||
INSERT INTO `#__campaign_events` (`id`,`campaign_id`,`parent_id`,`name`,`description`,`type`,`event_type`,`event_order`,`properties`,`trigger_date`,`trigger_interval`,`trigger_interval_unit`,`trigger_mode`,`decision_path`,`temp_id`,`channel`,`channel_id`,`failed_count`)
|
||||
VALUES
|
||||
(1,1,NULL,'Tag CampaignTest',NULL,'lead.changetags','action',1,'a:19:{s:14:\"canvasSettings\";a:2:{s:8:\"droppedX\";s:3:\"577\";s:8:\"droppedY\";s:3:\"155\";}s:4:\"name\";s:0:\"\";s:11:\"triggerMode\";s:9:\"immediate\";s:11:\"triggerDate\";N;s:15:\"triggerInterval\";s:1:\"1\";s:19:\"triggerIntervalUnit\";s:1:\"d\";s:6:\"anchor\";s:10:\"leadsource\";s:10:\"properties\";a:1:{s:8:\"add_tags\";a:1:{i:0;s:1:\"1\";}}s:4:\"type\";s:15:\"lead.changetags\";s:9:\"eventType\";s:6:\"action\";s:15:\"anchorEventType\";s:6:\"source\";s:10:\"campaignId\";s:47:\"mautic_801d9c4d0208e42f6f2bae3f87d0899c3ac45b32\";s:6:\"_token\";s:43:\"uNCD4MZ1GsWRZue4ErJSTW5Tj1CX5R-NYgc5Q_BrVjw\";s:7:\"buttons\";a:1:{s:4:\"save\";s:0:\"\";}s:8:\"settings\";a:4:{s:5:\"label\";s:21:\"Modify contact\'s tags\";s:11:\"description\";s:37:\"Add tag to or remove tag from contact\";s:8:\"formType\";s:16:\"modify_lead_tags\";s:9:\"eventName\";s:38:\"mautic.lead.on_campaign_trigger_action\";}s:6:\"tempId\";s:43:\"new86745ed0771cdfff79549cd84f17e9cc894e8903\";s:2:\"id\";s:43:\"new86745ed0771cdfff79549cd84f17e9cc894e8903\";s:8:\"add_tags\";a:1:{i:0;s:13:\"Campaign Test\";}s:11:\"remove_tags\";a:0:{}}',NULL,1,'d','immediate',NULL,'new86745ed0771cdfff79549cd84f17e9cc894e8903',NULL,NULL,0),
|
||||
(2,1,NULL,'Send email 1',NULL,'email.send','action',1,'a:21:{s:14:\"canvasSettings\";a:2:{s:8:\"droppedX\";s:3:\"337\";s:8:\"droppedY\";s:3:\"155\";}s:4:\"name\";s:0:\"\";s:11:\"triggerMode\";s:4:\"date\";s:11:\"triggerDate\";O:8:\"DateTime\":3:{s:4:\"date\";s:26:\"2018-01-04 15:32:00.000000\";s:13:\"timezone_type\";i:3;s:8:\"timezone\";s:27:\"America/North_Dakota/Center\";}s:15:\"triggerInterval\";s:1:\"1\";s:19:\"triggerIntervalUnit\";s:1:\"d\";s:6:\"anchor\";s:10:\"leadsource\";s:10:\"properties\";a:4:{s:5:\"email\";s:1:\"1\";s:10:\"email_type\";s:13:\"transactional\";s:8:\"priority\";s:1:\"2\";s:8:\"attempts\";s:1:\"3\";}s:4:\"type\";s:10:\"email.send\";s:9:\"eventType\";s:6:\"action\";s:15:\"anchorEventType\";s:6:\"source\";s:10:\"campaignId\";s:47:\"mautic_801d9c4d0208e42f6f2bae3f87d0899c3ac45b32\";s:6:\"_token\";s:43:\"uNCD4MZ1GsWRZue4ErJSTW5Tj1CX5R-NYgc5Q_BrVjw\";s:7:\"buttons\";a:1:{s:4:\"save\";s:0:\"\";}s:8:\"settings\";a:8:{s:5:\"label\";s:10:\"Send email\";s:11:\"description\";s:39:\"Send the selected email to the contact.\";s:9:\"eventName\";s:39:\"mautic.email.on_campaign_trigger_action\";s:8:\"formType\";s:14:\"emailsend_list\";s:15:\"formTypeOptions\";a:2:{s:13:\"update_select\";s:30:\"campaignevent_properties_email\";s:16:\"with_email_types\";b:1;}s:9:\"formTheme\";s:41:\"MauticEmailBundle:FormTheme\\EmailSendList\";s:7:\"channel\";s:5:\"email\";s:14:\"channelIdField\";s:5:\"email\";}s:6:\"tempId\";s:43:\"new8d8d68a07561544b6ae052e1344932e9dcff4f53\";s:2:\"id\";s:43:\"new8d8d68a07561544b6ae052e1344932e9dcff4f53\";s:5:\"email\";s:1:\"1\";s:10:\"email_type\";s:13:\"transactional\";s:8:\"priority\";i:2;s:8:\"attempts\";d:3;}','{SEND_EMAIL_1_TIMESTAMP}',1,'d','date',NULL,'new8d8d68a07561544b6ae052e1344932e9dcff4f53','email',1,0),
|
||||
(3,1,2,'Opens email',NULL,'email.open','decision',2,'a:0:{}',NULL,0,NULL,NULL,NULL,'new7b70bc0bee1752ab041c85806f62e4480d582671',NULL,NULL,0),
|
||||
(4,1,3,'Is UK',NULL,'lead.field_value','condition',3,'a:17:{s:14:\"canvasSettings\";a:2:{s:8:\"droppedX\";s:3:\"942\";s:8:\"droppedY\";s:3:\"374\";}s:4:\"name\";s:5:\"Is UK\";s:11:\"triggerMode\";s:9:\"immediate\";s:11:\"triggerDate\";N;s:15:\"triggerInterval\";s:1:\"1\";s:19:\"triggerIntervalUnit\";s:1:\"d\";s:6:\"anchor\";s:2:\"no\";s:10:\"properties\";a:3:{s:5:\"field\";s:7:\"country\";s:8:\"operator\";s:1:\"=\";s:5:\"value\";s:14:\"United Kingdom\";}s:4:\"type\";s:16:\"lead.field_value\";s:9:\"eventType\";s:9:\"condition\";s:15:\"anchorEventType\";s:8:\"decision\";s:10:\"campaignId\";s:47:\"mautic_801d9c4d0208e42f6f2bae3f87d0899c3ac45b32\";s:6:\"_token\";s:43:\"uNCD4MZ1GsWRZue4ErJSTW5Tj1CX5R-NYgc5Q_BrVjw\";s:7:\"buttons\";a:1:{s:4:\"save\";s:0:\"\";}s:5:\"field\";s:7:\"country\";s:8:\"operator\";s:1:\"=\";s:5:\"value\";s:14:\"United Kingdom\";}','{CONDITION_TIMESTAMP}',1,'d','date','no','new50630b403c8ee496674257bcd8eb739987cb681c',NULL,NULL,0),
|
||||
(5,1,3,'Is US',NULL,'lead.field_value','condition',3,'a:17:{s:14:\"canvasSettings\";a:2:{s:8:\"droppedX\";s:3:\"942\";s:8:\"droppedY\";s:3:\"374\";}s:4:\"name\";s:5:\"Is US\";s:11:\"triggerMode\";s:9:\"immediate\";s:11:\"triggerDate\";N;s:15:\"triggerInterval\";s:1:\"1\";s:19:\"triggerIntervalUnit\";s:1:\"d\";s:6:\"anchor\";s:2:\"no\";s:10:\"properties\";a:3:{s:5:\"field\";s:7:\"country\";s:8:\"operator\";s:1:\"=\";s:5:\"value\";s:13:\"United States\";}s:4:\"type\";s:16:\"lead.field_value\";s:9:\"eventType\";s:9:\"condition\";s:15:\"anchorEventType\";s:8:\"decision\";s:10:\"campaignId\";s:47:\"mautic_801d9c4d0208e42f6f2bae3f87d0899c3ac45b32\";s:6:\"_token\";s:43:\"uNCD4MZ1GsWRZue4ErJSTW5Tj1CX5R-NYgc5Q_BrVjw\";s:7:\"buttons\";a:1:{s:4:\"save\";s:0:\"\";}s:5:\"field\";s:7:\"country\";s:8:\"operator\";s:1:\"=\";s:5:\"value\";s:13:\"United States\";}','{CONDITION_TIMESTAMP}',1,'d','date','no','new7e053fe42a72aadb09dd679698216c5a020fdc9c',NULL,NULL,0),
|
||||
(6,1,5,'Tag US:NotOpen',NULL,'lead.changetags','action',4,'a:16:{s:14:\"canvasSettings\";a:2:{s:8:\"droppedX\";s:3:\"741\";s:8:\"droppedY\";s:3:\"483\";}s:4:\"name\";s:14:\"Tag US:NotOpen\";s:11:\"triggerMode\";s:9:\"immediate\";s:11:\"triggerDate\";N;s:15:\"triggerInterval\";s:1:\"1\";s:19:\"triggerIntervalUnit\";s:1:\"d\";s:6:\"anchor\";s:3:\"yes\";s:10:\"properties\";a:1:{s:8:\"add_tags\";a:1:{i:0;s:1:\"2\";}}s:4:\"type\";s:15:\"lead.changetags\";s:9:\"eventType\";s:6:\"action\";s:15:\"anchorEventType\";s:9:\"condition\";s:10:\"campaignId\";s:47:\"mautic_801d9c4d0208e42f6f2bae3f87d0899c3ac45b32\";s:6:\"_token\";s:43:\"uNCD4MZ1GsWRZue4ErJSTW5Tj1CX5R-NYgc5Q_BrVjw\";s:7:\"buttons\";a:1:{s:4:\"save\";s:0:\"\";}s:8:\"add_tags\";a:1:{i:0;s:10:\"US:NotOpen\";}s:11:\"remove_tags\";a:0:{}}',NULL,1,'d','immediate','yes','new258deb14812923521ffc071e80507c7c173c9bf2',NULL,NULL,0),
|
||||
(7,1,5,'Tag NonUS:NotOpen',NULL,'lead.changetags','action',4,'a:16:{s:14:\"canvasSettings\";a:2:{s:8:\"droppedX\";s:3:\"981\";s:8:\"droppedY\";s:3:\"483\";}s:4:\"name\";s:17:\"Tag NonUS:NotOpen\";s:11:\"triggerMode\";s:9:\"immediate\";s:11:\"triggerDate\";N;s:15:\"triggerInterval\";s:1:\"1\";s:19:\"triggerIntervalUnit\";s:1:\"d\";s:6:\"anchor\";s:2:\"no\";s:10:\"properties\";a:1:{s:8:\"add_tags\";a:1:{i:0;s:1:\"3\";}}s:4:\"type\";s:15:\"lead.changetags\";s:9:\"eventType\";s:6:\"action\";s:15:\"anchorEventType\";s:9:\"condition\";s:10:\"campaignId\";s:47:\"mautic_801d9c4d0208e42f6f2bae3f87d0899c3ac45b32\";s:6:\"_token\";s:43:\"uNCD4MZ1GsWRZue4ErJSTW5Tj1CX5R-NYgc5Q_BrVjw\";s:7:\"buttons\";a:1:{s:4:\"save\";s:0:\"\";}s:8:\"add_tags\";a:1:{i:0;s:13:\"NonUS:NotOpen\";}s:11:\"remove_tags\";a:0:{}}',NULL,1,'d','immediate','no','newa884023f692e4286283972779ee800d590a7c497',NULL,NULL,0),
|
||||
(8,1,4,'Tag UK:NotOpen',NULL,'lead.changetags','action',4,'a:16:{s:14:\"canvasSettings\";a:2:{s:8:\"droppedX\";s:3:\"501\";s:8:\"droppedY\";s:3:\"480\";}s:4:\"name\";s:14:\"Tag UK:NotOpen\";s:11:\"triggerMode\";s:9:\"immediate\";s:11:\"triggerDate\";N;s:15:\"triggerInterval\";s:1:\"1\";s:19:\"triggerIntervalUnit\";s:1:\"d\";s:6:\"anchor\";s:3:\"yes\";s:10:\"properties\";a:1:{s:8:\"add_tags\";a:1:{i:0;s:1:\"4\";}}s:4:\"type\";s:15:\"lead.changetags\";s:9:\"eventType\";s:6:\"action\";s:15:\"anchorEventType\";s:9:\"condition\";s:10:\"campaignId\";s:47:\"mautic_801d9c4d0208e42f6f2bae3f87d0899c3ac45b32\";s:6:\"_token\";s:43:\"uNCD4MZ1GsWRZue4ErJSTW5Tj1CX5R-NYgc5Q_BrVjw\";s:7:\"buttons\";a:1:{s:4:\"save\";s:0:\"\";}s:8:\"add_tags\";a:1:{i:0;s:10:\"UK:NotOpen\";}s:11:\"remove_tags\";a:0:{}}',NULL,1,'d','immediate','yes','new2519374e41eb9686a786cc6cbf4ea8a91e7a3491',NULL,NULL,0),
|
||||
(9,1,4,'Tag NonUK:NotOpen',NULL,'lead.changetags','action',4,'a:16:{s:14:\"canvasSettings\";a:2:{s:8:\"droppedX\";s:4:\"1221\";s:8:\"droppedY\";s:3:\"480\";}s:4:\"name\";s:17:\"Tag NonUK:NotOpen\";s:11:\"triggerMode\";s:9:\"immediate\";s:11:\"triggerDate\";N;s:15:\"triggerInterval\";s:1:\"1\";s:19:\"triggerIntervalUnit\";s:1:\"d\";s:6:\"anchor\";s:2:\"no\";s:10:\"properties\";a:1:{s:8:\"add_tags\";a:1:{i:0;s:1:\"5\";}}s:4:\"type\";s:15:\"lead.changetags\";s:9:\"eventType\";s:6:\"action\";s:15:\"anchorEventType\";s:9:\"condition\";s:10:\"campaignId\";s:47:\"mautic_801d9c4d0208e42f6f2bae3f87d0899c3ac45b32\";s:6:\"_token\";s:43:\"uNCD4MZ1GsWRZue4ErJSTW5Tj1CX5R-NYgc5Q_BrVjw\";s:7:\"buttons\";a:1:{s:4:\"save\";s:0:\"\";}s:8:\"add_tags\";a:1:{i:0;s:13:\"NonUK:NotOpen\";}s:11:\"remove_tags\";a:0:{}}',NULL,1,'d','immediate','no','new41e0645e966bf4d3af3f768e3f57b95574ae1683',NULL,NULL,0),
|
||||
(10,1,3,'Send email 2',NULL,'email.send','action',3,'a:18:{s:14:\"canvasSettings\";a:2:{s:8:\"droppedX\";s:3:\"742\";s:8:\"droppedY\";s:3:\"374\";}s:4:\"name\";s:12:\"Send email 2\";s:11:\"triggerMode\";s:9:\"immediate\";s:11:\"triggerDate\";N;s:15:\"triggerInterval\";s:1:\"1\";s:19:\"triggerIntervalUnit\";s:1:\"d\";s:6:\"anchor\";s:3:\"yes\";s:10:\"properties\";a:4:{s:5:\"email\";s:1:\"2\";s:10:\"email_type\";s:13:\"transactional\";s:8:\"priority\";s:1:\"2\";s:8:\"attempts\";s:1:\"3\";}s:4:\"type\";s:10:\"email.send\";s:9:\"eventType\";s:6:\"action\";s:15:\"anchorEventType\";s:8:\"decision\";s:10:\"campaignId\";s:47:\"mautic_801d9c4d0208e42f6f2bae3f87d0899c3ac45b32\";s:6:\"_token\";s:43:\"uNCD4MZ1GsWRZue4ErJSTW5Tj1CX5R-NYgc5Q_BrVjw\";s:7:\"buttons\";a:1:{s:4:\"save\";s:0:\"\";}s:5:\"email\";s:1:\"2\";s:10:\"email_type\";s:13:\"transactional\";s:8:\"priority\";i:2;s:8:\"attempts\";d:3;}',NULL,1,'d','immediate','yes','new82c4acf5ed2d115566d7a0f27b3a844dc2732211','email',2,0),
|
||||
(11,1,1,'Is US',NULL,'lead.field_value','condition',2,'a:17:{s:14:\"canvasSettings\";a:2:{s:8:\"droppedX\";s:3:\"577\";s:8:\"droppedY\";s:3:\"260\";}s:4:\"name\";s:5:\"Is US\";s:11:\"triggerMode\";s:9:\"immediate\";s:11:\"triggerDate\";N;s:15:\"triggerInterval\";s:1:\"1\";s:19:\"triggerIntervalUnit\";s:1:\"d\";s:6:\"anchor\";s:6:\"bottom\";s:10:\"properties\";a:3:{s:5:\"field\";s:7:\"country\";s:8:\"operator\";s:1:\"=\";s:5:\"value\";s:13:\"United States\";}s:4:\"type\";s:16:\"lead.field_value\";s:9:\"eventType\";s:9:\"condition\";s:15:\"anchorEventType\";s:6:\"action\";s:10:\"campaignId\";s:47:\"mautic_801d9c4d0208e42f6f2bae3f87d0899c3ac45b32\";s:6:\"_token\";s:43:\"uNCD4MZ1GsWRZue4ErJSTW5Tj1CX5R-NYgc5Q_BrVjw\";s:7:\"buttons\";a:1:{s:4:\"save\";s:0:\"\";}s:5:\"field\";s:7:\"country\";s:8:\"operator\";s:1:\"=\";s:5:\"value\";s:13:\"United States\";}',NULL,1,'d','immediate',NULL,'new851108680198a4802062cf78f0d6db86407899a5',NULL,NULL,0),
|
||||
(12,1,11,'Tag US:Action',NULL,'lead.changetags','action',3,'a:16:{s:14:\"canvasSettings\";a:2:{s:8:\"droppedX\";s:2:\"12\";s:8:\"droppedY\";s:3:\"357\";}s:4:\"name\";s:13:\"Tag US:Action\";s:11:\"triggerMode\";s:9:\"immediate\";s:11:\"triggerDate\";N;s:15:\"triggerInterval\";s:1:\"1\";s:19:\"triggerIntervalUnit\";s:1:\"d\";s:6:\"anchor\";s:3:\"yes\";s:10:\"properties\";a:1:{s:8:\"add_tags\";a:1:{i:0;s:1:\"6\";}}s:4:\"type\";s:15:\"lead.changetags\";s:9:\"eventType\";s:6:\"action\";s:15:\"anchorEventType\";s:9:\"condition\";s:10:\"campaignId\";s:47:\"mautic_801d9c4d0208e42f6f2bae3f87d0899c3ac45b32\";s:6:\"_token\";s:43:\"uNCD4MZ1GsWRZue4ErJSTW5Tj1CX5R-NYgc5Q_BrVjw\";s:7:\"buttons\";a:1:{s:4:\"save\";s:0:\"\";}s:8:\"add_tags\";a:1:{i:0;s:9:\"US:Action\";}s:11:\"remove_tags\";a:0:{}}',NULL,1,'d','immediate','yes','new679bfa3e62cb59526de7fd27b556443485a174f0',NULL,NULL,0),
|
||||
(13,1,11,'Tag NonUS:Action',NULL,'lead.changetags','action',3,'a:16:{s:14:\"canvasSettings\";a:2:{s:8:\"droppedX\";s:3:\"489\";s:8:\"droppedY\";s:3:\"357\";}s:4:\"name\";s:16:\"Tag NonUS:Action\";s:11:\"triggerMode\";s:9:\"immediate\";s:11:\"triggerDate\";N;s:15:\"triggerInterval\";s:1:\"1\";s:19:\"triggerIntervalUnit\";s:1:\"d\";s:6:\"anchor\";s:2:\"no\";s:10:\"properties\";a:1:{s:8:\"add_tags\";a:1:{i:0;s:1:\"7\";}}s:4:\"type\";s:15:\"lead.changetags\";s:9:\"eventType\";s:6:\"action\";s:15:\"anchorEventType\";s:9:\"condition\";s:10:\"campaignId\";s:47:\"mautic_801d9c4d0208e42f6f2bae3f87d0899c3ac45b32\";s:6:\"_token\";s:43:\"uNCD4MZ1GsWRZue4ErJSTW5Tj1CX5R-NYgc5Q_BrVjw\";s:7:\"buttons\";a:1:{s:4:\"save\";s:0:\"\";}s:8:\"add_tags\";a:1:{i:0;s:12:\"NonUS:Action\";}s:11:\"remove_tags\";a:0:{}}',NULL,1,'d','immediate','no','new62e190055219ebe5beb9df4c4a505bb0860fffd4',NULL,NULL,0),
|
||||
(14,1,3,'Tag EmailNotOpen',NULL,'lead.changetags','action',3,'a:19:{s:14:\"canvasSettings\";a:2:{s:8:\"droppedX\";s:4:\"1081\";s:8:\"droppedY\";s:3:\"374\";}s:4:\"name\";s:16:\"Tag EmailNotOpen\";s:11:\"triggerMode\";s:8:\"interval\";s:11:\"triggerDate\";N;s:15:\"triggerInterval\";s:1:\"1\";s:19:\"triggerIntervalUnit\";s:1:\"d\";s:6:\"anchor\";s:2:\"no\";s:10:\"properties\";a:1:{s:8:\"add_tags\";a:1:{i:0;s:1:\"9\";}}s:4:\"type\";s:15:\"lead.changetags\";s:9:\"eventType\";s:6:\"action\";s:15:\"anchorEventType\";s:8:\"decision\";s:10:\"campaignId\";s:1:\"1\";s:6:\"_token\";s:43:\"oRiunE5unGEBGhTql8VkzvtTkMHpwElCu5Ul4-_gd-I\";s:7:\"buttons\";a:1:{s:4:\"save\";s:0:\"\";}s:8:\"settings\";a:4:{s:5:\"label\";s:21:\"Modify contact\'s tags\";s:11:\"description\";s:37:\"Add tag to or remove tag from contact\";s:8:\"formType\";s:16:\"modify_lead_tags\";s:9:\"eventName\";s:38:\"mautic.lead.on_campaign_trigger_action\";}s:6:\"tempId\";s:43:\"newb3e5bfd9cdc154619ca0716b46f4a61328688a26\";s:2:\"id\";s:43:\"newb3e5bfd9cdc154619ca0716b46f4a61328688a26\";s:8:\"add_tags\";a:1:{i:0;s:12:\"EmailNotOpen\";}s:11:\"remove_tags\";a:0:{}}',NULL,2,'i','interval','no','newb3e5bfd9cdc154619ca0716b46f4a61328688a26',NULL,NULL,0),
|
||||
(15,1,3,'Tag EmailNotOpen Again',NULL,'lead.changetags','action',3,'a:16:{s:14:\"canvasSettings\";a:2:{s:8:\"droppedX\";s:4:\"1612\";s:8:\"droppedY\";s:3:\"374\";}s:4:\"name\";s:22:\"Tag EmailNotOpen Again\";s:11:\"triggerMode\";s:8:\"interval\";s:11:\"triggerDate\";N;s:15:\"triggerInterval\";s:1:\"6\";s:19:\"triggerIntervalUnit\";s:1:\"i\";s:6:\"anchor\";s:2:\"no\";s:10:\"properties\";a:1:{s:8:\"add_tags\";a:1:{i:0;s:1:\"9\";}}s:4:\"type\";s:15:\"lead.changetags\";s:9:\"eventType\";s:6:\"action\";s:15:\"anchorEventType\";s:8:\"decision\";s:10:\"campaignId\";s:1:\"1\";s:6:\"_token\";s:43:\"Wd8bGtv2HJ6Nyf3K90Efoo2Rn2VkDWwXhwzCIPMiD-M\";s:7:\"buttons\";a:1:{s:4:\"save\";s:0:\"\";}s:8:\"add_tags\";a:1:{i:0;s:12:\"EmailNotOpen\";}s:11:\"remove_tags\";a:0:{}}',NULL,6,'i','interval','no','newf16dfec5f2a65aa9c527675e7be516020a90daa6',NULL,NULL,0),
|
||||
(16,1,12,'Tag ChainedAction',NULL,'lead.changetags','action',4,'a:16:{s:14:\"canvasSettings\";a:2:{s:8:\"droppedX\";s:3:\"168\";s:8:\"droppedY\";s:3:\"439\";}s:4:\"name\";s:14:\"Chained Action\";s:11:\"triggerMode\";s:9:\"immediate\";s:11:\"triggerDate\";N;s:15:\"triggerInterval\";s:1:\"1\";s:19:\"triggerIntervalUnit\";s:1:\"d\";s:6:\"anchor\";s:6:\"bottom\";s:10:\"properties\";a:1:{s:8:\"add_tags\";a:1:{i:0;s:2:\"10\";}}s:4:\"type\";s:15:\"lead.changetags\";s:9:\"eventType\";s:6:\"action\";s:15:\"anchorEventType\";s:6:\"action\";s:10:\"campaignId\";s:1:\"1\";s:6:\"_token\";s:43:\"6xgHe74aRnc1V7AGzdang3-iJ0Ub5BKfbdU5NsxQmv0\";s:7:\"buttons\";a:1:{s:4:\"save\";s:0:\"\";}s:8:\"add_tags\";a:1:{i:0;s:13:\"ChainedAction\";}s:11:\"remove_tags\";a:0:{}}',NULL,1,'d','immediate',NULL,'new60f74507aeccf217f78647e41ae29af51debe666',NULL,NULL,0);
|
||||
|
||||
INSERT INTO `#__lead_lists` (`id`,`is_preference_center`, `is_published`,`date_added`,`created_by`,`created_by_user`,`date_modified`,`modified_by`,`modified_by_user`,`checked_out`,`checked_out_by`,`checked_out_by_user`,`name`,`description`,`alias`,`filters`,`is_global`, `public_name`)
|
||||
VALUES
|
||||
(1,0,1,'2018-01-04 23:41:20',1,'Admin User',NULL,NULL,NULL,NULL,NULL,NULL,'Campaign Test',NULL,'campaign-test','a:0:{}',1,'campaign-test');
|
||||
|
||||
INSERT INTO `#__campaign_leadlist_xref` (`campaign_id`,`leadlist_id`)
|
||||
VALUES
|
||||
(1,1);
|
||||
|
||||
INSERT INTO `#__campaign_leads` (`campaign_id`,`lead_id`,`date_added`,`manually_removed`,`manually_added`,`date_last_exited`,`rotation`)
|
||||
VALUES
|
||||
(1,1,'2018-01-04 22:47:30',0,1,NULL,1),
|
||||
(1,2,'2018-01-04 22:47:30',0,1,NULL,1),
|
||||
(1,3,'2018-01-04 22:47:30',0,1,NULL,1),
|
||||
(1,4,'2018-01-04 22:47:30',0,1,NULL,1),
|
||||
(1,5,'2018-01-04 22:47:30',0,1,NULL,1),
|
||||
(1,6,'2018-01-04 22:47:30',0,1,NULL,1),
|
||||
(1,7,'2018-01-04 22:47:30',0,1,NULL,1),
|
||||
(1,8,'2018-01-04 22:47:30',0,1,NULL,1),
|
||||
(1,9,'2018-01-04 22:47:30',0,1,NULL,1),
|
||||
(1,10,'2018-01-04 22:47:30',0,1,NULL,1),
|
||||
(1,11,'2018-01-04 22:47:30',0,1,NULL,1),
|
||||
(1,12,'2018-01-04 22:47:30',0,1,NULL,1),
|
||||
(1,13,'2018-01-04 22:47:30',0,1,NULL,1),
|
||||
(1,14,'2018-01-04 22:47:30',0,1,NULL,1),
|
||||
(1,15,'2018-01-04 22:47:30',0,1,NULL,1),
|
||||
(1,16,'2018-01-04 22:47:30',0,1,NULL,1),
|
||||
(1,17,'2018-01-04 22:47:30',0,1,NULL,1),
|
||||
(1,18,'2018-01-04 22:47:30',0,1,NULL,1),
|
||||
(1,19,'2018-01-04 22:47:30',0,1,NULL,1),
|
||||
(1,20,'2018-01-04 22:47:30',0,1,NULL,1),
|
||||
(1,21,'2018-01-04 22:47:30',0,1,NULL,1),
|
||||
(1,22,'2018-01-04 22:47:30',0,1,NULL,1),
|
||||
(1,23,'2018-01-04 22:47:30',0,1,NULL,1),
|
||||
(1,24,'2018-01-04 22:47:30',0,1,NULL,1),
|
||||
(1,25,'2018-01-04 22:47:30',0,1,NULL,1),
|
||||
(1,26,'2018-01-04 22:47:30',0,1,NULL,1),
|
||||
(1,27,'2018-01-04 22:47:30',0,1,NULL,1),
|
||||
(1,28,'2018-01-04 22:47:30',0,1,NULL,1),
|
||||
(1,29,'2018-01-04 22:47:30',0,1,NULL,1),
|
||||
(1,30,'2018-01-04 22:47:30',0,1,NULL,1),
|
||||
(1,31,'2018-01-04 22:47:30',0,1,NULL,1),
|
||||
(1,32,'2018-01-04 22:47:30',0,1,NULL,1),
|
||||
(1,33,'2018-01-04 22:47:30',0,1,NULL,1),
|
||||
(1,34,'2018-01-04 22:47:30',0,1,NULL,1),
|
||||
(1,35,'2018-01-04 22:47:30',0,1,NULL,1),
|
||||
(1,36,'2018-01-04 22:47:30',0,1,NULL,1),
|
||||
(1,37,'2018-01-04 22:47:30',0,1,NULL,1),
|
||||
(1,38,'2018-01-04 22:47:30',0,1,NULL,1),
|
||||
(1,39,'2018-01-04 22:47:30',0,1,NULL,1),
|
||||
(1,40,'2018-01-04 22:47:30',0,1,NULL,1),
|
||||
(1,41,'2018-01-04 22:47:30',0,1,NULL,1),
|
||||
(1,42,'2018-01-04 22:47:30',0,1,NULL,1),
|
||||
(1,43,'2018-01-04 22:47:30',0,1,NULL,1),
|
||||
(1,44,'2018-01-04 22:47:30',0,1,NULL,1),
|
||||
(1,45,'2018-01-04 22:47:30',0,1,NULL,1),
|
||||
(1,46,'2018-01-04 22:47:30',0,1,NULL,1),
|
||||
(1,47,'2018-01-04 22:47:30',0,1,NULL,1),
|
||||
(1,48,'2018-01-04 22:47:30',0,1,NULL,1),
|
||||
(1,49,'2018-01-04 22:47:30',0,1,NULL,1),
|
||||
(1,50,'2018-01-04 22:47:30',0,1,NULL,1);
|
||||
|
||||
INSERT INTO `#__lead_lists_leads` (`leadlist_id`,`lead_id`,`date_added`,`manually_removed`,`manually_added`)
|
||||
VALUES
|
||||
(1,1,'2018-01-04 22:47:00',0,1),
|
||||
(1,2,'2018-01-04 22:47:00',0,1),
|
||||
(1,3,'2018-01-04 22:47:00',0,1),
|
||||
(1,4,'2018-01-04 22:47:00',0,1),
|
||||
(1,5,'2018-01-04 22:47:00',0,1),
|
||||
(1,6,'2018-01-04 22:47:00',0,1),
|
||||
(1,7,'2018-01-04 22:47:00',0,1),
|
||||
(1,8,'2018-01-04 22:47:00',0,1),
|
||||
(1,9,'2018-01-04 22:47:00',0,1),
|
||||
(1,10,'2018-01-04 22:47:00',0,1),
|
||||
(1,11,'2018-01-04 22:47:00',0,1),
|
||||
(1,12,'2018-01-04 22:47:00',0,1),
|
||||
(1,13,'2018-01-04 22:47:00',0,1),
|
||||
(1,14,'2018-01-04 22:47:00',0,1),
|
||||
(1,15,'2018-01-04 22:47:00',0,1),
|
||||
(1,16,'2018-01-04 22:47:00',0,1),
|
||||
(1,17,'2018-01-04 22:47:00',0,1),
|
||||
(1,18,'2018-01-04 22:47:00',0,1),
|
||||
(1,19,'2018-01-04 22:47:00',0,1),
|
||||
(1,20,'2018-01-04 22:47:00',0,1),
|
||||
(1,21,'2018-01-04 22:47:00',0,1),
|
||||
(1,22,'2018-01-04 22:47:00',0,1),
|
||||
(1,23,'2018-01-04 22:47:00',0,1),
|
||||
(1,24,'2018-01-04 22:47:00',0,1),
|
||||
(1,25,'2018-01-04 22:47:00',0,1),
|
||||
(1,26,'2018-01-04 22:47:00',0,1),
|
||||
(1,27,'2018-01-04 22:47:00',0,1),
|
||||
(1,28,'2018-01-04 22:47:00',0,1),
|
||||
(1,29,'2018-01-04 22:47:00',0,1),
|
||||
(1,30,'2018-01-04 22:47:00',0,1),
|
||||
(1,31,'2018-01-04 22:47:00',0,1),
|
||||
(1,32,'2018-01-04 22:47:00',0,1),
|
||||
(1,33,'2018-01-04 22:47:00',0,1),
|
||||
(1,34,'2018-01-04 22:47:00',0,1),
|
||||
(1,35,'2018-01-04 22:47:00',0,1),
|
||||
(1,36,'2018-01-04 22:47:00',0,1),
|
||||
(1,37,'2018-01-04 22:47:00',0,1),
|
||||
(1,38,'2018-01-04 22:47:00',0,1),
|
||||
(1,39,'2018-01-04 22:47:00',0,1),
|
||||
(1,40,'2018-01-04 22:47:00',0,1),
|
||||
(1,41,'2018-01-04 22:47:00',0,1),
|
||||
(1,42,'2018-01-04 22:47:00',0,1),
|
||||
(1,43,'2018-01-04 22:47:00',0,1),
|
||||
(1,44,'2018-01-04 22:47:00',0,1),
|
||||
(1,45,'2018-01-04 22:47:00',0,1),
|
||||
(1,46,'2018-01-04 22:47:00',0,1),
|
||||
(1,47,'2018-01-04 22:47:00',0,1),
|
||||
(1,48,'2018-01-04 22:47:00',0,1),
|
||||
(1,49,'2018-01-04 22:47:00',0,1),
|
||||
(1,50,'2018-01-04 22:47:00',0,1);
|
||||
Reference in New Issue
Block a user