@param Campaign  $campaign
@param \DateTime $dateFrom
@param \DateTime $dateTo

@return array

@throws \Doctrine\DBAL\DBALException
778231
public function getCampaignRevenueDatatableData(Campaign $campaign, \DateTime $dateFrom, \DateTime $dateTo)
    {
        $response = [];

        $cache_dir = $this->dispatcher->getContainer()->getParameter('kernel.cache_dir');

        $unit             = $this->getTimeUnitFromDateRange($dateFrom, $dateTo);
        $chartQueryHelper = new ChartQuery($this->em->getConnection(), $dateFrom, $dateTo, $unit);
        $dbunit           = $chartQueryHelper->translateTimeUnit($unit);

        $results = $this->getRepository()->getCampaignRevenueData(
            $campaign,
            $dateFrom,
            $dateTo,
            $unit,
            $dbunit,
            $cache_dir
        );

        // Allow other bundles to alter the data before rendering
        $event = new ChartDataAlterEvent(
            'campaign.revenue.datatable',
            [
                'campaign' => $campaign,
                'dateFrom' => $dateFrom,
                'dateTo'   => $dateTo,
                'unit'     => $unit,
                'dbunit'   => $dbunit,
                'cacheDir' => $cache_dir,
            ], $results
        );
        $this->dispatcher->dispatch('mautic.contactledger.chartdata.alter', $event);
        $results = $event->getData();

        foreach ($results as $result) {
            $result['cost']    = self::formatDollar($result['cost']);
            $result['revenue'] = self::formatDollar($result['revenue']);
            $result['profit']  = self::formatDollar($result['profit']);
            $response[]        = $result;
        }

        return $response;
    }
337802
public function setFromQDateTime(QDateTime $dttFrom, QDateTime $dttTo)
    {
        $this->add($dttFrom->difference($dttTo));
    }
568898
public function getEvents($contactClientId, $eventType = null, $dateRange = [])
    {
        $q = $this->getEntityManager()->getConnection()->createQueryBuilder()
            ->from(MAUTIC_TABLE_PREFIX.'contactclient_events', 'c')
            ->select('c.*');

        $expr = $q->expr()->eq('c.contactclient_id', ':contactClient');
        $q->where($expr)
            ->setParameter('contactClient', (int) $contactClientId);

        if (isset($dateRange['dateFrom'])) {
            if (!($dateRange['dateFrom'] instanceof \DateTime)) {
                try {
                    $dateRange['datefrom'] = new \DateTime($dateRange['dateFrom']);
                    $dateRange['dateFrom']->setTime(0, 0, 0);
                } catch (\Exception $e) {
                    $dateRange['datefrom'] = new \DateTime('midnight -1 month');
                }
            }
            $q->andWhere(
                $q->expr()->gte('c.date_added', ':dateFrom')
            )
                ->setParameter('dateFrom', $dateRange['dateFrom']->format('Y-m-d H:i:s'));
        }
        if (isset($dateRange['dateTo'])) {
            if (!($dateRange['dateTo'] instanceof \DateTime)) {
                try {
                    $dateRange['datefrom'] = new \DateTime($dateRange['dateTo']);
                    $dateRange['dateTo']->setTime(0, 0, 0);
                } catch (\Exception $e) {
                    $dateRange['datefrom'] = new \DateTime('midnight');
                }
                $dateRange['dateTo']->modify('+1 day');
            }
            $q->andWhere(
                $q->expr()->lt('c.date_added', ':dateTo')
            )
                ->setParameter('dateTo', $dateRange['dateTo']->format('Y-m-d H:i:s'));
        }

        if ($eventType) {
            $q->andWhere(
                $q->expr()->eq('c.type', ':type')
            )
                ->setParameter('type', $eventType);
        }

        return $q->execute()->fetchAll();
    }
