/** * A method to activate/deactivate campaigns, based on the date and/or the inventory * requirements (impressions, clicks and/or conversions). Also sends email reports * for any campaigns that are activated/deactivated, as well as sending email reports * for any campaigns that are likely to expire in the near future. * * @param Date $oDate The current date/time. * @return string Report on the campaigns activated/deactivated. */ function manageCampaigns($oDate) { $aConf = $GLOBALS['_MAX']['CONF']; $oServiceLocator =& OA_ServiceLocator::instance(); $oEmail =& $oServiceLocator->get('OA_Email'); if ($oEmail === false) { $oEmail = new OA_Email(); $oServiceLocator->register('OA_Email', $oEmail); } $report = "\n"; // Select all campaigns in the system, where: // The campaign is ACTIVE and: // - The end date stored for the campaign is not null; or // - The campaign has a lifetime impression, click or conversion // target set. // // That is: // - It is possible for the active campaign to be automatically // stopped, as it has a valid end date. (No limitations are // applied to those campaigns tested, as the ME may not have // run for a while, and if so, even campaigns with an end date // of many, many weeks ago should be tested to ensure they are // [belatedly] halted.) // - It is possible for the active campaign to be automatically // stopped, as it has at leaast one lifetime target that could // have been reached. // // The campaign is INACTIVE and: // - The start date stored for the campaign is not null; and // - The weight is greater than zero; and // - The end date stored for the campaign is either null, or is // greater than "today" less one day. // // That is: // - It is possible for the inactive campaign to be automatically // started, as it has a valid start date. (No limitations are // applied to those campaigns tested, as the ME may not have run // for a while, and if so, even campaigns with an activation date // of many, many weeks ago should be tested to ensure they are // [belatedy] enabled.) // - The campaign is not in a permanently inactive state, as a // result of the weight being less then one, which means that // it cannot be activated. // - The test to start the campaign is unlikely to fail on account // of the end date. (Inactive campaigns with start dates may have // passed the start date, but they may also have passed the end // date - unfortunately, because the dates are not stored in UTC, // it's not possible to know exactly which campaigns have passed // the end date or not, until the values are converted to UTC based // on the Advertiser Account timezone preference - so it's necessary // to get some campaigns that might be passed the end date, and do // the converstion to UTC and test to check.) $prefix = $this->getTablePrefix(); $oYesterdayDate = new Date(); $oYesterdayDate->copy($oDate); $oYesterdayDate->subtractSeconds(SECONDS_PER_DAY); $query = "\n SELECT\n cl.clientid AS advertiser_id,\n cl.account_id AS advertiser_account_id,\n cl.agencyid AS agency_id,\n cl.contact AS contact,\n cl.email AS email,\n cl.reportdeactivate AS send_activate_deactivate_email,\n ca.campaignid AS campaign_id,\n ca.campaignname AS campaign_name,\n ca.views AS targetimpressions,\n ca.clicks AS targetclicks,\n ca.conversions AS targetconversions,\n ca.status AS status,\n ca.activate AS start,\n ca.expire AS end\n FROM\n {$prefix}campaigns AS ca,\n {$prefix}clients AS cl\n WHERE\n ca.clientid = cl.clientid\n AND\n ca.status = " . $this->oDbh->quote(OA_ENTITY_STATUS_RUNNING, 'integer') . "\n AND\n (\n ca.expire " . OA_Dal::notEqualNoDateString() . "\n OR\n (\n ca.views > 0\n OR\n ca.clicks > 0\n OR\n ca.conversions > 0\n )\n )\n UNION ALL\n SELECT\n cl.clientid AS advertiser_id,\n cl.account_id AS advertiser_account_id,\n cl.agencyid AS agency_id,\n cl.contact AS contact,\n cl.email AS email,\n cl.reportdeactivate AS send_activate_deactivate_email,\n ca.campaignid AS campaign_id,\n ca.campaignname AS campaign_name,\n ca.views AS targetimpressions,\n ca.clicks AS targetclicks,\n ca.conversions AS targetconversions,\n ca.status AS status,\n ca.activate AS start,\n ca.expire AS end\n FROM\n {$prefix}campaigns AS ca,\n {$prefix}clients AS cl\n WHERE\n ca.clientid = cl.clientid\n AND\n ca.status != " . $this->oDbh->quote(OA_ENTITY_STATUS_RUNNING, 'integer') . "\n AND\n ca.activate " . OA_Dal::notEqualNoDateString() . "\n AND\n (\n ca.weight > 0\n OR\n ca.priority > 0\n )\n AND\n (\n ca.expire >= " . $this->oDbh->quote($oYesterdayDate->format('%Y-%m-%d'), 'timestamp') . "\n OR\n ca.expire " . OA_Dal::equalNoDateString() . "\n )\n ORDER BY\n advertiser_id"; $rsResult = $this->oDbh->query($query); if (PEAR::isError($rsResult)) { return MAX::raiseError($rsResult, MAX_ERROR_DBFAILURE, PEAR_ERROR_DIE); } OA::debug('- Found ' . $rsResult->numRows() . ' campaigns to test for activation/deactivation', PEAR_LOG_DEBUG); while ($aCampaign = $rsResult->fetchRow()) { if ($aCampaign['status'] == OA_ENTITY_STATUS_RUNNING) { // The campaign is currently running, look at the campaign $disableReason = 0; $canExpireSoon = false; if ($aCampaign['targetimpressions'] > 0 || $aCampaign['targetclicks'] > 0 || $aCampaign['targetconversions'] > 0) { // The campaign has an impression, click and/or conversion target, // so get the sum total statistics for the campaign $query = "\n SELECT\n SUM(dia.impressions) AS impressions,\n SUM(dia.clicks) AS clicks,\n SUM(dia.conversions) AS conversions\n FROM\n " . $this->oDbh->quoteIdentifier($aConf['table']['prefix'] . $aConf['table']['data_intermediate_ad'], true) . " AS dia,\n " . $this->oDbh->quoteIdentifier($aConf['table']['prefix'] . $aConf['table']['banners'], true) . " AS b\n WHERE\n dia.ad_id = b.bannerid\n AND b.campaignid = {$aCampaign['campaign_id']}"; $rsResultInner = $this->oDbh->query($query); $valuesRow = $rsResultInner->fetchRow(); if (!is_null($valuesRow['impressions']) || !is_null($valuesRow['clicks']) || !is_null($valuesRow['conversions'])) { // There were impressions, clicks and/or conversions for this // campaign, so find out if campaign targets have been passed if (is_null($valuesRow['impressions'])) { // No impressions $valuesRow['impressions'] = 0; } if (is_null($valuesRow['clicks'])) { // No clicks $valuesRow['clicks'] = 0; } if (is_null($valuesRow['conversions'])) { // No conversions $valuesRow['conversions'] = 0; } if ($aCampaign['targetimpressions'] > 0) { if ($aCampaign['targetimpressions'] <= $valuesRow['impressions']) { // The campaign has an impressions target, and this has been // passed, so update and disable the campaign $disableReason |= OX_CAMPAIGN_DISABLED_IMPRESSIONS; } } if ($aCampaign['targetclicks'] > 0) { if ($aCampaign['targetclicks'] <= $valuesRow['clicks']) { // The campaign has a click target, and this has been // passed, so update and disable the campaign $disableReason |= OX_CAMPAIGN_DISABLED_CLICKS; } } if ($aCampaign['targetconversions'] > 0) { if ($aCampaign['targetconversions'] <= $valuesRow['conversions']) { // The campaign has a target limitation, and this has been // passed, so update and disable the campaign $disableReason |= OX_CAMPAIGN_DISABLED_CONVERSIONS; } } if ($disableReason) { // One of the campaign targets was exceeded, so disable $message = '- Exceeded a campaign quota: Deactivating campaign ID ' . "{$aCampaign['campaign_id']}: {$aCampaign['campaign_name']}"; OA::debug($message, PEAR_LOG_INFO); $report .= $message . "\n"; $doCampaigns = OA_Dal::factoryDO('campaigns'); $doCampaigns->campaignid = $aCampaign['campaign_id']; $doCampaigns->find(); $doCampaigns->fetch(); $doCampaigns->status = OA_ENTITY_STATUS_EXPIRED; $result = $doCampaigns->update(); if ($result == false) { return MAX::raiseError($rows, MAX_ERROR_DBFAILURE, PEAR_ERROR_DIE); } phpAds_userlogSetUser(phpAds_userMaintenance); phpAds_userlogAdd(phpAds_actionDeactiveCampaign, $aCampaign['campaign_id']); } else { // The campaign didn't have a diable reason, // it *might* possibly be diabled "soon"... $canExpireSoon = true; } } } // Does the campaign need to be disabled due to the date? if ($aCampaign['end'] != OA_Dal::noDateValue()) { // The campaign has a valid end date, stored in the timezone of the advertiser; // create an end date in the advertiser's timezone, set the time, and then // convert to UTC so that it can be compared with the MSE run time, which is // in UTC $aAdvertiserPrefs = OA_Preferences::loadAccountPreferences($aCampaign['advertiser_account_id'], true); $oTimezone = new Date_Timezone($aAdvertiserPrefs['timezone']); $oEndDate = new Date(); $oEndDate->convertTZ($oTimezone); $oEndDate->setDate($aCampaign['end'] . ' 23:59:59'); // Campaigns end at the end of the day $oEndDate->toUTC(); if ($oDate->after($oEndDate)) { // The end date has been passed; disable the campaign $disableReason |= OX_CAMPAIGN_DISABLED_DATE; $message = "- Passed campaign end time of '{$aCampaign['end']} 23:59:59 {$aAdvertiserPrefs['timezone']} (" . $oEndDate->format('%Y-%m-%d %H:%M:%S') . ' ' . $oEndDate->tz->getShortName() . ")': Deactivating campaign ID {$aCampaign['campaign_id']}: {$aCampaign['campaign_name']}"; OA::debug($message, PEAR_LOG_INFO); $report .= $message . "\n"; $doCampaigns = OA_Dal::factoryDO('campaigns'); $doCampaigns->campaignid = $aCampaign['campaign_id']; $doCampaigns->find(); $doCampaigns->fetch(); $doCampaigns->status = OA_ENTITY_STATUS_EXPIRED; $result = $doCampaigns->update(); if ($result == false) { return MAX::raiseError($rows, MAX_ERROR_DBFAILURE, PEAR_ERROR_DIE); } phpAds_userlogSetUser(phpAds_userMaintenance); phpAds_userlogAdd(phpAds_actionDeactiveCampaign, $aCampaign['campaign_id']); } else { // The campaign wasn't disabled based on the end // date, to it *might* possibly be disabled "soon"... $canExpireSoon = true; } } if ($disableReason) { // The campaign was disabled, so send the appropriate // message to the campaign's contact $query = "\n SELECT\n bannerid AS advertisement_id,\n description AS description,\n alt AS alt,\n url AS url\n FROM\n " . $this->oDbh->quoteIdentifier($aConf['table']['prefix'] . $aConf['table']['banners'], true) . "\n WHERE\n campaignid = {$aCampaign['campaign_id']}"; OA::debug("- Getting the advertisements for campaign ID {$aCampaign['campaign_id']}", PEAR_LOG_DEBUG); $rsResultAdvertisement = $this->oDbh->query($query); if (PEAR::isError($rsResultAdvertisement)) { return MAX::raiseError($rsResultAdvertisement, MAX_ERROR_DBFAILURE, PEAR_ERROR_DIE); } while ($advertisementRow = $rsResultAdvertisement->fetchRow()) { $advertisements[$advertisementRow['advertisement_id']] = array($advertisementRow['description'], $advertisementRow['alt'], $advertisementRow['url']); } if ($aCampaign['send_activate_deactivate_email'] == 't') { $oEmail->sendCampaignActivatedDeactivatedEmail($aCampaign['campaign_id'], $disableReason); } } else { if ($canExpireSoon) { // The campaign has NOT been deactivated - test to see if it will // be deactivated "soon", and send email(s) warning of this as required $oEmail->sendCampaignImpendingExpiryEmail($oDate, $aCampaign['campaign_id']); } } } else { // The campaign is not active - does it need to be enabled, // based on the campaign starting date? if ($aCampaign['start'] != OA_Dal::noDateValue()) { // The campaign has a valid start date, stored in the timezone of the advertiser; // create an end date in the advertiser's timezone, set the time, and then // convert to UTC so that it can be compared with the MSE run time, which is // in UTC $aAdvertiserPrefs = OA_Preferences::loadAccountPreferences($aCampaign['advertiser_account_id'], true); $oTimezone = new Date_Timezone($aAdvertiserPrefs['timezone']); $oStartDate = new Date(); $oStartDate->convertTZ($oTimezone); $oStartDate->setDate($aCampaign['start'] . ' 00:00:00'); // Campaigns start at the start of the day $oStartDate->toUTC(); if ($aCampaign['end'] != OA_Dal::noDateValue()) { // The campaign has a valid end date, stored in the timezone of the advertiser; // create an end date in the advertiser's timezone, set the time, and then // convert to UTC so that it can be compared with the MSE run time, which is // in UTC $oEndDate = new Date(); $oEndDate->convertTZ($oTimezone); $oEndDate->setDate($aCampaign['end'] . ' 23:59:59'); // Campaign end at the end of the day $oEndDate->toUTC(); } else { $oEndDate = null; } if ($oDate->after($oStartDate)) { // The start date has been passed; find out if there are any impression, click // or conversion targets for the campaign (i.e. if the target values are > 0) $remainingImpressions = 0; $remainingClicks = 0; $remainingConversions = 0; if ($aCampaign['targetimpressions'] > 0 || $aCampaign['targetclicks'] > 0 || $aCampaign['targetconversions'] > 0) { // The campaign has an impression, click and/or conversion target, // so get the sum total statistics for the campaign so far $query = "\n SELECT\n SUM(dia.impressions) AS impressions,\n SUM(dia.clicks) AS clicks,\n SUM(dia.conversions) AS conversions\n FROM\n " . $this->oDbh->quoteIdentifier($aConf['table']['prefix'] . $aConf['table']['data_intermediate_ad'], true) . " AS dia,\n " . $this->oDbh->quoteIdentifier($aConf['table']['prefix'] . $aConf['table']['banners'], true) . " AS b\n WHERE\n dia.ad_id = b.bannerid\n AND b.campaignid = {$aCampaign['campaign_id']}"; $rsResultInner = $this->oDbh->query($query); $valuesRow = $rsResultInner->fetchRow(); // Set the remaining impressions, clicks and conversions for the campaign $remainingImpressions = $aCampaign['targetimpressions'] - $valuesRow['impressions']; $remainingClicks = $aCampaign['targetclicks'] - $valuesRow['clicks']; $remainingConversions = $aCampaign['targetconversions'] - $valuesRow['conversions']; } // In order for the campaign to be activated, need to test: // 1) That there is no impression target (<= 0), or, if there is an impression target (> 0), // then there must be remaining impressions to deliver (> 0); and // 2) That there is no click target (<= 0), or, if there is a click target (> 0), // then there must be remaining clicks to deliver (> 0); and // 3) That there is no conversion target (<= 0), or, if there is a conversion target (> 0), // then there must be remaining conversions to deliver (> 0); and // 4) Either there is no end date, or the end date has not been passed if (($aCampaign['targetimpressions'] <= 0 || $aCampaign['targetimpressions'] > 0 && $remainingImpressions > 0) && ($aCampaign['targetclicks'] <= 0 || $aCampaign['targetclicks'] > 0 && $remainingClicks > 0) && ($aCampaign['targetconversions'] <= 0 || $aCampaign['targetconversions'] > 0 && $remainingConversions > 0) && (is_null($oEndDate) || $oEndDate->format('%Y-%m-%d') != OA_Dal::noDateValue() && Date::compare($oDate, $oEndDate) < 0)) { $message = "- Passed campaign start time of '{$aCampaign['start']} 00:00:00 {$aAdvertiserPrefs['timezone']} (" . $oStartDate->format('%Y-%m-%d %H:%M:%S') . ' ' . $oStartDate->tz->getShortName() . ")': Activating campaign ID {$aCampaign['campaign_id']}: {$aCampaign['campaign_name']}"; OA::debug($message, PEAR_LOG_INFO); $report .= $message . "\n"; $doCampaigns = OA_Dal::factoryDO('campaigns'); $doCampaigns->campaignid = $aCampaign['campaign_id']; $doCampaigns->find(); $doCampaigns->fetch(); $doCampaigns->status = OA_ENTITY_STATUS_RUNNING; $result = $doCampaigns->update(); if ($result == false) { return MAX::raiseError($rows, MAX_ERROR_DBFAILURE, PEAR_ERROR_DIE); } phpAds_userlogSetUser(phpAds_userMaintenance); phpAds_userlogAdd(phpAds_actionActiveCampaign, $aCampaign['campaign_id']); // Get the advertisements associated with the campaign $query = "\n SELECT\n bannerid AS advertisement_id,\n description AS description,\n alt AS alt,\n url AS url\n FROM\n " . $this->oDbh->quoteIdentifier($aConf['table']['prefix'] . $aConf['table']['banners'], true) . "\n WHERE\n campaignid = {$aCampaign['campaign_id']}"; OA::debug("- Getting the advertisements for campaign ID {$aCampaign['campaign_id']}", PEAR_LOG_DEBUG); $rsResultAdvertisement = $this->oDbh->query($query); if (PEAR::isError($rsResultAdvertisement)) { return MAX::raiseError($rsResultAdvertisement, MAX_ERROR_DBFAILURE, PEAR_ERROR_DIE); } while ($advertisementRow = $rsResultAdvertisement->fetchRow()) { $advertisements[$advertisementRow['advertisement_id']] = array($advertisementRow['description'], $advertisementRow['alt'], $advertisementRow['url']); } if ($aCampaign['send_activate_deactivate_email'] == 't') { $oEmail->sendCampaignActivatedDeactivatedEmail($aCampaign['campaign_id']); } } } } } } }
/** * A method to get the hourly revenuo of a monthly tenancy campaign * * Monthly tenancy calculation sponsored by www.admost.nl * * @param array $aInfo The finance information, as returned by _saveSummaryGetAdFinanceInfo * @param Date $oStartDate * @param Date $oEndDate * @param string $table * @return double */ function getMtRevenue($aInfo, $oStartDate, $oEndDate, $table) { OA::debug(sprintf(" - Calculating MT revenue for banner [id%d] between %s and %s:", $aInfo['ad_id'], $oStartDate->format('%Y-%m-%d %H:%M:%S %Z'), $oEndDate->format('%Y-%m-%d %H:%M:%S %Z')), PEAR_LOG_DEBUG); $aConf = $GLOBALS['_MAX']['CONF']; $oMonthStart = new Date($oStartDate); // Set timezone if (!empty($aInfo['advertiser_id'])) { $doClient = OA_Dal::staticGetDO('clients', $aInfo['advertiser_id']); $aAdvertiserPrefs = OA_Preferences::loadAccountPreferences($doClient->account_id, true); if (!empty($aAdvertiserPrefs['timezone'])) { $oMonthStart->convertTZbyID($aAdvertiserPrefs['timezone']); } } // Get ad/zone combinations for the campaign if (!isset($this->aMtRevenueCache[$aInfo['campaign_id']])) { $query = "\n SELECT\n COUNT(*) as cnt\n FROM\n " . $this->oDbh->quoteIdentifier($aConf['table']['prefix'] . $aConf['table'][$table], true) . " d JOIN\n " . $this->oDbh->quoteIdentifier($aConf['table']['prefix'] . $aConf['table']['banners'], true) . " a ON (a.bannerid = d.ad_id)\n WHERE\n a.campaignid = {$aInfo['campaign_id']}\n AND d.date_time >= " . $this->oDbh->quote($oStartDate->format('%Y-%m-%d %H:%M:%S'), 'timestamp') . "\n AND d.date_time <= " . $this->oDbh->quote($oEndDate->format('%Y-%m-%d %H:%M:%S'), 'timestamp'); $this->aMtRevenueCache[$aInfo['campaign_id']] = $this->oDbh->query($query)->fetchOne(); } $oMonthStart->setDay(1); $oMonthStart->setHour(0); $oMonthStart->setMinute(0); $oMonthStart->setSecond(0); OA::debug(sprintf(" - Month start: %s", $oMonthStart->format('%Y-%m-%d %H:%M:%S %Z')), PEAR_LOG_DEBUG); $daysInMonth = $oMonthStart->getDaysInMonth(); OA::debug(sprintf(" - Days in month: %d", $daysInMonth), PEAR_LOG_DEBUG); $oMonthEnd = new Date($oMonthStart); $oMonthEnd->setDay($daysInMonth); $oMonthEnd = $oMonthEnd->getNextDay(); $oMonthEnd->setTZ($oMonthStart->tz); OA::debug(sprintf(" - Month end: %s", $oMonthEnd->format('%Y-%m-%d %H:%M:%S %Z')), PEAR_LOG_DEBUG); $oDiff = new Date_Span(); $oDiff->setFromDateDiff($oMonthEnd, $oMonthStart); $hoursPerMonth = ceil($oDiff->toHours()); OA::debug(sprintf(" - Hours per month: %d", $hoursPerMonth), PEAR_LOG_DEBUG); $oDiff = new Date_Span(); $oDiff->setFromDateDiff($oEndDate, $oStartDate); $hoursPerInterval = ceil($oDiff->toHours()); OA::debug(sprintf(" - Hours per interval: %d", $hoursPerInterval), PEAR_LOG_DEBUG); $adZoneCombinations = $this->aMtRevenueCache[$aInfo['campaign_id']]; OA::debug(sprintf(" - Ad/zone/OI combinations for campaign [id%d]: %d", $aInfo['campaign_id'], $this->aMtRevenueCache[$aInfo['campaign_id']]), PEAR_LOG_DEBUG); $result = $aInfo['revenue'] / $hoursPerMonth * $hoursPerInterval / $adZoneCombinations; OA::debug(sprintf(" - Result: %0.4f", $result), PEAR_LOG_DEBUG); return $result; }
/** * @param $oDate * @param $campaignId * @return int Number of emails sent */ function sendCampaignImpendingExpiryEmail($oDate, $campaignId) { $aConf = $GLOBALS['_MAX']['CONF']; global $date_format; $oPreference = new OA_Preferences(); if (!isset($this->aAdminCache)) { // Get admin account ID $adminAccountId = OA_Dal_ApplicationVariables::get('admin_account_id'); // Get admin prefs $adminPrefsNames = $this->_createPrefsListPerAccount(OA_ACCOUNT_ADMIN); $aAdminPrefs = $oPreference->loadAccountPreferences($adminAccountId, $adminPrefsNames, OA_ACCOUNT_ADMIN); // Get admin users $aAdminUsers = $this->getAdminUsersLinkedToAccount(); // Store admin cache $this->aAdminCache = array($aAdminPrefs, $aAdminUsers); } else { // Retrieve admin cache list($aAdminPrefs, $aAdminUsers) = $this->aAdminCache; } $aPreviousOIDates = OX_OperationInterval::convertDateToPreviousOperationIntervalStartAndEndDates($oDate); $aPreviousOIDates = OX_OperationInterval::convertDateToPreviousOperationIntervalStartAndEndDates($aPreviousOIDates['start']); $doCampaigns = OA_Dal::staticGetDO('campaigns', $campaignId); if (!$doCampaigns) { return 0; } $aCampaign = $doCampaigns->toArray(); if (!isset($this->aClientCache[$aCampaign['clientid']])) { $doClients = OA_Dal::staticGetDO('clients', $aCampaign['clientid']); // Add advertiser linked users $aLinkedUsers['advertiser'] = $this->getUsersLinkedToAccount('clients', $aCampaign['clientid']); // Add advertiser prefs $advertiserPrefsNames = $this->_createPrefsListPerAccount(OA_ACCOUNT_ADVERTISER); $aPrefs['advertiser'] = $oPreference->loadAccountPreferences($doClients->account_id, $advertiserPrefsNames, OA_ACCOUNT_ADVERTISER); if (!isset($aAgencyCache[$doClients->agencyid])) { // Add manager linked users $doAgency = OA_Dal::staticGetDO('agency', $doClients->agencyid); $aLinkedUsers['manager'] = $this->getUsersLinkedToAccount('agency', $doClients->agencyid); // Add manager preferences $managerPrefsNames = $this->_createPrefsListPerAccount(OA_ACCOUNT_MANAGER); $aPrefs['manager'] = $oPreference->loadAccountPreferences($doAgency->account_id, $managerPrefsNames, OA_ACCOUNT_MANAGER); // Get agency "From" details $aAgencyFromDetails = $this->_getAgencyFromDetails($doAgency->agencyid); // Store in the agency cache $this->aAgencyCache = array($doClients->agencyid => array($aLinkedUsers['manager'], $aPrefs['manager'], $aAgencyFromDetails)); } else { // Retrieve agency cache list($aLinkedUsers['manager'], $aPrefs['manager'], $aAgencyFromDetails) = $this->aAgencyCache[$doClients->agencyid]; } // Add admin linked users and preferences $aLinkedUsers['admin'] = $aAdminUsers; $aPrefs['admin'] = $aAdminPrefs; // Create a linked user 'special' for the advertiser that will take the admin preferences for advertiser $aLinkedUsers['special']['advertiser'] = $doClients->toArray(); $aLinkedUsers['special']['advertiser']['contact_name'] = $aLinkedUsers['special']['advertiser']['contact']; $aLinkedUsers['special']['advertiser']['email_address'] = $aLinkedUsers['special']['advertiser']['email']; $aLinkedUsers['special']['advertiser']['language'] = ''; $aLinkedUsers['special']['advertiser']['user_id'] = 0; // Check that every user is not going to receive more than one email if they // are linked to more than one account $aLinkedUsers = $this->_deleteDuplicatedUser($aLinkedUsers); // Create the linked special user preferences from the admin preferences // the special user is the client that doesn't have preferences in the database $aPrefs['special'] = $aPrefs['admin']; $aPrefs['special']['warn_email_special'] = $aPrefs['special']['warn_email_advertiser']; $aPrefs['special']['warn_email_special_day_limit'] = $aPrefs['special']['warn_email_advertiser_day_limit']; $aPrefs['special']['warn_email_special_impression_limit'] = $aPrefs['special']['warn_email_advertiser_impression_limit']; // Store in the client cache $this->aClientCache = array($aCampaign['clientid'] => array($aLinkedUsers, $aPrefs, $aAgencyFromDetails)); } else { // Retrieve client cache list($aLinkedUsers, $aPrefs, $aAgencyFromDetails) = $this->aClientCache[$aCampaign['clientid']]; } $copiesSent = 0; foreach ($aLinkedUsers as $accountType => $aUsers) { if ($accountType == 'special' || $accountType == 'advertiser') { // Get the agency details and use them for emailing advertisers $aFromDetails = $aAgencyFromDetails; } else { // Use the Admin details $aFromDetails = ''; } if ($aPrefs[$accountType]['warn_email_' . $accountType]) { // Does the account type want warnings when the impressions are low? if ($aPrefs[$accountType]['warn_email_' . $accountType . '_impression_limit'] > 0 && $aCampaign['views'] > 0) { // Test to see if the placements impressions remaining are less than the limit $dalCampaigns = OA_Dal::factoryDAL('campaigns'); $remainingImpressions = $dalCampaigns->getAdImpressionsLeft($aCampaign['campaignid']); if ($remainingImpressions < $aPrefs[$accountType]['warn_email_' . $accountType . '_impression_limit']) { // Yes, the placement will expire soon! But did the placement just reach // the point where it is about to expire, or did it happen a while ago? $previousRemainingImpressions = $dalCampaigns->getAdImpressionsLeft($aCampaign['campaignid'], $aPreviousOIDates['end']); if ($previousRemainingImpressions >= $aPrefs[$accountType]['warn_email_' . $accountType . '_impression_limit']) { // Yes! This is the operation interval that the boundary // was crossed to the point where it's about to expire, // so send that email, baby! foreach ($aUsers as $aUser) { $aEmail = $this->prepareCampaignImpendingExpiryEmail($aUser, $aCampaign['clientid'], $aCampaign['campaignid'], 'impressions', $aPrefs[$accountType]['warn_email_' . $accountType . '_impression_limit'], $accountType); if ($aEmail !== false) { if ($this->sendMail($aEmail['subject'], $aEmail['contents'], $aUser['email_address'], $aUser['contact_name'], $aFromDetails)) { $copiesSent++; if ($aConf['email']['logOutgoing']) { phpAds_userlogSetUser(phpAds_userMaintenance); phpAds_userlogAdd(phpAds_actionWarningMailed, $aPlacement['campaignid'], "{$aEmail['subject']}\n\n\n {$aUser['contact_name']}({$aUser['email_address']})\n\n\n {$aEmail['contents']}"); } } } } } } } // Does the account type want warnings when the days are low? if ($aPrefs[$accountType]['warn_email_' . $accountType . '_day_limit'] > 0 && !empty($aCampaign['expire_time'])) { // Calculate the date that should be used to see if the warning needs to be sent $warnSeconds = (int) ($aPrefs[$accountType]['warn_email_' . $accountType . '_day_limit'] + 1) * SECONDS_PER_DAY; $oEndDate = new Date($aCampaign['expire_time']); $oEndDate->setTZbyID('UTC'); $oTestDate = new Date(); $oTestDate->copy($oDate); $oTestDate->addSeconds($warnSeconds); // Test to see if the test date is after the placement's expiration date if ($oTestDate->after($oEndDate)) { // Yes, the placement will expire soon! But did the placement just reach // the point where it is about to expire, or did it happen a while ago? $oiSeconds = (int) $aConf['maintenance']['operationInterval'] * 60; $oTestDate->subtractSeconds($oiSeconds); if (!$oTestDate->after($oEndDate)) { // Yes! This is the operation interval that the boundary // was crossed to the point where it's about to expire, // so send those emails, baby! foreach ($aUsers as $aUser) { $aEmail = $this->prepareCampaignImpendingExpiryEmail($aUser, $aCampaign['clientid'], $aCampaign['campaignid'], 'date', $oEndDate->format($date_format), $accountType); if ($aEmail !== false) { if ($this->sendMail($aEmail['subject'], $aEmail['contents'], $aUser['email_address'], $aUser['contact_name'], $aFromDetails)) { $copiesSent++; if ($aConf['email']['logOutgoing']) { phpAds_userlogSetUser(phpAds_userMaintenance); phpAds_userlogAdd(phpAds_actionWarningMailed, $aPlacement['campaignid'], "{$aEmail['subject']}\n\n\n {$aUser['contact_name']}({$aUser['email_address']})\n\n\n {$aEmail['contents']}"); } } } } } } } } } // Restore the default language strings Language_Loader::load('default'); return $copiesSent; }
/** * A method to check if the campaign is expired * * @return bool */ function _isExpired() { static $oServiceLocator; // MySQL null date hardcoded for optimisation if (!empty($this->expire) && $this->expire != '0000-00-00') { if (!isset($oServiceLocator)) { $oServiceLocator =& OA_ServiceLocator::instance(); } if (!($oNow = $oServiceLocator->get('now'))) { $oNow = new Date(); } $oExpire = new Date($this->expire); $oExpire->setHour(23); $oExpire->setMinute(59); $oExpire->setSecond(59); if (!empty($this->clientid)) { // Set timezone $aAccounts = $this->getOwningAccountIds(); $aPrefs = OA_Preferences::loadAccountPreferences($aAccounts[OA_ACCOUNT_ADVERTISER], true); if (isset($aPrefs['timezone'])) { $oExpire->setTZbyID($aPrefs['timezone']); } } if ($oNow->after($oExpire)) { return true; } } return false; }
/** * Return the timezone object that the campaign is suposed to be using * * @staticvar array $aCache * @param int $campaignId * @return Date_TimeZone */ public function getTimezoneForCampaign($campaignId) { static $aCache; $doAgency = OA_Dal::factoryDO('agency'); $doClients = OA_Dal::factoryDO('clients'); $doCampaigns = OA_Dal::factoryDO('campaigns'); $doCampaigns->campaignid = $campaignId; $doClients->joinAdd($doCampaigns); $doAgency->joinAdd($doClients); if ($doAgency->find()) { $doAgency->fetch(); if (!isset($aCache[$doAgency->account_id])) { $aPrefs = OA_Preferences::loadAccountPreferences($doAgency->account_id, true); $oTz = new Date_TimeZone(empty($aPrefs['timezone']) ? 'UTC' : $aPrefs['timezone']); $aCache[$doAgency->account_id] = $oTz; } else { $oTz = $aCache[$doAgency->account_id]; } } else { $oTz = new Date_TimeZone('UTC'); } return $oTz; }