Calculates whether the given timespan covers the first and last action
in a campaign.

@param Campaign $campaign
@param \DateInterval $campaignInterval
@return bool
514784
public function isValidTimespan(Campaign $campaign, \DateInterval $campaignInterval)
    {
        /** @var Action $firstAction */
        $firstAction = $this->em->getRepository('CampaignChain\CoreBundle\Entity\Campaign')
            ->getFirstAction($campaign);

        /** @var Action $lastAction */
        $lastAction = $this->em->getRepository('CampaignChain\CoreBundle\Entity\Campaign')
            ->getLastAction($campaign);

        // If no first and last action, any timespan is fine.
        if(!$firstAction && !$lastAction){
            return true;
        }

        /*
         * If first and last action exist, make sure the timespan stretches from
         * the start of the first to the start or end of the last action.
         */
        if($firstAction && $lastAction){
            if($lastAction->getEndDate()){
                $endDate = $lastAction->getEndDate();
            } else {
                $endDate = $lastAction->getStartDate();
            }

            $actionsInterval = $firstAction->getStartDate()->diff($endDate);

            return $campaignInterval >= $actionsInterval;
        }

        /*
         * If only first action or last action, make sure the timespan covers
         * the duration of the action.
         */
        if($firstAction && !$lastAction) {
            $action = $firstAction;
        } else {
            $action = $lastAction;
        }

        // If the action has no end date, then any timespan will do.
        if(!$action->getEndDate()){
            return true;
        }

        $actionInterval = $action->getStartDate()->diff($action->getEndDate());

        return $campaignInterval >= $actionInterval;
    }
737542
private static function deleteCampaignFeed(
        AdWordsServices $adWordsServices,
        AdWordsSession $session,
        $campaignFeed
    ) {
        $campaignFeedService = $adWordsServices->get($session, CampaignFeedService::class);

        printf(
            "Deleting association of feed ID %d and campaign ID %d...\n",
            $campaignFeed->getFeedId(),
            $campaignFeed->getCampaignId()
        );

        $operation = new CampaignFeedOperation();
        $operation->setOperand($campaignFeed);
        $operation->setOperator(Operator::REMOVE);

        return $campaignFeedService->mutate([$operation]);
    }
314270
public function isGoalAchieved(MemberCampaign $memberCampaign) {
    /** @var \Drupal\node\NodeInterface $campaign */
    $campaign = $memberCampaign->getCampaign();

    // Get all enabled activities list.
    $activitiesOptions = openy_campaign_get_enabled_activities($campaign);

    // For disabled Visits Goal activity.
    if (!in_array('field_prgf_activity_visits', $activitiesOptions)) {
      return FALSE;
    }

    // We need to set UTC zone as far as Drupal stores dates in UTC zone.
    $campaignStartDate = new \DateTime($campaign->get('field_campaign_start_date')->getString(), new \DateTimeZone(DATETIME_STORAGE_TIMEZONE));
    // The checkins are saved with 0:0:0 time.
    $campaignStartDate->setTime(0, 0, 0);
    $campaignEndDate = new \DateTime($campaign->get('field_campaign_end_date')->getString(), new \DateTimeZone(DATETIME_STORAGE_TIMEZONE));
    $minVisitsGoal = !empty($campaign->field_min_visits_goal->value) ? $campaign->field_min_visits_goal->value : 0;

    // Get member with achieved goal.
    /** @var \Drupal\Core\Database\Query\Select $query */
    $query = $this->connection->select('openy_campaign_member_checkin', 'ch');
    $query->join('openy_campaign_member_campaign', 'mc', 'ch.member = mc.member');

    $query->addField('mc', 'id', 'member_campaign');

    $query->condition('ch.date', $campaignStartDate->format('U'), '>=');
    $query->condition('ch.date', $campaignEndDate->format('U'), '<');

    $query->condition('mc.id', $memberCampaign->id());

    $query->groupBy('mc.goal');
    $query->groupBy('mc.id');
    $query->having('COUNT(ch.id) > 0 AND COUNT(ch.id) >= mc.goal AND COUNT(ch.id) >= :minGoal', [':minGoal' => $minVisitsGoal]);

    $results = $query->execute()->fetchAll();
    if (!empty($results)) {
      return TRUE;
    }

    return FALSE;
  }