838142
private function getCampaignNodeCampaignMenu(NodeInterface $campaign) {
    /** @var \Drupal\node\Entity\Node $campaign */
    if ($campaign->bundle() != 'campaign') {
      return [];
    }

    // Get full menu from the Campaign node.
    $campaignMenu = $campaign->get('field_campaign_menu')->getValue();
    if (!empty($campaignMenu)) {
      $campaignMenu = unserialize($campaign->field_campaign_menu->value);
    }

    if (empty($campaignMenu)) {
      return [];
    }

    /** @var \Drupal\node\Entity\Node $landingPage */
    $landingPage = $this->getActiveCampaignPage($campaign);

    if (empty($landingPage)) {
      return [];
    }

    $links = [];
    foreach ($campaignMenu[$landingPage->id()]['links'] as $k => $link) {
      if (empty($link['page'])) {
        continue;
      }
      $linkPageId = $link['page'][0]['target_id'];

      // Replace the link on the main Campaign page by the Campaign's URL.
      if ($linkPageId == $landingPage->id()) {
        $linkPageId = $campaign->id();
      }
      $needsLogin = $link['logged'] && !MemberCampaign::isLoggedIn($campaign->id());
      $links['campaign_' . $k] = [
        '#type' => 'link',
        '#title' => $link['title'],
        '#url' => !$needsLogin
          ? Url::fromRoute('entity.node.canonical', ['node' => $linkPageId])
          : Url::fromRoute('openy_campaign.member-action', ['action' => 'login', 'campaign_id' => $campaign->id()])
        ,
        '#attributes' => [
          'class' => [
            'campaign-page',
            'node-' . $linkPageId,
            'active',
            !$needsLogin ? '' : 'use-ajax login',
          ],
        ],
      ];
    }

    return $links;
  }
1301314
public function getFor($key, \DateTime $date)
    {
        if (!$this->hasFor($key, $date)) {
            return null;
        }

        return $this->data[$this->keyFor($key, $date)];
    }
468524
public function getStats(
        ContactClient $contactClient,
        $unit,
        \DateTime $dateFrom = null,
        \DateTime $dateTo = null,
        $campaignId = null,
        $dateFormat = null,
        $canViewOthers = true
    ) {
        $query = new ChartQuery($this->em->getConnection(), $dateFrom, $dateTo, $unit);
        $unit  = (null === $unit) ? $this->getTimeUnitFromDateRange($dateFrom, $dateTo) : $unit;
        $chart = new LineChart($unit, $dateFrom, $dateTo, $dateFormat);
        $stat  = new Stat();

        $params = ['contactclient_id' => $contactClient->getId()];

        if ($campaignId) {
            $params['campaign_id'] = $campaignId;
        }

        foreach ($stat->getAllTypes() as $type) {
            $params['type'] = $type;
            $q              = $query->prepareTimeDataQuery(
                'contactclient_stats',
                'date_added',
                $params
            );

            if (!in_array($unit, ['H', 'i', 's'])) {
                // For some reason, Mautic only sets UTC in Query Date builder
                // if its an intra-day date range ¯\_(ツ)_/¯
                // so we have to do it here.
                $userTZ        = new \DateTime('now');
                $userTzName    = $userTZ->getTimezone()->getName();
                $paramDateTo   = $q->getParameter('dateTo');
                $paramDateFrom = $q->getParameter('dateFrom');
                $paramDateTo   = new \DateTime($paramDateTo);
                $paramDateTo->setTimeZone(new \DateTimeZone('UTC'));
                $q->setParameter('dateTo', $paramDateTo->format('Y-m-d H:i:s'));
                $paramDateFrom = new \DateTime($paramDateFrom);
                $paramDateFrom->setTimeZone(new \DateTimeZone('UTC'));
                $q->setParameter('dateFrom', $paramDateFrom->format('Y-m-d H:i:s'));
                $select    = $q->getQueryPart('select')[0];
                $newSelect = str_replace(
                    't.date_added,',
                    "CONVERT_TZ(t.date_added, @@global.time_zone, '$userTzName'),",
                    $select
                );
                $q->resetQueryPart('select');
                $q->select($newSelect);

                // AND adjust the group By, since its using db timezone Date values
                $groupBy    = $q->getQueryPart('groupBy')[0];
                $newGroupBy = str_replace(
                    't.date_added,',
                    "CONVERT_TZ(t.date_added, @@global.time_zone, '$userTzName'),",
                    $groupBy
                );
                $q->resetQueryPart('groupBy');
                $q->groupBy($newGroupBy);
            }

            if (!$canViewOthers) {
                $this->limitQueryToCreator($q);
            }

            $data = $query->loadAndBuildTimeData($q);
            foreach ($data as $val) {
                if (0 !== $val) {
                    $chart->setDataset($this->translator->trans('mautic.contactclient.graph.'.$type), $data);
                    break;
                }
            }
        }

        return $chart->render();
    }
