/**
  * @param \DateTime        $value
  * @param AbstractPlatform $platform
  *
  * @return string|null
  */
 public function convertToDatabaseValue($value, AbstractPlatform $platform)
 {
     if ($value === null) {
         return null;
     }
     if (!self::$utc) {
         self::$utc = new \DateTimeZone('UTC');
     }
     if (!is_object($value)) {
         $dateHelper = new DateTimeHelper($value);
         $value = $dateHelper->getDateTime();
     }
     $tz = $value->getTimeZone();
     $utcDatetime = new \DateTime($value->format($platform->getDateTimeFormatString()), $tz);
     $utcDatetime->setTimezone(self::$utc);
     return $utcDatetime->format($platform->getDateTimeFormatString());
 }
Example #2
0
 /**
  * {@inheritdoc}
  *
  * @param \Mautic\LeadBundle\Entity\Lead &$entity
  * @param                                $parameters
  * @param                                $form
  * @param string                         $action
  */
 protected function preSaveEntity(&$entity, $form, $parameters, $action = 'edit')
 {
     //Since the request can be from 3rd party, check for an IP address if included
     if (isset($parameters['ipAddress'])) {
         $ip = $parameters['ipAddress'];
         unset($parameters['ipAddress']);
         $ipAddress = $this->factory->getIpAddress($ip);
         if (!$entity->getIpAddresses()->contains($ipAddress)) {
             $entity->addIpAddress($ipAddress);
         }
     }
     // Check for tag string
     if (isset($parameters['tags'])) {
         $this->model->modifyTags($entity, $parameters['tags']);
         unset($parameters['tags']);
     }
     if (isset($parameters['companies'])) {
         $this->model->modifyCompanies($entity, $parameters['companies']);
         unset($parameters['companies']);
     }
     // Check for lastActive date
     if (isset($parameters['lastActive'])) {
         $lastActive = new DateTimeHelper($parameters['lastActive']);
         $entity->setLastActive($lastActive->getDateTime());
     }
     //set the custom field values
     //pull the data from the form in order to apply the form's formatting
     foreach ($form as $f) {
         $parameters[$f->getName()] = $f->getData();
     }
     $this->model->setFieldValues($entity, $parameters, true);
 }
Example #3
0
 /**
  * Fetch the events.
  *
  * @return array Events sorted by timestamp with most recent event first
  */
 public function getEvents()
 {
     if (empty($this->events)) {
         return [];
     }
     $events = call_user_func_array('array_merge', $this->events);
     foreach ($events as &$e) {
         if (!$e['timestamp'] instanceof \DateTime) {
             $dt = new DateTimeHelper($e['timestamp'], 'Y-m-d H:i:s', 'UTC');
             $e['timestamp'] = $dt->getDateTime();
             unset($dt);
         }
     }
     if (!empty($this->orderBy)) {
         usort($events, function ($a, $b) {
             switch ($this->orderBy[0]) {
                 case 'eventLabel':
                     $aLabel = '';
                     if (isset($a['eventLabel'])) {
                         $aLabel = is_array($a['eventLabel']) ? $a['eventLabel']['label'] : $a['eventLabel'];
                     }
                     $bLabel = '';
                     if (isset($b['eventLabel'])) {
                         $bLabel = is_array($b['eventLabel']) ? $b['eventLabel']['label'] : $b['eventLabel'];
                     }
                     return strnatcmp($aLabel, $bLabel);
                 case 'timestamp':
                     if ($a['timestamp'] == $b['timestamp']) {
                         $aPriority = isset($a['eventPriority']) ? (int) $a['eventPriority'] : 0;
                         $bPriority = isset($b['eventPriority']) ? (int) $b['eventPriority'] : 0;
                         return $aPriority - $bPriority;
                     }
                     return $a['timestamp'] < $b['timestamp'] ? -1 : 1;
             }
         });
         if ($this->orderBy[1] == 'DESC') {
             $events = array_reverse($events);
         }
     }
     return $events;
 }
 /**
  * Fetch the events
  *
  * @return array Events sorted by timestamp with most recent event first
  */
 public function getEvents($returnGrouped = false)
 {
     $events = $this->events;
     $byDate = array();
     // Group by date
     foreach ($events as $e) {
         if (!$e['timestamp'] instanceof \DateTime) {
             $dt = new DateTimeHelper($e['timestamp'], 'Y-m-d H:i:s', 'UTC');
             $e['timestamp'] = $dt->getDateTime();
             unset($dt);
         }
         $dateString = $e['timestamp']->format('Y-m-d H:i');
         if (!isset($byDate[$dateString])) {
             $byDate[$dateString] = array();
         }
         $byDate[$dateString][] = $e;
     }
     // Sort by date
     krsort($byDate);
     // Sort by certain event actions
     $order = array('lead.ipadded', 'page.hit', 'form.submitted', 'asset.download', 'lead.merge', 'lead.create', 'lead.identified');
     $events = array();
     foreach ($byDate as $date => $dateEvents) {
         usort($dateEvents, function ($a, $b) use($order) {
             if (!in_array($a['event'], $order) || !in_array($b['event'], $order)) {
                 // No specific order so push to the end
                 return 1;
             }
             $pos_a = array_search($a['event'], $order);
             $pos_b = array_search($b['event'], $order);
             return $pos_a - $pos_b;
         });
         $byDate[$date] = $dateEvents;
         $events = array_merge($events, array_reverse($dateEvents));
     }
     return $returnGrouped ? $byDate : $events;
 }
