/** * This method initialises object from array. * * @param array $aEntityData */ function readDataFromArray($aEntityData) { $aFieldsTypes = $this->getFieldsTypes(); foreach ($aFieldsTypes as $fieldName => $fieldType) { if (array_key_exists($fieldName, $aEntityData)) { if ($fieldType == 'date') { // If the date is 'no date' then don't return this element in the response at all. if (empty($aEntityData[$fieldName]) || $aEntityData[$fieldName] == OA_Dal::noDateValue()) { unset($this->{$fieldName}); } else { $this->{$fieldName} = new Date($aEntityData[$fieldName]); } } else { $this->{$fieldName} = $aEntityData[$fieldName]; } } } }
/** * Return (or set) a default field value based on field type * * @see DB_DataObject for list of defined field types * * @param string $fieldType Field type to set * @param string $setDefaultValue Value to set * @return string * @static */ function defaultValueByType($fieldType, $setDefaultValue = null) { static $aDefaultValues; if ($setDefaultValue !== null) { $aDefaultValues[$fieldType] = $setDefaultValue; } if (isset($aDefaultValues[$fieldType])) { return $aDefaultValues[$fieldType]; } // This is the only exception we found so far, if we will find more we may need // to refactor following if ($fieldType & DB_DATAOBJECT_DATE) { if ($fieldType & DB_DATAOBJECT_NOTNULL) { return MAX_DATAGENERATOR_DEFAULT_DATE_VALUE; } // According to https://developer.openx.org/wiki/DatabasePractices#UsingPEAR::MDB2 return OA_Dal::noDateValue(); } // If no default set for this data type try default type if (isset($aDefaultValues[MAX_DATAGENERATOR_DEFAULT_TYPE])) { return $aDefaultValues[MAX_DATAGENERATOR_DEFAULT_TYPE]; } // If still nothing found use a global default return MAX_DATAGENERATOR_DEFAULT_VALUE; }
/** * 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']); } } } } } } }
/** * Checks whether end date is after start date. * * @access public * * @param date $oStartDate Pear::Date object with Start Date * @param date $oEndDate Pear::Date object with End Date * * @return boolean Returns false when start date * is after end date and true in other case. */ function checkDateOrder($oStartDate, $oEndDate) { if (isset($oStartDate) && isset($oEndDate) && ($oStartDate->format("%Y-%m-%d") != OA_Dal::noDateValue() && $oEndDate->format("%Y-%m-%d") != OA_Dal::noDateValue()) && $oStartDate->after($oEndDate)) { $this->raiseError('The start date is after the end date'); return false; } else { return true; } }
/** * Convert Date from iso 8601 format. * * @access private * * @param string $date date string in ISO 8601 format * @param PEAR::Date &$oResult transformed date * @param XML_RPC_Response &$oResponseWithError response with error message * * @return boolean shows true if method was executed successfully */ function _convertDateFromIso8601Format($date, &$oResult, &$oResponseWithError) { $datetime = explode('T', $date); $year = substr($datetime[0], 0, strlen($datetime[0]) - 4); $month = substr($datetime[0], -4, 2); $day = substr($datetime[0], -2, 2); // Explicitly allow the "zero date" value to be set if ($year == 0 && $month == 0 && $day == 0) { $oResult = new Date(OA_Dal::noDateValue()); return true; } if ($year < 1970 || $year > 2038) { $oResponseWithError = XmlRpcUtils::generateError('Year should be in range 1970-2038'); return false; } elseif ($month < 1 || $month > 12) { $oResponseWithError = XmlRpcUtils::generateError('Month should be in range 1-12'); return false; } elseif ($day < 1 || $day > 31) { $oResponseWithError = XmlRpcUtils::generateError('Day should be in range 1-31'); return false; } else { $oResult = new Date(); $oResult->setYear($year); $oResult->setMonth($month); $oResult->setDay($day); return true; } }
/** * This function sets all default values when adding new campaign. * */ function setDefaultForAdd() { if (is_null($this->startDate)) { $this->startDate = new Date(OA_Dal::noDateValue()); } if (is_null($this->endDate)) { $this->endDate = new Date(OA_Dal::noDateValue()); } if (is_null($this->impressions)) { $this->impressions = -1; } if (is_null($this->clicks)) { $this->clicks = -1; } if (is_null($this->priority)) { $this->priority = 0; } if (is_null($this->weight)) { $this->weight = 1; } if (is_null($this->targetImpressions)) { $this->targetImpressions = 0; } if (is_null($this->targetClicks)) { $this->targetClicks = 0; } if (is_null($this->targetConversions)) { $this->targetConversions = 0; } if (is_null($this->revenue)) { // Leave null } if (is_null($this->revenueType)) { // Leave null } if (is_null($this->capping)) { // Leave null } if (is_null($this->sessionCapping)) { // Leave null } if (is_null($this->block)) { // Leave null } }
/** * The class constructor method. * * @param array $aParams An associative array of values to be assigned to * the object. Valid array keys are: * 'campaignid' or 'placement_id' -> The placement ID. Required! * 'activate' -> The activation date of the placement in * 'YYYY-MM-DD' string format * 'expire' -> The expiration date of the placement in * 'YYYY-MM-DD' string format * 'views' or 'impression_target_total' -> The placement lifetime impression target * 'clicks' or 'click_target_total' -> The placement lifetime click target * 'conversions' or 'conversion_target_total' -> The placement lifetime conversion target * 'target_impression' or 'impression_target_daily' -> The dail impression target * 'target_click' or 'click_target_daily' -> The daily click target * 'target_conversion' or 'conversion_target_daily' -> The daily conversion target * 'priority' -> The placement priority */ function OX_Maintenance_Priority_Campaign($aParams) { // Convert "old" input value names to "new", if required foreach ($this->aNewOldTypes as $newName => $oldName) { if (empty($aParams[$newName])) { $aParams[$newName] = $aParams[$oldName]; } } // Test the input values $valid = true; if (!is_array($aParams)) { $valid = false; } if (count($aParams) < 0) { $valid = false; } if (!is_numeric($aParams['placement_id'])) { $valid = false; } if (!$valid) { $this->_abort(); } // Store the required supplied values $this->id = (int) $aParams['placement_id']; // Store the optional required values $this->activate = !empty($aParams['activate']) && $aParams['activate'] != OA_Dal::noDateString() ? $aParams['activate'] : OA_Dal::noDateValue(); $this->expire = !empty($aParams['expire']) && $aParams['expire'] != OA_Dal::noDateString() ? $aParams['expire'] : OA_Dal::noDateValue(); $this->impressionTargetTotal = isset($aParams['impression_target_total']) ? (int) $aParams['impression_target_total'] : 0; $this->clickTargetTotal = isset($aParams['click_target_total']) ? (int) $aParams['click_target_total'] : 0; $this->conversionTargetTotal = isset($aParams['conversion_target_total']) ? (int) $aParams['conversion_target_total'] : 0; $this->impressionTargetDaily = isset($aParams['impression_target_daily']) ? (int) $aParams['impression_target_daily'] : 0; $this->clickTargetDaily = isset($aParams['click_target_daily']) ? (int) $aParams['click_target_daily'] : 0; $this->conversionTargetDaily = isset($aParams['conversion_target_daily']) ? (int) $aParams['conversion_target_daily'] : 0; $this->priority = isset($aParams['priority']) ? (int) $aParams['priority'] : 0; // Set the object's data access layer objects $this->oMaxDalEntities =& $this->_getMAX_Dal_Entities(); $this->oMaxDalMaintenancePriority =& $this->_getOA_Dal_Maintenance_Priority(); }
/** * Processes submit values of campaign form * * @param OA_Admin_UI_Component_Form $form form to process * @return An array of Pear::Error objects if any */ function processCampaignForm($form, &$oComponent = null) { $aFields = $form->exportValues(); $expire = !empty($aFields['end']) ? date('Y-m-d', strtotime($aFields['end'])) : OA_Dal::noDateValue(); $activate = !empty($aFields['start']) ? date('Y-m-d', strtotime($aFields['start'])) : OA_Dal::noDateValue(); if (empty($aFields['campaignid'])) { // The form is submitting a new campaign, so, the ID is not set; // set the ID to the string "null" so that the table auto_increment // or sequence will be used when the campaign is created $aFields['campaignid'] = "null"; } else { // The form is submitting a campaign modification; need to test // if any of the banners in the campaign are linked to an email zone, // and if so, if the link(s) would still be valid if the change(s) // to the campaign were made... $dalCampaigns = OA_Dal::factoryDAL('campaigns'); $aCurrentLinkedEmalZoneIds = $dalCampaigns->getLinkedEmailZoneIds($aFields['campaignid']); if (PEAR::isError($aCurrentLinkedEmalZoneIds)) { OX::disableErrorHandling(); $errors[] = PEAR::raiseError($GLOBALS['strErrorDBPlain']); OX::enableErrorHandling(); } $errors = array(); foreach ($aCurrentLinkedEmalZoneIds as $zoneId) { $thisLink = Admin_DA::_checkEmailZoneAdAssoc($zoneId, $aFields['campaignid'], $activate, $expire); if (PEAR::isError($thisLink)) { $errors[] = $thisLink; break; } } } //correct and check revenue and ecpm correctAdnCheckNumericFormField($aFields, $errors, 'revenue', $GLOBALS['strErrorEditingCampaignRevenue']); correctAdnCheckNumericFormField($aFields, $errors, 'ecpm', $GLOBALS['strErrorEditingCampaignECPM']); if (empty($errors)) { //check booked limits values // If this is a remnant, ecpm or exclusive campaign with an expiry date, set the target's to unlimited if (OA_Dal::isValidDate($expire) && ($aFields['campaign_type'] == OX_CAMPAIGN_TYPE_REMNANT || $aFields['campaign_type'] == OX_CAMPAIGN_TYPE_ECPM || $aFields['campaign_type'] == OX_CAMPAIGN_TYPE_CONTRACT_EXCLUSIVE)) { $aFields['impressions'] = $aFields['clicks'] = $aFields['conversions'] = -1; } else { if (!empty($aFields['impr_unlimited']) && $aFields['impr_unlimited'] == 't') { $aFields['impressions'] = -1; } else { if (empty($aFields['impressions']) || $aFields['impressions'] == '-') { $aFields['impressions'] = 0; } } if (!empty($aFields['click_unlimited']) && $aFields['click_unlimited'] == 't') { $aFields['clicks'] = -1; } else { if (empty($aFields['clicks']) || $aFields['clicks'] == '-') { $aFields['clicks'] = 0; } } if (!empty($aFields['conv_unlimited']) && $aFields['conv_unlimited'] == 't') { $aFields['conversions'] = -1; } else { if (empty($aFields['conversions']) || $aFields['conversions'] == '-') { $aFields['conversions'] = 0; } } } //pricing model - reset fields not applicable to model to 0, //note that in new flow MAX_FINANCE_CPA allows all limits to be set if ($aFields['revenue_type'] == MAX_FINANCE_CPM) { $aFields['clicks'] = -1; $aFields['conversions'] = -1; } else { if ($aFields['revenue_type'] == MAX_FINANCE_CPC) { $aFields['conversions'] = -1; } else { if ($aFields['revenue_type'] == MAX_FINANCE_MT) { $aFields['impressions'] = -1; $aFields['clicks'] = -1; $aFields['conversions'] = -1; } } } //check type and set priority if ($aFields['campaign_type'] == OX_CAMPAIGN_TYPE_REMNANT) { $aFields['priority'] = 0; //low } else { if ($aFields['campaign_type'] == OX_CAMPAIGN_TYPE_CONTRACT_NORMAL) { $aFields['priority'] = isset($aFields['high_priority_value']) ? $aFields['high_priority_value'] : 5; //high } else { if ($aFields['campaign_type'] == OX_CAMPAIGN_TYPE_CONTRACT_EXCLUSIVE) { $aFields['priority'] = -1; //exclusive } else { if ($aFields['campaign_type'] == OX_CAMPAIGN_TYPE_ECPM) { $aFields['priority'] = -2; //ecpm } } } } if ($aFields['priority'] > 0) { // Set target $target_impression = 0; $target_click = 0; $target_conversion = 0; if (isset($aFields['target_value']) && $aFields['target_value'] != '-') { switch ($aFields['target_type']) { case 'target_impression': $target_impression = $aFields['target_value']; break; case 'target_click': $target_click = $aFields['target_value']; break; case 'target_conversion': $target_conversion = $aFields['target_value']; break; } } $aFields['weight'] = 0; } else { // Set weight if (!isset($aFields['weight']) || $aFields['weight'] == '-' || $aFields['weight'] == '') { $aFields['weight'] = 0; } $target_impression = 0; $target_click = 0; $target_conversion = 0; } if ($aFields['anonymous'] != 't') { $aFields['anonymous'] = 'f'; } if ($aFields['companion'] != 1) { $aFields['companion'] = 0; } $new_campaign = $aFields['campaignid'] == 'null'; if (empty($aFields['revenue']) || $aFields['revenue'] <= 0) { // No revenue information, set to null $aFields['revenue'] = 'NULL'; } if (empty($aFields['ecpm']) || $aFields['ecpm'] <= 0) { // No ecpm information, set to null $aFields['ecpm'] = 'NULL'; } // Get the capping variables $block = _initCappingVariables($aFields['time'], $aFields['capping'], $aFields['session_capping']); $noDateValue = OA_Dal::noDateValue(); if (!isset($noDateValue)) { $noDateValue = 0; } $doCampaigns = OA_Dal::factoryDO('campaigns'); $doCampaigns->campaignname = $aFields['campaignname']; $doCampaigns->clientid = $aFields['clientid']; $doCampaigns->views = $aFields['impressions']; $doCampaigns->clicks = $aFields['clicks']; $doCampaigns->conversions = $aFields['conversions']; $doCampaigns->expire = OA_Dal::isValidDate($expire) ? $expire : $noDateValue; $doCampaigns->activate = OA_Dal::isValidDate($activate) ? $activate : $noDateValue; $doCampaigns->priority = $aFields['priority']; $doCampaigns->weight = $aFields['weight']; $doCampaigns->target_impression = $target_impression; $doCampaigns->target_click = $target_click; $doCampaigns->target_conversion = $target_conversion; $doCampaigns->min_impressions = $aFields['min_impressions']; $doCampaigns->ecpm = $aFields['ecpm']; $doCampaigns->anonymous = $aFields['anonymous']; $doCampaigns->companion = $aFields['companion']; $doCampaigns->comments = $aFields['comments']; $doCampaigns->revenue = $aFields['revenue']; $doCampaigns->revenue_type = $aFields['revenue_type']; $doCampaigns->block = $block; $doCampaigns->capping = $aFields['capping']; $doCampaigns->session_capping = $aFields['session_capping']; if (!empty($aFields['campaignid']) && $aFields['campaignid'] != "null") { $doCampaigns->campaignid = $aFields['campaignid']; $doCampaigns->setEcpmEnabled(); $doCampaigns->update(); } else { $doCampaigns->setEcpmEnabled(); $aFields['campaignid'] = $doCampaigns->insert(); } if ($oComponent) { $oComponent->processCampaignForm($aFields); } // Recalculate priority only when editing a campaign // or moving banners into a newly created, and when: // // - campaign changes status (activated or deactivated) or // - the campaign is active and target/weight are changed // if (!$new_campaign) { $doCampaigns = OA_Dal::staticGetDO('campaigns', $aFields['campaignid']); $status = $doCampaigns->status; switch (true) { case (bool) $status != (bool) $aFields['status_old']: // Run the Maintenance Priority Engine process OA_Maintenance_Priority::scheduleRun(); break; case $status == OA_ENTITY_STATUS_RUNNING: if (!empty($aFields['target_type']) && ${$aFields['target_type']} != $aFields['target_old'] || !empty($aFields['target_type']) && $aFields['target_type_old'] != $aFields['target_type'] || $aFields['weight'] != $aFields['weight_old'] || $aFields['clicks'] != $aFields['previousclicks'] || $aFields['conversions'] != $aFields['previousconversions'] || $aFields['impressions'] != $aFields['previousimpressions']) { // Run the Maintenance Priority Engine process OA_Maintenance_Priority::scheduleRun(); } break; } } // Rebuild cache // include_once MAX_PATH . '/lib/max/deliverycache/cache-'.$conf['delivery']['cache'].'.inc.php'; // phpAds_cacheDelete(); // Delete channel forecasting cache include_once 'Cache/Lite.php'; $options = array('cacheDir' => MAX_CACHE); $cache = new Cache_Lite($options); $group = 'campaign_' . $aFields['campaignid']; $cache->clean($group); $translation = new OX_Translation(); if ($new_campaign) { // Queue confirmation message $translated_message = $translation->translate($GLOBALS['strCampaignHasBeenAdded'], array(MAX::constructURL(MAX_URL_ADMIN, 'campaign-edit.php?clientid=' . $aFields['clientid'] . '&campaignid=' . $aFields['campaignid']), htmlspecialchars($aFields['campaignname']), MAX::constructURL(MAX_URL_ADMIN, 'banner-edit.php?clientid=' . $aFields['clientid'] . '&campaignid=' . $aFields['campaignid']))); OA_Admin_UI::queueMessage($translated_message, 'local', 'confirm', 0); OX_Admin_Redirect::redirect("advertiser-campaigns.php?clientid=" . $aFields['clientid']); } else { $translated_message = $translation->translate($GLOBALS['strCampaignHasBeenUpdated'], array(MAX::constructURL(MAX_URL_ADMIN, 'campaign-edit.php?clientid=' . $aFields['clientid'] . '&campaignid=' . $aFields['campaignid']), htmlspecialchars($aFields['campaignname']))); OA_Admin_UI::queueMessage($translated_message, 'local', 'confirm', 0); OX_Admin_Redirect::redirect("campaign-edit.php?clientid=" . $aFields['clientid'] . "&campaignid=" . $aFields['campaignid']); } } //return processing errors return $errors; }
function setDefaultValue($fieldName, $fieldType) { if (isset($this->defaultValues[$fieldName])) { if ($this->defaultValues[$fieldName] === '%DATE_TIME%') { return date('Y-m-d H:i:s'); } else { if ($this->defaultValues[$fieldName] === '%NO_DATE_TIME%') { return OA_Dal::noDateValue(); } } return $this->defaultValues[$fieldName]; } else { if ($fieldName == 'updated') { return date('Y-m-d H:i:s'); } } return NULL; }
/** * Returns true if $sqlDate is not an 'empty' date, false otherwise. * * @static * @param string $sqlDate */ function isValidDate($sqlDate) { $dbh = OA_DB::singleton(); return preg_match('#\\d\\d\\d\\d-\\d\\d-\\d\\d#', $sqlDate) && $sqlDate != OA_Dal::noDateValue(); }
/** * A method to distribute the calculated required campaign impressions between the campaign's * children advertisements. Impression allocation takes in to account ad weight, and the number * of operations intervals the ad will be active in given date/time delivery limitations, and * the pattern of available impressions for the zone(s) the advertisements are linked to. * * The calculated ad impressions are written to the temporary table tmp_ad_required_impression * for later analysis by the {@link OA_Maintenance_Priority_AdServer_Task_AllocateZoneImpressions} * class. * * @param array $aCampaigns An array of {@link OX_Maintenance_Priority_Campaign} objects which require * that their total required impressions be distributed between the * component advertisements. */ function distributeCampaignImpressions($aCampaigns) { // Create an array for storing required ad impressions $aRequiredAdImpressions = array(); // Get the current operation interval start/end dates $aCurrentOperationIntervalDates = OX_OperationInterval::convertDateToOperationIntervalStartAndEndDates($this->_getDate()); // For each campaign foreach ($aCampaigns as $oCampaign) { OA::debug(' - Distributing impression inventory requirements for campaign ID: ' . $oCampaign->id, PEAR_LOG_DEBUG); $adsCount = count($oCampaign->aAds); if ($adsCount == 1) { $adsWord = 'ad'; } else { $adsWord = 'ads'; } OA::debug(" - Campaign has {$adsCount} {$adsWord}.", PEAR_LOG_DEBUG); // Get date object to represent campaign expiration date if ($oCampaign->impressionTargetDaily > 0 || $oCampaign->clickTargetDaily > 0 || $oCampaign->conversionTargetDaily > 0) { // The campaign has a daily target to meet, so treat the // campaign as if it expires at the end of "today", regardless // of the existance of any activation or expiration dates that // may (or may not) be set for the campaign $oDate =& $this->_getDate(); // Get the end of the day from this date $oCampaignExpiryDate = new Date($oDate->format('%Y-%m-%d') . ' 23:59:59'); } else { if ($oCampaign->expire != OA_Dal::noDateValue() && ($oCampaign->impressionTargetTotal > 0 || $oCampaign->clickTargetTotal > 0 || $oCampaign->conversionTargetTotal > 0)) { // The campaign has an expiration date, and has some kind of // (total) inventory requirement, so treat the campaign as if // it expires at the end of the expiration date $oCampaignExpiryDate =& $this->_getDate($oCampaign->expire); // Campaign expires at end of expiry date, so add one day less one // second, so we have a date with time portion 23:59:59 $oCampaignExpiryDate->addSeconds(SECONDS_PER_DAY - 1); } else { // Error! There should not be any other kind of high-priority // campaign in terms of activation/expiration dates and // either (total) inventory requirements or daily targets $message = "- Error calculating the end date for Campaign ID {$oCampaign->id}"; OA::debug($message, PEAR_LOG_ERR); continue; } } // Determine number of remaining operation intervals for campaign $message = " - Calculating campaign remaining operation intervals."; OA::debug($message, PEAR_LOG_DEBUG); $campaignRemainingOperationIntervals = OX_OperationInterval::getIntervalsRemaining($aCurrentOperationIntervalDates['start'], $oCampaignExpiryDate); // For all ads in the campaign, determine: // - If the ad is capable of delivery in the current operation // interval, or not, based on if it is linked to any zones, and, // if so: // - If the ad is capable of delivery in the current operation // interval, or not, based on delivery limitation(s), and if so; // - The result of the weight of the ad multiplied by the // number of operation intervals remaining in which the ad // is capable of delivering $aAdZones = array(); $aAdDeliveryLimtations = array(); $aAdCurrentOperationInterval = array(); $aAdWeightRemainingOperationIntervals = array(); $aInvalidAdIds = array(); reset($oCampaign->aAds); while (list($key, $oAd) = each($oCampaign->aAds)) { // Only calculate values for active ads if ($oAd->active && $oAd->weight > 0) { $message = " - Calculating remaining operation intervals for ad ID: {$oAd->id}"; OA::debug($message, PEAR_LOG_DEBUG); // Get all zones associated with the ad $aAdsZones = $this->oDal->getAdZoneAssociationsByAds(array($oAd->id)); $aAdZones[$oAd->id] = @$aAdsZones[$oAd->id]; if (is_null($aAdZones[$oAd->id])) { $aInvalidAdIds[] = $oAd->id; $message = " - Ad ID {$oAd->id} has no linked zones, will skip..."; OA::debug($message, PEAR_LOG_ERR); continue; } // Prepare a delivery limitation object for the ad $aAdDeliveryLimtations[$oAd->id] = new OA_Maintenance_Priority_DeliveryLimitation($oAd->getDeliveryLimitations()); // Is the ad blocked from delivering in the current operation interval? $aAdCurrentOperationInterval[$oAd->id] = $aAdDeliveryLimtations[$oAd->id]->deliveryBlocked($aCurrentOperationIntervalDates['start']); // Determine how many operation intervals remain that the ad can deliver in $adRemainingOperationIntervals = $aAdDeliveryLimtations[$oAd->id]->getActiveAdOperationIntervals($campaignRemainingOperationIntervals, $aCurrentOperationIntervalDates['start'], $oCampaignExpiryDate); // Determine the value of the ad weight multiplied by the number // of operation intervals remaining that the ad can deliver in if ($oAd->weight > 0) { $aAdWeightRemainingOperationIntervals[$oAd->id] = $oAd->weight * $adRemainingOperationIntervals; } else { $aAdWeightRemainingOperationIntervals[$oAd->id] = 0; } } } // Get the total sum of the ad weight * remaining OI values $sumAdWeightRemainingOperationIntervals = array_sum($aAdWeightRemainingOperationIntervals); // For each (active) ad that is capable of delivering in the current // operation interval, determine how many of the campaign's required // impressions should be alloced as the ad's required impressions // For each advertisement reset($oCampaign->aAds); while (list($key, $oAd) = each($oCampaign->aAds)) { if (in_array($oAd->id, $aInvalidAdIds)) { OA::debug(' - Skipping ad ID: ' . $oAd->id, PEAR_LOG_DEBUG); continue; } OA::debug(' - Caclulating required impressions for ad ID: ' . $oAd->id, PEAR_LOG_DEBUG); // Get impressions required $totalRequiredAdImpressions = 0; if ($oAd->active && $oAd->weight > 0 && $aAdCurrentOperationInterval[$oAd->id] !== true) { $totalRequiredAdImpressions = $oCampaign->requiredImpressions * ($aAdWeightRemainingOperationIntervals[$oAd->id] / $sumAdWeightRemainingOperationIntervals); } if ($totalRequiredAdImpressions <= 0) { OA::debug(' - No required impressions for ad ID: ' . $oAd->id, PEAR_LOG_DEBUG); continue; } // Based on the average zone pattern of the zones the ad is // linked to, calculate how many of these impressions should // be delivered in the next operation interval OA::debug(' - Caclulating next OI required impressions for ad ID: ' . $oAd->id, PEAR_LOG_DEBUG); $oAd->requiredImpressions = $this->_getAdImpressions($oAd, $totalRequiredAdImpressions, $aCurrentOperationIntervalDates['start'], $oCampaignExpiryDate, $aAdDeliveryLimtations[$oAd->id], $aAdZones[$oAd->id]); $aRequiredAdImpressions[] = array('ad_id' => $oAd->id, 'required_impressions' => $oAd->requiredImpressions); } } // Save the required impressions into the temporary database table OA::setTempDebugPrefix('- '); // Check if table exists if (!isset($GLOBALS['_OA']['DB_TABLES']['tmp_ad_required_impression'])) { if ($this->oTable->createTable('tmp_ad_required_impression', null, true) !== false) { // Remember that table was created $GLOBALS['_OA']['DB_TABLES']['tmp_ad_required_impression'] = true; } } $this->oDal->saveRequiredAdImpressions($aRequiredAdImpressions); }
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); $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 && $aCampaign['expire'] != OA_Dal::noDateValue()) { // 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'] . ' 23:59:59'); // Convert day to end of Date $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; }