452429
private function getCampaignsToSend($emailsToSend, $website)
    {
        $campaignsToSend = [];
        foreach ($emailsToSend as $campaign) {
            $email = $campaign->getEmail();
            $campaignId = $campaign->getCampaignId();
            $websiteId = $website->getId();
            $client = false;
            if ($this->helper->isEnabled($websiteId)) {
                $client = $this->helper->getWebsiteApiClient($websiteId);
            }
            //Only if valid client is returned
            if ($client && $this->isCampaignValid($campaign)) {
                $campaignsToSend[$campaignId]['client'] = $client;
                $contact = $this->helper->getContact(
                    $campaign->getEmail(),
                    $websiteId
                );
                if ($contact && isset($contact->id)) {
                    //update data fields
                    if ($campaign->getEventName() == 'Order Review') {
                        $this->updateDataFieldsForORderReviewCampaigns($campaign, $websiteId, $client, $email);
                    } elseif ($campaign->getEventName() ==
                        \Dotdigitalgroup\Email\Model\Campaign::CAMPAIGN_EVENT_LOST_BASKET
                    ) {
                        $campaignCollection = $this->campaignCollection->create();
                        // If AC campaigns found with status processing for given email then skip for current cron run
                        if ($campaignCollection->getNumberOfAcCampaignsWithStatusProcessingExistForContact($email)) {
                            continue;
                        }
                        $this->helper->updateLastQuoteId($campaign->getQuoteId(), $email, $websiteId);
                    }

                    $campaignsToSend[$campaignId]['contacts'][] = $contact->id;
                    $campaignsToSend[$campaignId]['ids'][] = $campaign->getId();
                } else {
                    //update the failed to send email message error message
                    $campaign->setSendStatus(\Dotdigitalgroup\Email\Model\Campaign::FAILED)
                        ->setMessage('Send not permitted. Contact is suppressed.');
                    $this->campaignResourceModel->saveItem($campaign);
                }
            }
        }

        return $campaignsToSend;
    }
1025264
private function updateDataFieldsForORderReviewCampaigns($campaign, $websiteId, $client, $email)
    {
        $order = $this->salesOrderFactory->create()->loadByIncrementId(
            $campaign->getOrderIncrementId()
        );

        if ($lastOrderId = $this->helper->getWebsiteConfig(
            \Dotdigitalgroup\Email\Helper\Config::XML_PATH_CONNECTOR_CUSTOMER_LAST_ORDER_ID,
            $websiteId
        )
        ) {
            $data[] = [
                'Key' => $lastOrderId,
                'Value' => $order->getId(),
            ];
        }
        if ($orderIncrementId = $this->helper->getWebsiteConfig(
            \Dotdigitalgroup\Email\Helper\Config::
            XML_PATH_CONNECTOR_CUSTOMER_LAST_ORDER_INCREMENT_ID,
            $websiteId
        )
        ) {
            $data[] = [
                'Key' => $orderIncrementId,
                'Value' => $order->getIncrementId(),
            ];
        }

        if (!empty($data)) {
            //update data fields
            $client->updateContactDatafieldsByEmail(
                $email,
                $data
            );
        }
    }