Example #5
0
 /**
  * @param string|Stat $stat
  * @param             $request
  * @param bool        $viaBrowser
  */
 public function hitEmail($stat, $request, $viaBrowser = false)
 {
     if (!$stat instanceof Stat) {
         $stat = $this->getEmailStatus($stat);
     }
     if (!$stat) {
         return;
     }
     $email = $stat->getEmail();
     if ((int) $stat->isRead()) {
         if ($viaBrowser && !$stat->getViewedInBrowser()) {
             //opened via browser so note it
             $stat->setViewedInBrowser($viaBrowser);
         }
     }
     $readDateTime = new DateTimeHelper();
     $stat->setLastOpened($readDateTime->getDateTime());
     $lead = $stat->getLead();
     if ($lead !== null) {
         // Set the lead as current lead
         $this->leadModel->setCurrentLead($lead);
     }
     $firstTime = false;
     if (!$stat->getIsRead()) {
         $firstTime = true;
         $stat->setIsRead(true);
         $stat->setDateRead($readDateTime->getDateTime());
         // Only up counts if associated with both an email and lead
         if ($email && $lead) {
             try {
                 $this->getRepository()->upCount($email->getId(), 'read', 1, $email->isVariant());
             } catch (\Exception $exception) {
                 error_log($exception);
             }
         }
     }
     if ($viaBrowser) {
         $stat->setViewedInBrowser($viaBrowser);
     }
     $stat->addOpenDetails(['datetime' => $readDateTime->toUtcString(), 'useragent' => $request->server->get('HTTP_USER_AGENT'), 'inBrowser' => $viaBrowser]);
     //check for existing IP
     $ipAddress = $this->ipLookupHelper->getIpAddress();
     $stat->setIpAddress($ipAddress);
     if ($this->dispatcher->hasListeners(EmailEvents::EMAIL_ON_OPEN)) {
         $event = new EmailOpenEvent($stat, $request, $firstTime);
         $this->dispatcher->dispatch(EmailEvents::EMAIL_ON_OPEN, $event);
     }
     //device granularity
     $dd = new DeviceDetector($request->server->get('HTTP_USER_AGENT'));
     $dd->parse();
     $deviceRepo = $this->leadModel->getDeviceRepository();
     $emailOpenDevice = $deviceRepo->getDevice(null, $lead, $dd->getDeviceName(), $dd->getBrand(), $dd->getModel());
     if (empty($emailOpenDevice)) {
         $emailOpenDevice = new LeadDevice();
         $emailOpenDevice->setClientInfo($dd->getClient());
         $emailOpenDevice->setDevice($dd->getDeviceName());
         $emailOpenDevice->setDeviceBrand($dd->getBrand());
         $emailOpenDevice->setDeviceModel($dd->getModel());
         $emailOpenDevice->setDeviceOs($dd->getOs());
         $emailOpenDevice->setDateOpen($readDateTime->toUtcString());
         $emailOpenDevice->setLead($lead);
         try {
             $this->em->persist($emailOpenDevice);
             $this->em->flush($emailOpenDevice);
         } catch (\Exception $exception) {
             if (MAUTIC_ENV === 'dev') {
                 throw $exception;
             } else {
                 $this->logger->addError($exception->getMessage(), ['exception' => $exception]);
             }
         }
     } else {
         $emailOpenDevice = $deviceRepo->getEntity($emailOpenDevice['id']);
     }
     if ($email) {
         $this->em->persist($email);
         $this->em->flush($email);
     }
     if (isset($emailOpenDevice) and is_object($emailOpenDevice)) {
         $emailOpenStat = new StatDevice();
         $emailOpenStat->setIpAddress($ipAddress);
         $emailOpenStat->setDevice($emailOpenDevice);
         $emailOpenStat->setDateOpened($readDateTime->toUtcString());
         $emailOpenStat->setStat($stat);
         $this->em->persist($emailOpenStat);
         $this->em->flush($emailOpenStat);
     }
     $this->em->persist($stat);
     $this->em->flush();
 }
