Skip to content

Commit

Permalink
feat: [DPMMA-796] Add export lead contact info (mautic#13981)
Browse files Browse the repository at this point in the history
* fix: [DPMMA-796] Add export lead contact info

* fix: [DPMMA-796] Correct tests

* feat: [DPMMA-796] Correct AuditLog exports

* feat: [DPMMA-796] Add functional test

* fix: [DPMMA-796] Add filter Contact Exports
  • Loading branch information
tomekkowalczyk authored Aug 8, 2024
1 parent ce948d1 commit 81bbae3
Show file tree
Hide file tree
Showing 7 changed files with 154 additions and 2 deletions.
1 change: 1 addition & 0 deletions app/bundles/CoreBundle/EventListener/ReportSubscriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ public function onReportBuilder(ReportBuilderEvent $event): void
'dynamicContent' => 'dynamicContent',
'form' => 'form',
'ContactExportScheduler' => 'ContactExportScheduler',
'ContactExports' => 'ContactExports',
'import' => 'import',
'field' => 'field',
'note' => 'note',
Expand Down
13 changes: 13 additions & 0 deletions app/bundles/CoreBundle/Model/IteratorExportDataModel.php
Original file line number Diff line number Diff line change
Expand Up @@ -122,4 +122,17 @@ private function getDataForExport(): void
$this->total += $this->totalResult;
$this->position = 0;
}

public function getTotal(): int
{
return $this->total;
}

/**
* @return array<string, string>
*/
public function getArgs(): array
{
return $this->args;
}
}
27 changes: 25 additions & 2 deletions app/bundles/LeadBundle/Controller/LeadController.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
use Mautic\LeadBundle\Entity\LeadField;
use Mautic\LeadBundle\Entity\LeadRepository;
use Mautic\LeadBundle\Entity\PointsChangeLog;
use Mautic\LeadBundle\Event\ContactExportEvent;
use Mautic\LeadBundle\Event\ContactExportSchedulerEvent;
use Mautic\LeadBundle\Form\Type\BatchType;
use Mautic\LeadBundle\Form\Type\ContactGroupPointsType;
Expand Down Expand Up @@ -1983,6 +1984,8 @@ public function batchOwnersAction(Request $request, $objectId = 0)