263279
public function isExecutableByCampaignByInterval($content, \DateTime $startDate, $interval, $errMsg)
    {
        /** @var Campaign $campaign */
        $campaign = $content->getOperation()->getActivity()->getCampaign();

        if($campaign->getInterval()){
            $campaignIntervalDate = new \DateTime();
            $campaignIntervalDate->modify($campaign->getInterval());
            $maxDuplicateIntervalDate = new \DateTime();
            $maxDuplicateIntervalDate->modify($interval);

            if($maxDuplicateIntervalDate > $campaignIntervalDate){
                return array(
                    'status' => false,
                    'message' => $errMsg,
                );
            }
        }

        return $this->isExecutableByCampaign(
            $content, $content->getOperation()->getActivity()->getStartDate()
        );
    }
26906
public function updateCampaign($CampaignId, Campaign $campaign) {
        $response = $this->mailjet->put(Resources::$Campaign, ['id' => $CampaignId, 'body' => $campaign->format()]);
        if (!$response->success()) {
            $this->throwError("CampaignManager:updateCampaign() failed", $response);
        }

        return $response->getData();
    }
1135363
public function isRemovable(Activity $activity)
    {
        //Deletion should only be possible if the activity is not closed
        if ($activity->getStatus() == 'closed') {
            return false;
        }

        /** @var Activity $activity */
        $activity = $this->em
            ->getRepository('CampaignChainCoreBundle:Activity')
            ->createQueryBuilder('a')
            ->select('a, f, o, sr, cta')
            ->leftJoin('a.facts', 'f')
            ->leftJoin('a.operations', 'o')
            ->leftJoin('o.scheduledReports', 'sr')
            ->leftJoin('o.outboundCTAs', 'cta')
            ->where('a.id = :id')
            ->setParameter('id', $activity)
            ->getQuery()
            ->getOneOrNullResult();

        if (!$activity->getFacts()->isEmpty()) {
            return false;
        }

        /** @var Operation[] $operations */
        $operations = new ArrayCollection();
        foreach ($activity->getOperations() as $op) {
            $operations->add($op);
        }
        //Check if there are scheduled reports or cta data for the operation
        foreach ($operations as $op) {
            if (!$op->getScheduledReports()->isEmpty() or !$op->getOutboundCTAs()->isEmpty()) {
                return false;
            }
        }

        $schedulerReportsActivities = $this->em
                ->getRepository('CampaignChainCoreBundle:SchedulerReportActivity')
                ->findBy(['endActivity' => $activity]);
        $ctaActivities = $this->em
                ->getRepository('CampaignChainCoreBundle:ReportCTA')
                ->findBy(['activity' => $activity]);

        if (!empty($schedulerReportsActivities) or !empty($ctaActivities)) {
            return false;
        }

        return true;
    }
798172
protected function checkCampaignPeriod(Node $campaign) {
    /** @var \Drupal\node\Entity\Node $campaign Campaign node. */
    $localeCampaignStartDate = OpenYLocaleDate::createDateFromFormat($campaign->get('field_campaign_start_date')->getString());
    $localeCampaignEndDate = OpenYLocaleDate::createDateFromFormat($campaign->get('field_campaign_end_date')->getString());

    return $localeCampaignStartDate->dateExpired() && !$localeCampaignEndDate->dateExpired();
  }