Example #6
0
 /**
  * Check to see if the interval between events are appropriate to fire currentEvent
  *
  * @param           $action
  * @param \DateTime $parentTriggeredDate
  * @param bool      $allowNegative
  *
  * @return bool
  */
 public function checkEventTiming($action, \DateTime $parentTriggeredDate = null, $allowNegative = false)
 {
     $logger = $this->factory->getLogger();
     $now = new \DateTime();
     $logger->debug('CAMPAIGN: Check timing for ' . ucfirst($action['eventType']) . ' ID# ' . $action['id']);
     if ($action instanceof Event) {
         $action = $action->convertToArray();
     }
     if ($action['decisionPath'] == 'no' && !$allowNegative) {
         $logger->debug('CAMPAIGN: ' . ucfirst($action['eventType']) . ' is attached to a negative path which is not allowed');
         return false;
     } else {
         $negate = $action['decisionPath'] == 'no' && $allowNegative;
         if ($action['triggerMode'] == 'interval') {
             $triggerOn = $negate ? clone $parentTriggeredDate : new \DateTime();
             if ($triggerOn == null) {
                 $triggerOn = new \DateTime();
             }
             $interval = $action['triggerInterval'];
             $unit = strtoupper($action['triggerIntervalUnit']);
             $logger->debug('CAMPAIGN: Adding interval of ' . $interval . $unit . ' to ' . $triggerOn->format('Y-m-d H:i:s T'));
             switch ($unit) {
                 case 'Y':
                 case 'M':
                 case 'D':
                     $dt = "P{$interval}{$unit}";
                     break;
                 case 'I':
                     $dt = "PT{$interval}M";
                     break;
                 case 'H':
                 case 'S':
                     $dt = "PT{$interval}{$unit}";
                     break;
             }
             $dv = new \DateInterval($dt);
             $triggerOn->add($dv);
             if ($triggerOn > $now) {
                 $logger->debug('CAMPAIGN: Date to execute (' . $triggerOn->format('Y-m-d H:i:s T') . ') is later than now (' . $now->format('Y-m-d H:i:s T') . ')' . ($action['decisionPath'] == 'no' ? ' so ignore' : ' so schedule'));
                 // Save some RAM for batch processing
                 unset($now, $action, $dv, $dt);
                 //the event is to be scheduled based on the time interval
                 return $triggerOn;
             }
         } elseif ($action['triggerMode'] == 'date') {
             if (!$action['triggerDate'] instanceof \DateTime) {
                 $triggerDate = new DateTimeHelper($action['triggerDate']);
                 $action['triggerDate'] = $triggerDate->getDateTime();
                 unset($triggerDate);
             }
             $logger->debug('CAMPAIGN: Date execution on ' . $action['triggerDate']->format('Y-m-d H:i:s T'));
             $pastDue = $now >= $action['triggerDate'];
             if ($negate) {
                 $logger->debug('CAMPAIGN: Negative comparison; Date to execute (' . $action['triggerDate']->format('Y-m-d H:i:s T') . ') compared to now (' . $now->format('Y-m-d H:i:s T') . ') and is thus ' . ($pastDue ? 'overdue' : 'not past due'));
                 //it is past the scheduled trigger date and the lead has done nothing so return true to trigger
                 //the event otherwise false to do nothing
                 $return = $pastDue ? true : $action['triggerDate'];
                 // Save some RAM for batch processing
                 unset($now, $action);
                 return $return;
             } elseif (!$pastDue) {
                 $logger->debug('CAMPAIGN: Non-negative comparison; Date to execute (' . $action['triggerDate']->format('Y-m-d H:i:s T') . ') compared to now (' . $now->format('Y-m-d H:i:s T') . ') and is thus not past due');
                 //schedule the event
                 return $action['triggerDate'];
             }
         }
     }
     $logger->debug('CAMPAIGN: Nothing stopped execution based on timing.');
     //default is to trigger the event
     return true;
 }