446315
private function mapClientArrayToEntity($stat, $dateTo)
    {
        $fieldsMap = [
            'campaignId'      => 'campaign_id',
            'received'        => 'received',
            'declined'        => 'rejected',
            'converted'       => 'converted',
            'cost'            => 'cost',
            'revenue'         => 'revenue',
            'contactClientId' => 'contactclient_id',
            'grossIncome'     => 'gross_income',
            'margin'          => 'gross_margin',
            'ecpm'            => 'ecpm',
            'utmSource'       => 'utm_source',
        ];

        $entity = new CampaignClientStats();
        foreach ($fieldsMap as $entityParam => $statKey) {
            if (null == $stat[$statKey]) {
                $stat[$statKey] = '';
            }
            $entity->__set($entityParam, $stat[$statKey]);
        }
        $entity->setDateAdded($dateTo);

        return $entity;
    }
533883
public static function getRelTime($datetime, $datetimeFrom = null)
    {
        $ret = '';
        $dateTime = self::getDateTime($datetime);
        $dateTimeFrom = self::getDateTime($datetimeFrom);
        $dateTimeSameDay = clone $dateTimeFrom;
        $dateTimeSameDay->setTime(0, 0, 0);
        $diffSec = $dateTimeFrom->getTimestamp() - $dateTime->getTimestamp();
        if ($dateTime > $dateTimeFrom) {
            // Future
            $dateTimeTest = clone $dateTimeSameDay;
            if ($dateTime < $dateTimeTest->modify('tomorrow')) {
                $ret = 'Today at '.$dateTime->format('g:ia');
            } elseif ($dateTime < $dateTimeTest->modify('+2 days')) {
                $ret = 'Tomorrow at '.$dateTime->format('g:ia');
            } else {
                $ret = $dateTime->format('F jS');
            }
        } elseif ($diffSec < 60) {
            // within a min
            $ret = 'Just now';
        } elseif ($diffSec < 3600) {
            // within an hour
            $ret = \round(($diffSec)/60) .' min ago';
        } elseif ($diffSec < 3600*6) {
            // within 6 hours
            $hrs = \round(($diffSec)/3600);
            $ret = $hrs.' '.Str::plural($hrs, 'hour').' ago';
        } elseif ($dateTime > $dateTimeSameDay) {             // since midnight so it's today
            $ret = 'Today at '.$dateTime->format('g:ia');
        } elseif ($dateTime->getTimestamp() >= $dateTimeSameDay->getTimestamp() - 86400) {
            $ret = 'Yesterday at '.$dateTime->format('g:ia');
        } elseif ($dateTime->getTimestamp() >= $dateTimeSameDay->getTimestamp() - 86400*7) {
            $ret = $dateTime->format('l \a\t g:ia');
        } elseif ($dateTime->getTimestamp() > \mktime(0, 0, 0, 1, 1)) {// since 1st Jan so it's this year
            $ret = $dateTime->format('F jS');
        } else {                                // last year..
            $ret = $dateTime->format('F jS, Y');
        }
        $ret = \str_replace(' at 12:00am', '', $ret);
        return $ret;
    }
291614
private static function getFeedItemIdsForCampaignFeed($campaignFeed)
    {
        $feedItemIds = [];

        if ($campaignFeed->getMatchingFunction()->getOperator() === FunctionOperator::IN) {
            // Check if matchingFunction is of the form IN(FEED_ITEM_ID,{xxx,xxx}).
            // Extract feed items if applicable.
            $feedItemIds = array_merge(
                $feedItemIds,
                self::getFeedItemIdsFromArgument($campaignFeed->getMatchingFunction())
            );
        } elseif ($campaignFeed->getMatchingFunction()->getOperator() === FunctionOperator::AND_VALUE) {
            foreach ($campaignFeed->getMatchingFunction()->getLhsOperand() as $argument) {
                // Check if matchingFunction is of the form IN(FEED_ITEM_ID,{xxx,xxx}).
                // Extract feed items if applicable.
                if ($argument instanceof FunctionOperand) {
                    if ($argument->getValue()->getOperator() === FunctionOperator::IN) {
                        $feedItemIds = array_merge(
                            $feedItemIds,
                            self::getFeedItemIdsFromArgument($argument->getValue())
                        );
                    }
                }
            }
        }

        return $feedItemIds;
    }
1068922
public function query($entity, $ref = 0, array $dateRange)
    {
        return new Query($this->mongo, $entity, $ref, $dateRange);
    }