263867
private function getEdgeAction(Campaign $campaign, $position)
    {
        if($position != 'first' && $position != 'last'){
            throw new \Exception('Position must be either "first" or "last"');
        }
        if($position == 'first'){
            $order = 'ASC';
        } else {
            $order = 'DESC';
        }

        // Get first Activity
        /** @var Activity $activity */
        $activity = $this->createQueryBuilder('c')
            ->select('a')
            ->from('CampaignChain\CoreBundle\Entity\Activity', 'a')
            ->where('a.campaign = :campaign')
            ->setParameter('campaign', $campaign)
            ->orderBy('a.startDate', $order)
            ->setMaxResults(1)
            ->getQuery()
            ->getOneOrNullResult();

        // Get first Milestone
        /** @var Milestone $milestone */
        $milestone = $this->createQueryBuilder('c')
            ->select('m')
            ->from('CampaignChain\CoreBundle\Entity\Milestone', 'm')
            ->where('m.campaign = :campaign')
            ->setParameter('campaign', $campaign)
            ->orderBy('m.startDate', $order)
            ->setMaxResults(1)
            ->getQuery()
            ->getOneOrNullResult();

        // Does Activity or Milestone exist?
        if($activity == null && $milestone == null){
            return null;
        }
        if($milestone == null){
            return $activity;
        }
        if($activity == null){
            return $milestone;
        }

        // Does Activity or Milestone come first/last?
        if($position == 'first') {
            if ($activity->getStartDate() < $milestone->getStartDate()) {
                return $activity;
            } else {
                return $milestone;
            }
        } else {
            if ($activity->getStartDate() > $milestone->getStartDate()) {
                return $activity;
            } else {
                return $milestone;
            }
        }
    }
702476
private function validateMemberAge() {
    /** @var \Drupal\node\Entity\Node $campaign Campaign node object. */
    $campaign = $this->getCampaign();
    /** @var \Drupal\openy_campaign\Entity\Member $member Temporary Member object. Will be saved by submit. */
    $member = $this->getMember();

    $minAge = $campaign->get('field_campaign_age_minimum')->value;
    $maxAge = $campaign->get('field_campaign_age_maximum')->value;

    $birthday = new \DateTime($member->getBirthDate());
    $now = new \DateTime();
    $interval = $now->diff($birthday)->format('%y');

    if (
      (!empty($minAge) && !empty($maxAge) && $interval >= $minAge &&  $interval <= $maxAge) ||
      (!empty($minAge) && empty($maxAge) && $interval >= $minAge) ||
      (empty($minAge) && !empty($maxAge) && $interval <= $maxAge)
    ) {
      return ['status' => TRUE, 'error' => ''];
    }

    return ['status' => FALSE, 'error' => t('Age is not between @min and @max.', ['@min' => $minAge, '@max' => $maxAge])->render()];

  }
993027
public boolean execute(Campaign campaign) {
        boolean campaignResult = true;
        currentCampaign = campaign;
        campaignStartTimeStamp = new Date();
        try {
            createReport();

            for (CampaignRun run : currentCampaign.getRuns()) {
                if (TestEngine.isAbortedByUser()) {
                    break;
                }
                currentTestBed = run.getTestbed();
                String testSuiteName = currentCampaign.getName() + " - " + currentTestBed.substring(0,
                      currentTestBed.lastIndexOf('.'));
                TestBedConfiguration.setConfigFile(StaticConfiguration.TESTBED_CONFIG_DIRECTORY + "/" + currentTestBed);
                currentTestSuite = MetaTestSuite.createMetaTestSuite(testSuiteName, run.getTestsuites());
                if (currentTestSuite == null) {
                    continue;
                }
                currentTestSuite.addTestReportListener(this);
                campaignResult &= TestEngine.execute(
                      currentTestSuite); // NOSONAR - Potentially dangerous use of non-short-circuit logic
                currentTestSuite.removeTestReportListener(this);
                currentTestSuite = null;
            }
            CampaignReportManager.getInstance().stopReport();
        } finally {
            TestEngine.tearDown();
            campaignStartTimeStamp = null;
            currentCampaign = null;
        }
        return campaignResult;
    }
725668
public function removeCampaign(\CampaignChain\CoreBundle\Entity\Campaign $campaigns)
    {
        $this->campaigns->removeElement($campaigns);
    }