Example #7
0
 /**
  * Fetch Lead stats for some period of time.
  *
  * @param integer $quantity of units
  * @param string $unit of time php.net/manual/en/class.dateinterval.php#dateinterval.props
  * @param array $options
  *
  * @return mixed
  * @throws \Doctrine\ORM\NoResultException
  * @throws \Doctrine\ORM\NonUniqueResultException
  */
 public function getLeadStats($quantity, $unit, $options = array())
 {
     $graphData = GraphHelper::prepareDatetimeLineGraphData($quantity, $unit, array('viewed'));
     // Load points for selected period
     $q = $this->getEntityManager()->getConnection()->createQueryBuilder();
     $q->select(sprintf('count(*) as count, DATE(cl.date_added) as date_added'))->from(MAUTIC_TABLE_PREFIX . 'campaign_leads', 'cl');
     $utc = new \DateTimeZone('UTC');
     $graphData['fromDate']->setTimezone($utc);
     $q->andwhere($q->expr()->andX($q->expr()->gte('cl.date_added', ':date'), $q->expr()->eq('cl.manually_removed', ':false')))->setParameter('date', $graphData['fromDate']->format('Y-m-d H:i:s'))->setParameter('false', false, 'boolean')->groupBy('DATE(cl.date_added)')->orderBy('date_added', 'ASC');
     if (isset($options['campaign_id'])) {
         $q->andwhere($q->expr()->gte('cl.campaign_id', (int) $options['campaign_id']));
     }
     $datesAdded = $q->execute()->fetchAll();
     $format = GraphHelper::getDateLabelFormat($unit);
     $formattedDates = array();
     $dt = new DateTimeHelper();
     foreach ($datesAdded as &$date) {
         $dt->setDateTime($date['date_added'], 'Y-m-d', 'utc');
         $key = $dt->getDateTime()->format($format);
         $formattedDates[$key] = (int) $date['count'];
     }
     foreach ($graphData['labels'] as $key => $label) {
         $graphData['datasets'][0]['data'][$key] = isset($formattedDates[$label]) ? $formattedDates[$label] : 0;
     }
     unset($graphData['fromDate']);
     return $graphData;
 }
Example #8
0
 /**
  * {@inheritdoc}
  *
  * @param Email $entity
  * @param       $unlock
  *
  * @return mixed
  */
 public function saveEntity($entity, $unlock = true)
 {
     $now = new DateTimeHelper();
     $type = $entity->getEmailType();
     if (empty($type)) {
         // Just in case JS failed
         $entity->setEmailType('template');
     }
     // Ensure that list emails are published
     if ($entity->getEmailType() == 'list') {
         $entity->setIsPublished(true);
         $entity->setPublishDown(null);
         $entity->setPublishUp(null);
     }
     //set the author for new pages
     if (!$entity->isNew()) {
         //increase the revision
         $revision = $entity->getRevision();
         $revision++;
         $entity->setRevision($revision);
     }
     // Ensure links in template content don't have encoded ampersands
     if ($entity->getTemplate()) {
         $content = $entity->getContent();
         foreach ($content as $key => $value) {
             $content[$key] = $this->cleanUrlsInContent($value);
         }
         $entity->setContent($content);
     } else {
         // Ensure links in HTML don't have encoded ampersands
         $htmlContent = $this->cleanUrlsInContent($entity->getCustomHtml());
         $entity->setCustomHtml($htmlContent);
     }
     // Ensure links in PLAIN TEXT don't have encoded ampersands
     $plainContent = $this->cleanUrlsInContent($entity->getPlainText());
     $entity->setPlainText($plainContent);
     // Reset the variant hit and start date if there are any changes and if this is an A/B test
     // Do it here in addition to the blanket resetVariants call so that it's available to the event listeners
     $changes = $entity->getChanges();
     $parent = $entity->getVariantParent();
     if ($parent !== null && !empty($changes) && empty($this->inConversion)) {
         $entity->setVariantSentCount(0);
         $entity->setVariantReadCount(0);
         $entity->setVariantStartDate($now->getDateTime());
     }
     parent::saveEntity($entity, $unlock);
     // If parent, add this entity as a child of the parent so that it populates the list in the tab (due to Doctrine hanging on to entities in memory)
     if ($parent) {
         $parent->addVariantChild($entity);
     }
     // Reset associated variants if applicable due to changes
     if ($entity->isVariant() && !empty($changes) && empty($this->inConversion)) {
         $dateString = $now->toUtcString();
         $parentId = !empty($parent) ? $parent->getId() : $entity->getId();
         $this->getRepository()->resetVariants($parentId, $dateString);
         //if the parent was changed, then that parent/children must also be reset
         if (isset($changes['variantParent'])) {
             $this->getRepository()->resetVariants($changes['variantParent'][0], $dateString);
         }
     }
 }
 /**
  * Note last ID read for user in channel
  *
  * @param User $userId
  * @param Channel $channelId
  * @param $lastId
  */
 public function markRead(User $user, Channel $channel, $lastId)
 {
     $qb = $this->_em->createQueryBuilder();
     $qb->select('s')->from('MauticChatBundle:ChannelStat', 's')->where($qb->expr()->eq('s.channel', ':channel'))->setParameter('channel', $channel)->andWhere($qb->expr()->eq('s.user', ':user'))->setParameter('user', $user);
     $exists = $qb->getQuery()->getResult();
     $now = new DateTimeHelper();
     if (!empty($exists)) {
         //update the record
         $exists[0]->setLastRead($lastId);
         $exists[0]->setDateRead($now->getDateTime());
         $this->_em->persist($exists[0]);
     } else {
         $stat = new ChannelStat();
         $stat->setChannel($channel);
         $stat->setUser($user);
         $stat->setLastRead($lastId);
         $stat->setDateRead($now->getDateTime());
         $stat->setDateJoined($now->getDateTime());
         $this->_em->persist($stat);
     }
     $this->_em->flush();
 }
