Spaces:
No application file
No application file
| namespace Mautic\CampaignBundle\Entity; | |
| use Doctrine\DBAL\ArrayParameterType; | |
| use Mautic\CoreBundle\Entity\CommonRepository; | |
| /** | |
| * @extends CommonRepository<Event> | |
| */ | |
| class EventRepository extends CommonRepository | |
| { | |
| /** | |
| * Get a list of entities. | |
| * | |
| * @param mixed[] $args | |
| * | |
| * @return \Doctrine\ORM\Tools\Pagination\Paginator<object>|object[]|mixed[] | |
| */ | |
| public function getEntities(array $args = []) | |
| { | |
| $select = 'e'; | |
| $q = $this | |
| ->createQueryBuilder('e') | |
| ->join('e.campaign', 'c'); | |
| if (!empty($args['campaign_id'])) { | |
| $q->andWhere( | |
| $q->expr()->eq('IDENTITY(e.campaign)', (int) $args['campaign_id']) | |
| ); | |
| } | |
| if (empty($args['ignore_children'])) { | |
| $select .= ', ec, ep'; | |
| $q->leftJoin('e.children', 'ec') | |
| ->leftJoin('e.parent', 'ep'); | |
| } | |
| $q->select($select); | |
| $args['qb'] = $q; | |
| return parent::getEntities($args); | |
| } | |
| /** | |
| * @param int $contactId | |
| * @param string $type | |
| * | |
| * @return array | |
| */ | |
| public function getContactPendingEvents($contactId, $type) | |
| { | |
| // Limit to events that hasn't been executed or scheduled yet | |
| $eventQb = $this->getEntityManager()->createQueryBuilder(); | |
| $eventQb->select('IDENTITY(log_event.event)') | |
| ->from(LeadEventLog::class, 'log_event') | |
| ->where( | |
| $eventQb->expr()->andX( | |
| $eventQb->expr()->eq('log_event.event', 'e'), | |
| $eventQb->expr()->eq('log_event.lead', 'l.lead'), | |
| $eventQb->expr()->eq('log_event.rotation', 'l.rotation') | |
| ) | |
| ); | |
| // Limit to events that has no parent or whose parent has already been executed | |
| $parentQb = $this->getEntityManager()->createQueryBuilder(); | |
| $parentQb->select('parent_log_event.id') | |
| ->from(LeadEventLog::class, 'parent_log_event') | |
| ->where( | |
| $parentQb->expr()->eq('parent_log_event.event', 'e.parent'), | |
| $parentQb->expr()->eq('parent_log_event.lead', 'l.lead'), | |
| $parentQb->expr()->eq('parent_log_event.rotation', 'l.rotation'), | |
| $parentQb->expr()->eq('parent_log_event.isScheduled', 0) | |
| ); | |
| $q = $this->createQueryBuilder('e', 'e.id'); | |
| $q->select('e,c') | |
| ->innerJoin('e.campaign', 'c') | |
| ->innerJoin('c.leads', 'l') | |
| ->where( | |
| $q->expr()->andX( | |
| $q->expr()->eq('c.isPublished', 1), | |
| $q->expr()->isNull('c.deleted'), | |
| $q->expr()->eq('e.type', ':type'), | |
| $q->expr()->isNull('e.deleted'), | |
| $q->expr()->eq('IDENTITY(l.lead)', ':contactId'), | |
| $q->expr()->eq('l.manuallyRemoved', 0), | |
| $q->expr()->notIn('e.id', $eventQb->getDQL()), | |
| $q->expr()->orX( | |
| $q->expr()->isNull('e.parent'), | |
| $q->expr()->exists($parentQb->getDQL()) | |
| ) | |
| ) | |
| ) | |
| ->setParameter('type', $type) | |
| ->setParameter('contactId', (int) $contactId); | |
| return $q->getQuery()->getResult(); | |
| } | |
| /** | |
| * Get array of events by parent. | |
| * | |
| * @param int $parentId | |
| * @param string|null $decisionPath | |
| * @param string|null $eventType | |
| * | |
| * @return array | |
| */ | |
| public function getEventsByParent($parentId, $decisionPath = null, $eventType = null) | |
| { | |
| $q = $this->getEntityManager()->createQueryBuilder(); | |
| $q->select('e') | |
| ->from(Event::class, 'e', 'e.id') | |
| ->where( | |
| $q->expr()->eq('IDENTITY(e.parent)', (int) $parentId) | |
| ); | |
| if (null !== $decisionPath) { | |
| $q->andWhere( | |
| $q->expr()->eq('e.decisionPath', ':decisionPath') | |
| ) | |
| ->setParameter('decisionPath', $decisionPath); | |
| } | |
| if (null !== $eventType) { | |
| $q->andWhere( | |
| $q->expr()->eq('e.eventType', ':eventType') | |
| ) | |
| ->setParameter('eventType', $eventType); | |
| } | |
| return $q->getQuery()->getArrayResult(); | |
| } | |
| /** | |
| * @param int $campaignId | |
| * @param bool $ignoreDeleted | |
| * | |
| * @return array<int,mixed[]> | |
| */ | |
| public function getCampaignEvents($campaignId, $ignoreDeleted = true): array | |
| { | |
| $q = $this->getEntityManager()->createQueryBuilder(); | |
| $q->select('e, IDENTITY(e.parent)') | |
| ->from(Event::class, 'e', 'e.id') | |
| ->where( | |
| $q->expr()->eq('IDENTITY(e.campaign)', (int) $campaignId) | |
| ) | |
| ->orderBy('e.order', \Doctrine\Common\Collections\Criteria::ASC); | |
| if ($ignoreDeleted) { | |
| $q->andWhere($q->expr()->isNull('e.deleted')); | |
| } | |
| $results = $q->getQuery()->getArrayResult(); | |
| // Fix the parent ID | |
| $events = []; | |
| foreach ($results as $id => $r) { | |
| $r[0]['parent_id'] = $r[1]; | |
| $events[$id] = $r[0]; | |
| } | |
| unset($results); | |
| return $events; | |
| } | |
| /** | |
| * @return string[] | |
| */ | |
| public function getCampaignEventIds(int $campaignId): array | |
| { | |
| $q = $this->getEntityManager()->getConnection()->createQueryBuilder(); | |
| $q->select('e.id') | |
| ->from(MAUTIC_TABLE_PREFIX.Event::TABLE_NAME, 'e') | |
| ->where($q->expr()->eq('e.campaign_id', $campaignId)); | |
| return array_column($q->executeQuery()->fetchAllAssociative(), 'id'); | |
| } | |
| /** | |
| * Get array of events with stats. | |
| * | |
| * @param array $args | |
| * | |
| * @return array | |
| */ | |
| public function getEvents($args = []) | |
| { | |
| $q = $this->createQueryBuilder('e') | |
| ->select('e, ec, ep') | |
| ->join('e.campaign', 'c') | |
| ->leftJoin('e.children', 'ec') | |
| ->leftJoin('e.parent', 'ep') | |
| ->orderBy('e.order'); | |
| if (!empty($args['campaigns'])) { | |
| $q->andWhere($q->expr()->in('e.campaign', ':campaigns')) | |
| ->setParameter('campaigns', $args['campaigns']); | |
| } | |
| if (isset($args['positivePathOnly'])) { | |
| $q->andWhere( | |
| $q->expr()->orX( | |
| $q->expr()->neq( | |
| 'e.decisionPath', | |
| $q->expr()->literal('no') | |
| ), | |
| $q->expr()->isNull('e.decisionPath') | |
| ) | |
| ); | |
| } | |
| return $q->getQuery()->getArrayResult(); | |
| } | |
| /** | |
| * Null event parents in preparation for deleI'lting a campaign. | |
| * | |
| * @param int $campaignId | |
| */ | |
| public function nullEventParents($campaignId): void | |
| { | |
| $this->getEntityManager()->getConnection()->update( | |
| MAUTIC_TABLE_PREFIX.'campaign_events', | |
| ['parent_id' => null], | |
| ['campaign_id' => (int) $campaignId] | |
| ); | |
| } | |
| /** | |
| * Null event parents in preparation for deleting events from a campaign. | |
| * | |
| * @param string[] $events | |
| */ | |
| public function nullEventRelationships($events): void | |
| { | |
| $qb = $this->getEntityManager()->getConnection()->createQueryBuilder(); | |
| $qb->update(MAUTIC_TABLE_PREFIX.'campaign_events') | |
| ->set('parent_id', ':null') | |
| ->setParameter('null', null) | |
| ->where( | |
| $qb->expr()->in('parent_id', $events) | |
| ) | |
| ->executeStatement(); | |
| } | |
| /** | |
| * @param string[] $eventIds | |
| */ | |
| public function deleteEvents(array $eventIds): void | |
| { | |
| $qb = $this->getEntityManager()->createQueryBuilder(); | |
| $qb->delete(Event::class, 'e') | |
| ->where($qb->expr()->in('e.id', ':event_ids')) | |
| ->setParameter('event_ids', $eventIds, ArrayParameterType::INTEGER) | |
| ->getQuery() | |
| ->execute(); | |
| } | |
| /** | |
| * @param string[] $eventIds | |
| */ | |
| public function setEventsAsDeleted(array $eventIds): void | |
| { | |
| $dateTime = (new \DateTime())->format('Y-m-d H:i:s'); | |
| $qb = $this->getEntityManager()->getConnection()->createQueryBuilder(); | |
| $qb->update(MAUTIC_TABLE_PREFIX.Event::TABLE_NAME) | |
| ->set('deleted', ':deleted') | |
| ->setParameter('deleted', $dateTime) | |
| ->where( | |
| $qb->expr()->in('id', $eventIds) | |
| ) | |
| ->executeStatement(); | |
| } | |
| public function getTableAlias(): string | |
| { | |
| return 'e'; | |
| } | |
| /** | |
| * For the API. | |
| * | |
| * @return string[] | |
| */ | |
| public function getSearchCommands(): array | |
| { | |
| return $this->getStandardSearchCommands(); | |
| } | |
| /** | |
| * @param string $eventType | |
| */ | |
| public function getEventsByChannel($channel, $campaignId = null, $eventType = 'action') | |
| { | |
| $q = $this->getEntityManager()->createQueryBuilder(); | |
| $q->select('e') | |
| ->from(Event::class, 'e', 'e.id') | |
| ->where('e.channel = :channel') | |
| ->setParameter('channel', $channel); | |
| if ($campaignId) { | |
| $q->andWhere('IDENTITY(e.campaign) = :campaignId') | |
| ->setParameter('campaignId', $campaignId) | |
| ->orderBy('e.order'); | |
| } | |
| if ($eventType) { | |
| $q->andWhere('e.eventType', ':eventType') | |
| ->setParameter('eventType', $eventType); | |
| } | |
| return $q->getQuery()->getResult(); | |
| } | |
| /** | |
| * Get an array of events that have been triggered by this lead. | |
| */ | |
| public function getLeadTriggeredEvents($leadId): array | |
| { | |
| $q = $this->getEntityManager()->createQueryBuilder() | |
| ->select('e, c, l') | |
| ->from(Event::class, 'e') | |
| ->join('e.campaign', 'c') | |
| ->join('e.log', 'l'); | |
| // make sure the published up and down dates are good | |
| $q->where($q->expr()->eq('IDENTITY(l.lead)', (int) $leadId)); | |
| $results = $q->getQuery()->getArrayResult(); | |
| $return = []; | |
| foreach ($results as $r) { | |
| $return[$r['id']] = $r; | |
| } | |
| return $return; | |
| } | |
| /** | |
| * {@inheritdoc} | |
| * | |
| * For the API | |
| */ | |
| protected function addCatchAllWhereClause($q, $filter): array | |
| { | |
| return $this->addStandardCatchAllWhereClause( | |
| $q, | |
| $filter, | |
| [ | |
| $this->getTableAlias().'.name', | |
| ] | |
| ); | |
| } | |
| /** | |
| * {@inheritdoc} | |
| * | |
| * For the API | |
| */ | |
| protected function addSearchCommandWhereClause($q, $filter): array | |
| { | |
| return $this->addStandardSearchCommandWhereClause($q, $filter); | |
| } | |
| /** | |
| * Update the failed count using DBAL to avoid | |
| * race conditions and deadlocks. | |
| */ | |
| public function incrementFailedCount(Event $event): int | |
| { | |
| $q = $this->_em->getConnection()->createQueryBuilder(); | |
| $q->update(MAUTIC_TABLE_PREFIX.'campaign_events') | |
| ->set('failed_count', 'failed_count + 1') | |
| ->where($q->expr()->eq('id', ':id')) | |
| ->setParameter('id', $event->getId()); | |
| $q->executeStatement(); | |
| return $this->getFailedCount($event); | |
| } | |
| /** | |
| * Get the up to date failed count | |
| * for the given Event. | |
| */ | |
| public function getFailedCount(Event $event): int | |
| { | |
| $q = $this->_em->getConnection()->createQueryBuilder(); | |
| $q->select('failed_count') | |
| ->from(MAUTIC_TABLE_PREFIX.'campaign_events') | |
| ->where($q->expr()->eq('id', ':id')) | |
| ->setParameter('id', $event->getId()); | |
| return (int) $q->executeQuery()->fetchOne(); | |
| } | |
| /** | |
| * Reset the failed_count's for all events | |
| * within the given Campaign. | |
| */ | |
| public function resetFailedCountsForEventsInCampaign(Campaign $campaign): void | |
| { | |
| $q = $this->_em->getConnection()->createQueryBuilder(); | |
| $q->update(MAUTIC_TABLE_PREFIX.'campaign_events') | |
| ->set('failed_count', ':failedCount') | |
| ->where($q->expr()->eq('campaign_id', ':campaignId')) | |
| ->setParameter('failedCount', 0) | |
| ->setParameter('campaignId', $campaign->getId()); | |
| $q->executeStatement(); | |
| } | |
| } | |