/**
* Bulk export contacts.
*
* @throws \Exception
*/
public function batchExportAction(Request $request, ExportHelper $exportHelper, EventDispatcherInterface $dispatcher): Response
{
Expand Down Expand Up @@ -2059,13 +2062,23 @@ public function batchExportAction(Request $request, ExportHelper $exportHelper,

$iterator = new IteratorExportDataModel($model, $args, fn ($contact) => $exportHelper->parseLeadToExport($contact));

return $this->exportResultsAs($iterator, $fileType, 'contacts', $exportHelper);
$response = $this->exportResultsAs($iterator, $fileType, 'contacts', $exportHelper);

$details['total'] = $iterator->getTotal();
$details['args'] = $iterator->getArgs();

$dispatcher->dispatch(
new ContactExportEvent($details, 'ContactExports'),
LeadEvents::POST_CONTACT_EXPORT
);

return $response;
}

/**
* @return array|JsonResponse|\Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\StreamedResponse
*/
public function contactExportAction(Request $request, ExportHelper $exportHelper, $contactId)
public function contactExportAction(Request $request, ExportHelper $exportHelper, EventDispatcherInterface $dispatcher, $contactId)
{
// set some permissions
$permissions = $this->security->isGranted(
Expand All @@ -2092,6 +2105,11 @@ public function contactExportAction(Request $request, ExportHelper $exportHelper
}

$contactFields = $lead->getProfileFields();
$args[] = [
'lead' => $contactId,
'dataType' => $dataType,
];

$export = [];
foreach ($contactFields as $alias => $contactField) {
$export[] = [
Expand All @@ -2100,6 +2118,11 @@ public function contactExportAction(Request $request, ExportHelper $exportHelper
];
}

$dispatcher->dispatch(
new ContactExportEvent($args, 'ContactExport'),
LeadEvents::POST_CONTACT_EXPORT
);

return $this->exportResultsAs($export, $dataType, 'contact_data_'.($contactFields['email'] ?: $contactFields['id']), $exportHelper);
}

Expand Down
32 changes: 32 additions & 0 deletions app/bundles/LeadBundle/Event/ContactExportEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

declare(strict_types=1);

namespace Mautic\LeadBundle\Event;

use Symfony\Contracts\EventDispatcher\Event;

class ContactExportEvent extends Event
{
/**
* @param array<string|int, string|array<string, mixed>> $args
*/
public function __construct(
private array $args,
private string $object
) {
}

/**
* @return array<string, string|array<string, mixed>>
*/
public function getArgs(): array
{
return $this->args;
}

public function getObject(): string
{
return $this->object;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

declare(strict_types=1);

namespace Mautic\LeadBundle\EventListener;

use Mautic\CoreBundle\Helper\IpLookupHelper;
use Mautic\CoreBundle\Model\AuditLogModel;
use Mautic\LeadBundle\Event\ContactExportEvent;
use Mautic\LeadBundle\LeadEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class ContactExportAuditLogSubscriber implements EventSubscriberInterface
{
public function __construct(
private AuditLogModel $auditLogModel,
private IpLookupHelper $ipLookupHelper
) {
}

public static function getSubscribedEvents(): array
{
return [
LeadEvents::POST_CONTACT_EXPORT => 'onContactExport',
];
}

public function onContactExport(ContactExportEvent $event): void
{
$this->auditLogModel->writeToLog(
[
'bundle' => 'lead',
'object' => $event->getObject(),
'objectId' => 0,
'action' => 'create',
'details' => $event->getArgs(),
'ipAddress' => $this->ipLookupHelper->getIpAddressFromRequest(),
]
);
}
}
2 changes: 2 additions & 0 deletions app/bundles/LeadBundle/LeadEvents.php
Original file line number Diff line number Diff line change
Expand Up @@ -782,6 +782,8 @@ final class LeadEvents
*/
public const POST_CONTACT_EXPORT_SCHEDULED = 'mautic.post_contact_export_scheduled';

public const POST_CONTACT_EXPORT = 'mautic.post_contact_export';

/**
* The mautic.contact_export_prepare_file event is dispatched when a contact export is being processed.
*
Expand Down
40 changes: 40 additions & 0 deletions app/bundles/LeadBundle/Tests/Controller/LeadControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -924,4 +924,44 @@ public function testCompanyMergeList(): void
Assert::assertStringContainsString('Company B', $content);
Assert::assertStringNotContainsString('Company A', $content);
}

public function testAuditLogBatchExportContact(): void
{
$this->loadFixtures([LoadLeadData::class]);

ob_start();
$this->client->request(Request::METHOD_GET, '/s/contacts/batchExport?filetype=xlsx');
$content = ob_get_contents();
ob_end_clean();

$clientResponse = $this->client->getResponse();

$this->assertEquals(Response::HTTP_OK, $clientResponse->getStatusCode());
$this->assertEquals($this->client->getInternalResponse()->getHeader('content-type'), 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
$this->assertEquals(true, strlen($content) > 10000);

/** @var AuditLog $auditLog */
$auditLog = $this->em->getRepository(AuditLog::class)->findOneBy([
'object' => 'ContactExports',
'bundle' => 'lead',
'userId' => 1,
'action' => 'create',
]);
$this->assertNotNull($auditLog);
Assert::assertTrue(isset($auditLog->getDetails()['args']), json_encode($auditLog, JSON_PRETTY_PRINT));
Assert::assertSame(
[
'start' => 0,
'limit' => 200,
'filter' => [
'string' => '',
'force' => ' !is:anonymous',
],
'orderBy' => 'l.last_active, l.id',
'orderByDir' => 'DESC',
'withTotalCount' => true,
],
$auditLog->getDetails()['args']
);
}
}

0 comments on commit 81bbae3

Please sign in to comment.