272 lines
8.4 KiB
PHP
Executable File
272 lines
8.4 KiB
PHP
Executable File
<?php
|
|
|
|
namespace Mautic\ChannelBundle\Model;
|
|
|
|
use Doctrine\ORM\EntityManager;
|
|
use Mautic\CampaignBundle\Model\CampaignModel;
|
|
use Mautic\ChannelBundle\ChannelEvents;
|
|
use Mautic\ChannelBundle\Entity\Message;
|
|
use Mautic\ChannelBundle\Entity\MessageRepository;
|
|
use Mautic\ChannelBundle\Event\MessageEvent;
|
|
use Mautic\ChannelBundle\Form\Type\MessageType;
|
|
use Mautic\ChannelBundle\Helper\ChannelListHelper;
|
|
use Mautic\CoreBundle\Helper\CoreParametersHelper;
|
|
use Mautic\CoreBundle\Helper\UserHelper;
|
|
use Mautic\CoreBundle\Model\AjaxLookupModelInterface;
|
|
use Mautic\CoreBundle\Model\FormModel;
|
|
use Mautic\CoreBundle\Model\GlobalSearchInterface;
|
|
use Mautic\CoreBundle\Security\Permissions\CorePermissions;
|
|
use Mautic\CoreBundle\Translation\Translator;
|
|
use Psr\Log\LoggerInterface;
|
|
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
|
use Symfony\Component\Form\FormFactoryInterface;
|
|
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
|
|
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
|
use Symfony\Contracts\EventDispatcher\Event;
|
|
|
|
/**
|
|
* @extends FormModel<Message>
|
|
*
|
|
* @implements AjaxLookupModelInterface<Message>
|
|
*/
|
|
class MessageModel extends FormModel implements AjaxLookupModelInterface, GlobalSearchInterface
|
|
{
|
|
public const CHANNEL_FEATURE = 'marketing_messages';
|
|
|
|
protected static $channels;
|
|
|
|
public function __construct(
|
|
protected ChannelListHelper $channelListHelper,
|
|
protected CampaignModel $campaignModel,
|
|
EntityManager $em,
|
|
CorePermissions $security,
|
|
EventDispatcherInterface $dispatcher,
|
|
UrlGeneratorInterface $router,
|
|
Translator $translator,
|
|
UserHelper $userHelper,
|
|
LoggerInterface $mauticLogger,
|
|
CoreParametersHelper $coreParametersHelper,
|
|
) {
|
|
parent::__construct($em, $security, $dispatcher, $router, $translator, $userHelper, $mauticLogger, $coreParametersHelper);
|
|
}
|
|
|
|
/**
|
|
* @param Message $entity
|
|
* @param bool $unlock
|
|
*/
|
|
public function saveEntity($entity, $unlock = true): void
|
|
{
|
|
$isNew = $entity->isNew();
|
|
|
|
parent::saveEntity($entity, $unlock);
|
|
|
|
if (!$isNew) {
|
|
// Update the channels
|
|
$channels = $entity->getChannels();
|
|
foreach ($channels as $channel) {
|
|
$channel->setMessage($entity);
|
|
}
|
|
$this->getRepository()->saveEntities($channels);
|
|
}
|
|
}
|
|
|
|
public function getPermissionBase(): string
|
|
{
|
|
return 'channel:messages';
|
|
}
|
|
|
|
public function getRepository(): ?MessageRepository
|
|
{
|
|
return $this->em->getRepository(Message::class);
|
|
}
|
|
|
|
public function getEntity($id = null): ?Message
|
|
{
|
|
if (null === $id) {
|
|
return new Message();
|
|
}
|
|
|
|
return parent::getEntity($id);
|
|
}
|
|
|
|
/**
|
|
* @param object $entity
|
|
* @param array $options
|
|
*
|
|
* @return \Symfony\Component\Form\FormInterface<mixed>
|
|
*/
|
|
public function createForm($entity, FormFactoryInterface $formFactory, $action = null, $options = []): \Symfony\Component\Form\FormInterface
|
|
{
|
|
if (!empty($action)) {
|
|
$options['action'] = $action;
|
|
}
|
|
|
|
return $formFactory->create(MessageType::class, $entity, $options);
|
|
}
|
|
|
|
/**
|
|
* @return array
|
|
*/
|
|
public function getChannels()
|
|
{
|
|
if (!self::$channels) {
|
|
$channels = $this->channelListHelper->getFeatureChannels(self::CHANNEL_FEATURE);
|
|
|
|
// Validate channel configs
|
|
foreach ($channels as $channel => $config) {
|
|
if (!isset($config['lookupFormType']) && !isset($config['propertiesFormType'])) {
|
|
throw new \InvalidArgumentException('lookupFormType and/or propertiesFormType are required for channel '.$channel);
|
|
}
|
|
|
|
$label = match (true) {
|
|
$this->translator->hasId('mautic.channel.'.$channel) => $this->translator->trans('mautic.channel.'.$channel),
|
|
$this->translator->hasId('mautic.'.$channel) => $this->translator->trans('mautic.'.$channel),
|
|
$this->translator->hasId('mautic.'.$channel.'.'.$channel) => $this->translator->trans('mautic.'.$channel.'.'.$channel),
|
|
default => ucfirst($channel),
|
|
};
|
|
$config['label'] = $label;
|
|
|
|
$channels[$channel] = $config;
|
|
}
|
|
|
|
self::$channels = $channels;
|
|
}
|
|
|
|
return self::$channels;
|
|
}
|
|
|
|
/**
|
|
* @param string $filter
|
|
* @param int $limit
|
|
* @param int $start
|
|
* @param array $options
|
|
*/
|
|
public function getLookupResults($type, $filter = '', $limit = 10, $start = 0, $options = []): array
|
|
{
|
|
$results = [];
|
|
switch ($type) {
|
|
case 'channel.message':
|
|
$entities = $this->getRepository()->getMessageList(
|
|
$filter,
|
|
$limit,
|
|
$start
|
|
);
|
|
|
|
foreach ($entities as $entity) {
|
|
$results[] = [
|
|
'label' => $entity['name'],
|
|
'value' => $entity['id'],
|
|
];
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
return $results;
|
|
}
|
|
|
|
public function getMessageChannels($messageId): array
|
|
{
|
|
return $this->getRepository()->getMessageChannels($messageId);
|
|
}
|
|
|
|
/**
|
|
* @return array
|
|
*/
|
|
public function getChannelMessageByChannelId($channelId)
|
|
{
|
|
return $this->getRepository()->getChannelMessageByChannelId($channelId);
|
|
}
|
|
|
|
public function getLeadStatsPost($messageId, $dateFrom = null, $dateTo = null, $channel = null): array
|
|
{
|
|
$eventLog = $this->campaignModel->getCampaignLeadEventLogRepository();
|
|
|
|
return $eventLog->getChartQuery(
|
|
[
|
|
'type' => 'message.send',
|
|
'dateFrom' => $dateFrom,
|
|
'dateTo' => $dateTo,
|
|
'channel' => 'channel.message',
|
|
'channelId' => $messageId,
|
|
'logChannel' => $channel,
|
|
]
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @return mixed
|
|
*/
|
|
public function getMarketingMessagesEventLogs($messageId, $dateFrom = null, $dateTo = null)
|
|
{
|
|
$eventLog = $this->campaignModel->getCampaignLeadEventLogRepository();
|
|
|
|
return $eventLog->getEventLogs(['type' => 'message.send', 'dateFrom' => $dateFrom, 'dateTo' => $dateTo, 'channel' => 'message', 'channelId' => $messageId]);
|
|
}
|
|
|
|
/**
|
|
* Get the channel name from the database.
|
|
*
|
|
* @template T of object
|
|
*
|
|
* @param int $id
|
|
* @param class-string<T> $entityName
|
|
* @param string $nameColumn
|
|
*
|
|
* @return string|null
|
|
*/
|
|
public function getChannelName($id, $entityName, $nameColumn = 'name')
|
|
{
|
|
if (!$id || !$entityName || !$nameColumn) {
|
|
return null;
|
|
}
|
|
|
|
$repo = $this->em->getRepository($entityName);
|
|
$qb = $repo->createQueryBuilder('e')
|
|
->select('e.'.$nameColumn)
|
|
->where('e.id = :id')
|
|
->setParameter('id', (int) $id);
|
|
$result = $qb->getQuery()->getOneOrNullResult();
|
|
|
|
return $result[$nameColumn] ?? null;
|
|
}
|
|
|
|
/**
|
|
* @throws MethodNotAllowedHttpException
|
|
*/
|
|
protected function dispatchEvent($action, &$entity, $isNew = false, ?Event $event = null): ?Event
|
|
{
|
|
if (!$entity instanceof Message) {
|
|
throw new MethodNotAllowedHttpException(['Message']);
|
|
}
|
|
|
|
switch ($action) {
|
|
case 'pre_save':
|
|
$name = ChannelEvents::MESSAGE_PRE_SAVE;
|
|
break;
|
|
case 'post_save':
|
|
$name = ChannelEvents::MESSAGE_POST_SAVE;
|
|
break;
|
|
case 'pre_delete':
|
|
$name = ChannelEvents::MESSAGE_PRE_DELETE;
|
|
break;
|
|
case 'post_delete':
|
|
$name = ChannelEvents::MESSAGE_POST_DELETE;
|
|
break;
|
|
default:
|
|
return null;
|
|
}
|
|
|
|
if ($this->dispatcher->hasListeners($name)) {
|
|
if (empty($event)) {
|
|
$event = new MessageEvent($entity, $isNew);
|
|
}
|
|
$this->dispatcher->dispatch($event, $name);
|
|
|
|
return $event;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|