631054
private static List<CampaignFeed> getCampaignFeeds(AdWordsServicesInterface adWordsServices,
      AdWordsSession session, Feed feed, int placeholderType) throws RemoteException {
    // Get the CampaignFeedService.
    CampaignFeedServiceInterface campaignFeedService =
        adWordsServices.get(session, CampaignFeedServiceInterface.class);

    String query = String.format(
        "SELECT CampaignId, MatchingFunction, PlaceholderTypes WHERE Status = 'ENABLED' "
        + "AND FeedId = %d AND PlaceholderTypes CONTAINS_ANY [%d]", feed.getId(), placeholderType);

    List<CampaignFeed> campaignFeeds = new ArrayList<>();
    int offset = 0;
    CampaignFeedPage campaignFeedPage;

    do {
      String pageQuery = String.format(query + " LIMIT %d, %d", offset, PAGE_SIZE);
      campaignFeedPage = campaignFeedService.query(pageQuery);
      if (campaignFeedPage.getEntries() != null) {
        campaignFeeds.addAll(Arrays.asList(campaignFeedPage.getEntries()));
      }
      offset += PAGE_SIZE;
    } while (offset < campaignFeedPage.getTotalNumEntries());

    return campaignFeeds;
  }
1334952
public function reportCampaignList($start_date, $end_date, $show_hidden)
		{
			$form_data = array(
				'from_date' => $start_date,
				'to_date' => $end_date,
				'show_hidden' => $show_hidden
			);
			$xml = $this->call('rpt_campaign_list', $form_data);

			$campaigns = array();

			foreach ($xml->Data as $campaign_item) {
				$campaign = new Report();
				$campaign
					->setCampaignId((int)$campaign_item->campaign_id)
					->setListId((int)$campaign_item->list_id)
					->setListName((string)$campaign_item->list_name)
					->setSubject((string)$campaign_item->subject)
					->setDate(\DateTime::createFromFormat('Y/m/d H:i:s', $campaign_item->deploy_date)) //2016-02-01 11:16:33
					->setRecipients((int)$campaign_item->pieces_sent)
					->setTaskId((int)$campaign_item->task_id);

				$campaigns[] = $campaign;
			}
			return $campaigns;
		}
925513
public function updateCampaignSchedule($CampaignId, $date)
    {
        $response = $this->mailjet->put(Resources::$CampaigndraftSchedule,
            ['id' => $CampaignId, 'body' => $date]);
        if (!$response->success()) {
            $this->throwError("CampaignDraftService:updateCampaignSchedule failed",
                $response);
        }

        return $response->getData();
    }
909655
public function create($campaign)
    {
        if (is_array($campaign)) {
            $campaign["campaign_type"] = "PROMOTION";
        }
        elseif (is_object($campaign)) {
            $campaign->campaign_type = "PROMOTION";
        }

        return $this->campaigns->create($campaign);
    }
1020440
private function mapArrayToEntity($stat, $context, $dateTo)
    {
        $fieldsMap = [
            'CampaignSourceStats'   => [
                'campaignId'      => 'campaign_id',
                'received'        => 'received',
                'declined'        => 'rejected',
                'converted'       => 'converted',
                'scrubbed'        => 'scrubbed',
                'cost'            => 'cost',
                'revenue'         => 'revenue',
                'contactSourceId' => 'contactsource_id',
                'grossIncome'     => 'gross_income',
                'margin'          => 'gross_margin',
                'ecpm'            => 'ecpm',
                'utmSource'       => 'utm_source',
            ],
            'CampaignSourceBudgets' => [
            ],
        ];

        $class  = '\MauticPlugin\MauticContactLedgerBundle\Entity\\'.$context;
        $entity = new $class();
        foreach ($fieldsMap[$context] as $entityParam => $statKey) {
            if (null == $stat[$statKey]) {
                $stat[$statKey] = '';
            }
            $entity->__set($entityParam, $stat[$statKey]);
        }
        $entity->setDateAdded($dateTo);
        $entity->setReprocessFlag(false);

        return $entity;
    }