Example #10
0
 /**
  * Subscribe user to channel
  *
  * @param Channel $channel
  * @param User    $user
  */
 public function subscribeToChannel(Channel $channel, User $user = null)
 {
     if ($user == null) {
         $user = $this->factory->getUser();
     }
     $stat = $this->getUserChannelStats($channel);
     if (empty($stat)) {
         $now = new DateTimeHelper();
         //get the last read id
         $lastId = $this->getRepository()->getLastChatId($channel->getId());
         $stat = new ChannelStat();
         $stat->setChannel($channel);
         $stat->setUser($user);
         $stat->setLastRead($lastId);
         $stat->setDateRead($now->getDateTime());
         $stat->setDateJoined($now->getDateTime());
         $this->getRepository()->saveEntity($stat);
     }
 }
Example #11
0
 /**
  * {@inheritdoc}
  *
  * @param Page $entity
  * @param bool $unlock
  */
 public function saveEntity($entity, $unlock = true)
 {
     if (empty($this->inConversion)) {
         $alias = $entity->getAlias();
         if (empty($alias)) {
             $alias = $entity->getTitle();
         }
         $alias = $this->cleanAlias($alias, '', false, '-');
         //make sure alias is not already taken
         $repo = $this->getRepository();
         $testAlias = $alias;
         $count = $repo->checkUniqueAlias($testAlias, $entity);
         $aliasTag = $count;
         while ($count) {
             $testAlias = $alias . $aliasTag;
             $count = $repo->checkUniqueAlias($testAlias, $entity);
             $aliasTag++;
         }
         if ($testAlias != $alias) {
             $alias = $testAlias;
         }
         $entity->setAlias($alias);
     }
     $now = new DateTimeHelper();
     //set the author for new pages
     $isNew = $entity->isNew();
     if (!$isNew) {
         //increase the revision
         $revision = $entity->getRevision();
         $revision++;
         $entity->setRevision($revision);
     }
     // Reset the variant hit and start date if there are any changes and if this is an A/B test
     // Do it here in addition to the blanket resetVariants call so that it's available to the event listeners
     $changes = $entity->getChanges();
     $parent = $entity->getVariantParent();
     if ($parent !== null && !empty($changes) && empty($this->inConversion)) {
         $entity->setVariantHits(0);
         $entity->setVariantStartDate($now->getDateTime());
     }
     parent::saveEntity($entity, $unlock);
     // If parent, add this entity as a child of the parent so that it populates the list in the tab (due to Doctrine hanging on to entities in memory)
     if ($parent) {
         $parent->addVariantChild($entity);
     }
     if ($translationParent = $entity->getTranslationParent()) {
         $translationParent->addTranslationChild($entity);
     }
     // Reset associated variants if applicable due to changes
     if ($entity->isVariant() && !empty($changes) && empty($this->inConversion)) {
         $dateString = $now->toUtcString();
         $parentId = !empty($parent) ? $parent->getId() : $entity->getId();
         $this->getRepository()->resetVariants($parentId, $dateString);
         //if the parent was changed, then that parent/children must also be reset
         if (isset($changes['variantParent'])) {
             $this->getRepository()->resetVariants($changes['variantParent'][0], $dateString);
         }
     }
 }