1300863
public function getExpiredEmailCampaignsByStoreIds($storeIds)
    {
        $time = new \DateTime('now', new \DateTimezone('UTC'));
        $interval = $this->dateIntervalFactory->create(
            ['interval_spec' => sprintf('PT%sH', 2)]
        );
        $time->sub($interval);

        $campaignCollection = $this->addFieldToFilter('campaign_id', ['notnull' => true])
            ->addFieldToFilter('send_status', \Dotdigitalgroup\Email\Model\Campaign::PROCESSING)
            ->addFieldToFilter('store_id', ['in' => $storeIds])
            ->addFieldToFilter('send_id', ['notnull' => true])
            ->addFieldToFilter('updated_at', ['lt' => $time->format('Y-m-d H:i:s')]);

        return $campaignCollection;
    }
265162
public function reportDailyStatistics($campaign_id, $start_date, $end_date)
		{
			$form_data = array(
				'campaign_id' => $campaign_id,
				'from_date' => $start_date,
				'to_date' => $end_date
			);
			$xml = $this->call('rpt_daily_stats', $form_data);

			$reports = array();

			foreach ($xml->Data as $daily_report)
			{
				$report = new Report();
				$report
					->setCampaignId((int)$daily_report->Campaign_ID)
					->setEventDate(\DateTime::createFromFormat('m/d/Y', $daily_report->event_date))
					->setTotalSent((int)$daily_report->Total_sent)
					->setTotalOpened((int)$daily_report->Total_opened)
					->setTotalOpenedUnique((int)$daily_report->Unique_opened)
					->setTotalClicks((int)$daily_report->Total_clickthroughs)
					->setTotalClicksUnique((int)$daily_report->Unique_clickthroughs)
					->setSoftBounces((int)$daily_report->Total_soft_bounced)
					->setHardBounces((int)$daily_report->Total_hard_bounced)
					->setUnsubscribes((int)$daily_report->Total_unsubscribed)
					->setComplaintBounces((int)$daily_report->Total_complaints_bounced)
					->setBlockedBounces((int)$daily_report->Total_blocked_bounced);
				$reports[] = $report;
			}

			return $reports;
		}
11293
public function setCampaign(Campaign $campaign = null)
    {
        if ($campaign) {
            $this->campaign   = $campaign;
            $this->campaignId = $campaign->getId();
        }

        return $this;
    }
76456
public static function compareDateIntervals(DateInterval $a, DateInterval $b)
    {
        $current = Carbon::now();
        $passed = $current->copy()->add($b);
        $current->add($a);

        if ($current < $passed) {
            return -1;
        } elseif ($current > $passed) {
            return 1;
        }

        return 0;
    }
8090
public function launchCampaign(Campaign &$campaign)
		{
			$form_data = array(
				'list_id' => $campaign->getListId(),
				'template_id' => $campaign->getTemplateId(),
				'subject' => $campaign->getSubject(),
				'seed_list_id' => $campaign->getSeedListId(),
				'segmentation_id' => $campaign->getSegmentationId(),
				'format' => $campaign->getFormat(),
				'campaign_alias' => $campaign->getAlias(),
				'target_rss' => $campaign->getRss(),
				'vmta' => $campaign->getVmta(),
				'ab_definition_id' => $campaign->getAbDefinitionId(),
				'deployed_by_email' => $campaign->getDeployedByEmail(),
				'return_task_id' => $campaign->getReturnTaskId(),
				'delivery' => $campaign->getSeedDelivery(),
				'notify_email' => $campaign->getSendNotification()
			);
			$data = $this->call('launch', $form_data);

			if ($campaign->getReturnTaskId())
			{
				$campaign->setTaskId(trim($data[2]));
			}

		}
563879
public function getWinnerStream(NodeInterface $campaign) {
    $winners = [];
    $streamType = $campaign->get('field_campaign_stream_type')->getString();
    switch ($streamType) {
      case 'all':
        $instantWinners = $this->getWinnersOfType('instant', $campaign->id());
        $visitGoalAchived = $this->getWinnersOfType('visit', $campaign->id());

        $winners = array_merge($instantWinners, $visitGoalAchived);
        break;

      case 'instant':
        $winners = $this->getWinnersOfType('instant', $campaign->id());
        break;

      case 'visit':
        $winners = $this->getWinnersOfType('visit', $campaign->id());
        break;

      default:
        break;
    }
    shuffle($winners);
    return $winners;
  }