public function __construct($oStart, $oEnd, $aEntityParams) { $oNow = new Date(); $this->oStart = $oNow->before($oStart) ? $oNow : $oStart; $this->oEnd = $oNow->before($oEnd) ? $oNow : $oEnd; $this->parseEntityParams($aEntityParams); }
/** * A method to test the getPlacementFirstStatsDate() method. * * Requirements: * Test 1: Test with an invalid placement ID, and ensure null is returned. * Test 2: Test with no data in the database, and ensure current date is returned. * Test 3: Test with single row in the database, and ensure correct date is * returned. * Test 4: Test with multi rows in the database, and ensure correct date is * returned. */ function testGetPlacementFirstStatsDate() { $conf =& $GLOBALS['_MAX']['CONF']; $oDbh =& OA_DB::singleton(); $oDalStatistics = new MAX_Dal_Statistics(); // Test 1 $placementId = 'foo'; $oResult = $oDalStatistics->getPlacementFirstStatsDate($placementId); $this->assertNull($oResult); // Test 2 $placementId = 1; $oBeforeDate = new Date(); sleep(1); $oResult = $oDalStatistics->getPlacementFirstStatsDate($placementId); sleep(1); $oAfterDate = new Date(); $this->assertTrue(is_a($oResult, 'Date')); $this->assertTrue($oBeforeDate->before($oResult)); $this->assertTrue($oAfterDate->after($oResult)); // Test 3 $oNow = new Date(); $aData = array('campaignid' => $placementId, 'active' => 't', 'updated' => $oNow->format('%Y-%m-%d %H:%M:%S'), 'acls_updated' => $oNow->format('%Y-%m-%d %H:%M:%S')); $idBanner1 = $this->_insertBanner($aData); $aData = array('day' => '2006-10-30', 'hour' => 12, 'ad_id' => $idBanner1, 'updated' => $oNow->format('%Y-%m-%d %H:%M:%S')); $idDSAH1 = $this->_insertDataSummaryAdHourly($aData); $oResult = $oDalStatistics->getPlacementFirstStatsDate($placementId); $oExpectedDate = new Date('2006-10-30 12:00:00'); $this->assertEqual($oResult, $oExpectedDate); // Test 4 $aData = array('campaignid' => $placementId, 'active' => 't', 'updated' => $oNow->format('%Y-%m-%d %H:%M:%S'), 'acls_updated' => $oNow->format('%Y-%m-%d %H:%M:%S')); $idBanner2 = $this->_insertBanner($aData); $aData = array('campaignid' => 999, 'active' => 't', 'updated' => $oNow->format('%Y-%m-%d %H:%M:%S'), 'acls_updated' => $oNow->format('%Y-%m-%d %H:%M:%S')); $idBanner3 = $this->_insertBanner($aData); $aData = array('day' => '2006-10-29', 'hour' => 12, 'ad_id' => $idBanner2, 'updated' => $oNow->format('%Y-%m-%d %H:%M:%S')); $idDSAH1 = $this->_insertDataSummaryAdHourly($aData); $aData = array('day' => '2006-10-28', 'hour' => 12, 'ad_id' => $idBanner2, 'updated' => $oNow->format('%Y-%m-%d %H:%M:%S')); $idDSAH2 = $this->_insertDataSummaryAdHourly($aData); $aData = array('day' => '2006-10-27', 'hour' => 12, 'ad_id' => $idBanner2, 'updated' => $oNow->format('%Y-%m-%d %H:%M:%S')); $idDSAH3 = $this->_insertDataSummaryAdHourly($aData); $aData = array('day' => '2006-10-26', 'hour' => 12, 'ad_id' => 999, 'updated' => $oNow->format('%Y-%m-%d %H:%M:%S')); $idDSAH4 = $this->_insertDataSummaryAdHourly($aData); $oResult = $oDalStatistics->getPlacementFirstStatsDate($placementId); $oExpectedDate = new Date('2006-10-27 12:00:00'); $this->assertEqual($oResult, $oExpectedDate); DataGenerator::cleanUp(); }
/** * A method to check if the campaign is awaiting activation * * @return bool */ function _isAwaiting() { static $oServiceLocator; // MySQL null date hardcoded for optimisation if (!empty($this->activate) && $this->activate != '0000-00-00') { if (!isset($oServiceLocator)) { $oServiceLocator =& OA_ServiceLocator::instance(); } if (!($oNow = $oServiceLocator->get('now'))) { $oNow = new Date(); } $oActivate = new Date($this->activate); if (!empty($this->clientid)) { // Set timezone $aAccounts = $this->getOwningAccountIds(); $aPrefs = OA_Preferences::loadAccountPreferences($aAccounts[OA_ACCOUNT_ADVERTISER], true); if (isset($aPrefs['timezone'])) { $oActivate->setTZbyID($aPrefs['timezone']); } } if ($oNow->before($oActivate)) { return true; } } return false; }
/** * A method to calculate the range of dates that a statistics screen needs to display. * * Returns an array of values where: * * - If "week" or "day" is the breakdown, array is of days, indexed by "YYYY-MM-DD", * and formatted using the user's local format for days. * * - If "month" is the breakdown, array is of months, indexed by "YYYY-MM", * and formatted using the user's local format for months and days. * * - If "dow" is the breakdown, array is of days of the week, indexed by the integers * 0 to 6, and formatted with the user's local weekday names. * * - If "hour" is the breakdown, array is of hours of the day, indexed by the integers * 0 to 23, and formatted in the format "00:00 - 00:59", "01:00 01:59", etc. * * @param array $aDates An array of the start and end dates in use by the day * span selector element, if set. * @param string $breakdown The breakdown type in use. One of "week", "day", "month", * "dow" or "hour". * @param PEAR::Date $oStatsStartDate A date object representing the first day of statistics * that are available. * @return array The array, as described above. */ function getDatesArray($aDates, $breakdown, $oStatsStartDate) { // Does the day span selector element have dates set? if ($aDates['day_begin'] && $aDates['day_end'] || $aDates['period_start'] && $aDates['period_end']) { if ($aDates['day_begin'] && $aDates['day_end']) { // Use the dates given by the day span selector element $oStartDate = new Date($aDates['day_begin']); $oEndDate = new Date($aDates['day_end']); } else { // Use the dates given by the period_start and period_end $oStartDate = new Date($aDates['period_start']); $oEndDate = new Date($aDates['period_end']); } // Adjust end date to be now, if it's in the future if ($oEndDate->isFuture()) { $oEndDate = new Date(); $aDates['day_end'] = new Date(); $aDates['day_end'] = $aDates['day_end']->format('%Y-%m-%d'); } } else { // Use the dates given by the statistics date limitation // and now $oStartDate = new Date(); $oStartDate->copy($oStatsStartDate); $oEndDate = new Date(); } // Prepare the return array $aDatesResult = array(); switch ($breakdown) { case 'week': case 'day': $oOneDaySpan = new Date_Span('1', '%d'); $oEndDate->addSpan($oOneDaySpan); $oDate = new Date(); $oDate->copy($oStartDate); while ($oDate->before($oEndDate)) { $aDatesResult[$oDate->format('%Y-%m-%d')] = $oDate->format($GLOBALS['date_format']); $oDate->addSpan($oOneDaySpan); } break; case 'month': $oOneMonthSpan = new Date_Span((string) ($oEndDate->getDaysInMonth() - $oEndDate->getDay() + 1), '%d'); $oEndDate->addSpan($oOneMonthSpan); $oDate = new Date(); $oDate->copy($oStartDate); while ($oDate->before($oEndDate)) { $aDatesResult[$oDate->format('%Y-%m')] = $oDate->format($GLOBALS['month_format']); $oOneMonthSpan = new Date_Span((string) ($oDate->getDaysInMonth() - $oDate->getDay() + 1), '%d'); $oDate->addSpan($oOneMonthSpan); } break; case 'dow': for ($dow = 0; $dow < 7; $dow++) { $aDatesResult[$dow] = $GLOBALS['strDayFullNames'][$dow]; } break; case 'hour': for ($hour = 0; $hour < 24; $hour++) { $aDatesResult[$hour] = sprintf('%02d:00 - %02d:59', $hour, $hour); } break; } return $aDatesResult; }
/** * A method for obtaining the targeting statistics of an ad or placement * for a single day, where the data is summarised by operation interval. * * @param integer $id The ad or placement ID. * @param string $type Either "ad" or "placement". * @param PEAR::Date $oDate A date representing the day required. * * @return mixed Returns false in the event of incorrect input, or in the case * of being unable to connect to the database, otherwise, returns * an array of arrays: * * * array( * [$operationIntervalId] => array( * ['interval_start'] => PEAR::Date * ['interval_end'] => PEAR::Date * ['ad_required_impressions'] => integer * ['ad_requested_impressions'] => integer * ['ad_actual_impressions'] => integer * ['zones_forecast_impressions'] => integer * ['zones_actual_impressions'] => integer * ['average'] => integer * ) * . * . * . * ) * * or: * * array( * [$operationIntervalId] => array( * ['interval_start'] => PEAR::Date * ['interval_end'] => PEAR::Date * ['placement_required_impressions'] => integer * ['placement_requested_impressions'] => integer * ['placement_actual_impressions'] => integer * ['zones_forecast_impressions'] => integer * ['zones_actual_impressions'] => integer * ['average'] => integer * ) * . * . * . * ) * * For the ad or placement and day specified, returns an array for each * operation interval in the day, consisting of the operation interval start * and end dates, and the total number of impressions requested by the ad, or * all ads in the placement (for all zones the ads are linked to), as well as * the total number of impressions actually delivered by the ad, or all ads * in the placement (for all zones the ads are linked to). * * The individual ad/zone impressions requested values may need to be * calculated as an "averge" value, in the event that there are multiple, * differing values for an ad in a zone for an operation interval -- in * much the same way as is done in * OA_Dal_Maintenance_Priority::getPreviousAdDeliveryInfo() -- before * the total impressions requested value can be calculated. */ function getDailyTargetingStatistics($id, $type, $oDate) { if (!$this->_testGetTargetingStatisticsDayParameters($id, $type, $oDate)) { return false; } // Ensure that, if a placement, the placement has advertisements $aAdIds = $this->_testGetTargetingStatisticsSpanPlacement($id, $type); if ($aAdIds === false) { return false; } // Prepare the results array $aResult = array(); // Get a date for the start of the day $oStartDate = new Date(); $oStartDate->copy($oDate); $oStartDate->setHour(0); $oStartDate->setMinute(0); $oStartDate->setSecond(0); // Get a date for the end of the day $oEndOfDayDate = new Date(); $oEndOfDayDate->copy($oDate); $oEndOfDayDate->setHour(23); $oEndOfDayDate->setMinute(59); $oEndOfDayDate->setSecond(59); // Get the first operation interval of the day $aDates = OX_OperationInterval::convertDateToOperationIntervalStartAndEndDates($oStartDate); // Get dates to be used in date comparisons $oCompareDate = new Date(); $oCompareDate->copy($aDates['start']); $oCompareEndDate = new Date(); $oCompareEndDate->copy($oEndOfDayDate); while ($oCompareDate->before($oEndOfDayDate)) { // Get the operation interval ID $operationIntervalId = OX_OperationInterval::convertDateToOperationIntervalID($aDates['start']); // Get the results for this operation interval $aResult[$operationIntervalId] = $this->getOperationIntervalTargetingStatistics($aAdIds, $type, $aDates['start'], $aDates['end']); if ($aResult[$operationIntervalId] === false) { return false; } // Get the next operation interval dates $aDates = OX_OperationInterval::convertDateToNextOperationIntervalStartAndEndDates($aDates['start']); // Update the comparison dates $oCompareDate = new Date(); $oCompareDate->copy($aDates['start']); $oCompareEndDate = new Date(); $oCompareEndDate->copy($oEndOfDayDate); } return $aResult; }
/** * A method to get the most recent details of contract campaign creative delivery * for a given list of creative/zone pairs set to deliver in the current * operation interval. Normally, the data will be retrieved from the previous * operation interval, but if no data exists for that creative/zone pair, then the * next previous operation interval will be tried, and so on, up to a limit * of MAX_PREVIOUS_AD_DELIVERY_INFO_LIMIT minutes (default is one week). * * - Requires that a current day/time (as a Date object) be registered * with the OA_ServiceLocator (as "now"). * * - Ignores creative ID 0 and zone ID 0 items, as these are reserved for * direct selection, which is considered to be outside the process of * priority compensation calculations (even though priority values for * all contract campaign creatives are calculated and stored for the * zone ID 0). * * Note: The logic of this method seems a little convoluted, and it is. * However, it needs to be. The reason being: * * - If a contract campaign creative delivered in the previous operation interval, * then it should have had a priority set in ad_zone_assoc (that's how OpenX * knows to deliver contract campiang creatives, natch!). This should be the most * recent entry in data_summary_ad_zone_assoc. So, the first step is to get the * data for all contract campiang creatives that have delivered in the previous * OI, and the associated prioritisation data. * - If a contract campaign creative did not deliver, the prioritisation data set * in the previous OI is still needed anyway (as it might have been *supposed* * to deliver), so the second step is to get those creatives that had * prioiritisation data set in the previous OI, but did not deliver. * - Finally, as some creatives are limited by hour (for example), we want to * to be able to get past prioritisation data for creatives that were * disabled in the last OI, so, we need to look for creative/zone pairs * that have not yet been found, and get BOTH the prioritisation AND the * delivery data from the last OI when the creatives were active in the * zones. * * This is why the method uses a complex, 3 step process! * * @access public * @param array $aCurrentZones An array of Zones, indexed by Zone ID, with each * Zone containing the Advert objects that are linked * to deliver in the zone, in the current operation * interval. * @return mixed An array of arrays of arrays, each one representing a set of * ad/zone delivery information, indexed by ad ID and zone ID. * Each sub-sub array, if present, has the format: * array ( * 'ad_id' => integer * 'zone_id' => integer * 'required_impressions' => integer * 'requested_impressions' => integer * 'priority_factor' => double * 'past_zone_traffic_fraction' => double * 'impressions' => integer * ) * Returns false when the current date/time is not set in the * OA_ServiceLocator. */ function &getPreviousAdDeliveryInfo($aCurrentZones) { OA::debug(" - Getting details of previous creative/zone delivery", PEAR_LOG_DEBUG); $aConf = $GLOBALS['_MAX']['CONF']; $oServiceLocator =& OA_ServiceLocator::instance(); $oDate =& $oServiceLocator->get('now'); if (!$oDate) { return false; } $aAds = array(); $aZones = array(); $aZonesAds = array(); $aPastDeliveryResult = array(); $aPastPriorityResult = array(); $aNonDeliveringPastPriorityResult = array(); $aFinalResult = array(); // Obtain the earliest existing interval_start date found in the // data_summary_ad_zone_assoc table $table = $this->_getTablename('data_summary_ad_zone_assoc'); $query = "\n SELECT\n interval_start AS interval_start\n FROM\n {$table}\n ORDER BY\n interval_start\n LIMIT\n 1"; $rc = $this->oDbh->query($query); if (!PEAR::isError($rc) && $rc->numRows() == 1) { $aRow = $rc->fetchRow(); $oEarliestPastPriorityRecordDate = new Date($aRow['interval_start']); // Create a new date that is the limit number of minutes ago $oLimitDate = new Date(); $oLimitDate->copy($oDate); $oLimitDate->subtractSeconds(MAX_PREVIOUS_AD_DELIVERY_INFO_LIMIT * 60); // Is the earliest date before this date? if ($oEarliestPastPriorityRecordDate->before($oLimitDate)) { // Use the limit date instead $oEarliestPastPriorityRecordDate = new Date(); $oEarliestPastPriorityRecordDate->copy($oLimitDate); } } // Obtain the operation interval ID, and the start and end dates of the previous // operation interval $currentOperationIntervalID = OX_OperationInterval::convertDateToOperationIntervalID($oDate); $previousOperationIntervalID = OX_OperationInterval::previousOperationIntervalID($currentOperationIntervalID); $aDates = OX_OperationInterval::convertDateToPreviousOperationIntervalStartAndEndDates($oDate); // Obtain the ad ID, zone ID and number of impressions delivered for every ad/zone // combination that delivered impressions in the previous operation interval, where // the ad is from a contract campaign (as we don't care about other campaign types) OA::debug(" - Getting details of contract campaign creative/zone pairs that delivered last OI", PEAR_LOG_DEBUG); $sDataIntermediateAd = $this->_getTablename('data_intermediate_ad'); $sBanners = $this->_getTablename('banners'); $sCampaigns = $this->_getTablename('campaigns'); $query = "\n SELECT\n ad_id AS ad_id,\n zone_id AS zone_id,\n SUM(impressions) AS impressions\n FROM\n {$sDataIntermediateAd} AS dia,\n {$sBanners} AS b,\n {$sCampaigns} AS c\n WHERE\n dia.operation_interval = {$aConf['maintenance']['operationInterval']}\n AND\n dia.operation_interval_id = {$previousOperationIntervalID}\n AND\n dia.interval_start = '" . $aDates['start']->format('%Y-%m-%d %H:%M:%S') . "'\n AND\n dia.interval_end = '" . $aDates['end']->format('%Y-%m-%d %H:%M:%S') . "'\n AND\n dia.ad_id != 0\n AND\n dia.zone_id != 0\n AND\n dia.ad_id = b.bannerid\n AND\n b.campaignid = c.campaignid\n AND\n c.priority > 0\n GROUP BY\n ad_id,\n zone_id\n ORDER BY\n ad_id,\n zone_id"; $rc = $this->oDbh->query($query); while ($aRow = $rc->fetchRow()) { // Store the ad ID as being one that has delivered $aAds[$aRow['ad_id']] = $aRow['ad_id']; // Store the zone ID as one that had impressions in it $aZones[$aRow['zone_id']] = $aRow['zone_id']; // Store the ad IDs by zone ID $aZonesAds[$aRow['zone_id']][$aRow['ad_id']] = true; // Store the impressions delivered for the contract campaign creative/zone pair, // and that the past priority information for this contract campiang creative/zone // pair has not been found yet (it will be found later on) $aPastDeliveryResult[$aRow['ad_id']][$aRow['zone_id']]['impressions'] = $aRow['impressions']; $aPastDeliveryResult[$aRow['ad_id']][$aRow['zone_id']]['pastPriorityFound'] = false; } // Did any ads deliver last operation interval? if (!empty($aAds)) { // Is there past deliver data? if (isset($oEarliestPastPriorityRecordDate)) { // As all of the above contract capiang creative/zone combinations delivered impressions // in the previous operation interval, a priority value must have existed. However, the // priority value may *not* have come from the previous interval, as maintenance may not // have been run (although it should have ;-) // To be sure, interate backwards over past operation intervals (up to the earliest // existing record), obtaining the details of the impressions requested and the priority // values used for the above combinations $previousOperationIntervalIDLoop = $previousOperationIntervalID; $aDatesLoop = array(); $aDatesLoop['start'] = new Date(); $aDatesLoop['start']->copy($aDates['start']); $aDatesLoop['end'] = new Date(); $aDatesLoop['end']->copy($aDates['end']); $foundAll = false; while (!$foundAll) { if (!empty($aAds) && !empty($aZones)) { OA::debug(' - Getting past details of contract campiang creative/zone pairs for OI starting at ' . $aDatesLoop['start']->format('%Y-%m-%d %H:%M:%S'), PEAR_LOG_DEBUG); $table = $this->_getTablename('data_summary_ad_zone_assoc'); $query = "\n SELECT\n ad_id AS ad_id,\n zone_id AS zone_id,\n required_impressions AS required_impressions,\n requested_impressions AS requested_impressions,\n to_be_delivered AS to_be_delivered,\n priority_factor AS priority_factor,\n past_zone_traffic_fraction AS past_zone_traffic_fraction,\n created AS created,\n expired AS expired\n FROM\n {$table}\n WHERE\n ad_id IN (" . implode(', ', $aAds) . ")\n AND\n zone_id IN (" . implode(', ', $aZones) . ")\n AND\n operation_interval = {$aConf['maintenance']['operationInterval']}\n AND\n operation_interval_id = {$previousOperationIntervalIDLoop}\n AND\n interval_start = '" . $aDatesLoop['start']->format('%Y-%m-%d %H:%M:%S') . "'\n AND\n interval_end = '" . $aDatesLoop['end']->format('%Y-%m-%d %H:%M:%S') . "'\n ORDER BY\n ad_id,\n zone_id"; $rc = $this->oDbh->query($query); $aResult = $rc->fetchAll(); // Calculate the past priority results, using $aPastDeliveryResult in the call to // _calculateAveragePastPriorityValues(), so that if this is the second (or greater) // time this has been done then any contract campiang creative/zone pairs that have // come up with details for a second (or greater) time (i.e. as a result of a priority // value record from an earise operation interval as we iterate backwards in time) will // NOT have its past priority info re-calculated with the wrong values $this->_calculateAveragePastPriorityValues($aPastPriorityResult, $aResult, $oDate, $aPastDeliveryResult); // Loop over the results, marking off the contract campiang banner/zone // combinations in the past delivery array as having had their past prioritisation // information found and/or calculated if (!empty($aPastPriorityResult)) { foreach ($aPastPriorityResult as $a => $aAd) { foreach ($aAd as $z => $aZone) { if ($aZone['pastPriorityFound']) { $aPastDeliveryResult[$a][$z]['pastPriorityFound'] = true; } } } } } // Look over the past delivery array to see if there are any contract campaign creative/zone // combinations that do not yet have the past prioritisation information $foundAll = true; if (!empty($aPastDeliveryResult)) { foreach ($aPastDeliveryResult as $a => $aAd) { $remove = true; foreach ($aAd as $z => $aZone) { if (!$aPastDeliveryResult[$a][$z]['pastPriorityFound']) { if ($foundAll) { // Need to go back in time to look for more past priority info $previousOperationIntervalIDLoop = OX_OperationInterval::previousOperationIntervalID($previousOperationIntervalIDLoop); $aDatesLoop = OX_OperationInterval::convertDateToPreviousOperationIntervalStartAndEndDates($aDatesLoop['start']); if (!$aDatesLoop['start']->before($oEarliestPastPriorityRecordDate)) { // Haven't exceeded earliest priority info date, so okay // to go ahead with going back in time... $foundAll = false; } } $remove = false; } // Remove the contract campaign creative from the list of creatives to select // from next round, and check if this was the last creative in the zone, and, // if so, also remove the zone from the list of zones to select from // next round if ($remove) { unset($aAds[$a]); unset($aZonesAds[$z][$a]); if (count($aZonesAds[$z]) == 0) { unset($aZones[$z]); } } } } } } } // Merge the past priority and delivery values into the final results array if (!empty($aPastDeliveryResult)) { foreach ($aPastDeliveryResult as $a => $aAd) { foreach ($aAd as $z => $aZone) { $aFinalResult[$a][$z] = array('ad_id' => $a, 'zone_id' => $z, 'required_impressions' => $aPastPriorityResult[$a][$z]['required_impressions'], 'requested_impressions' => $aPastPriorityResult[$a][$z]['requested_impressions'], 'to_be_delivered' => $aPastPriorityResult[$a][$z]['to_be_delivered'], 'priority_factor' => $aPastPriorityResult[$a][$z]['priority_factor'], 'past_zone_traffic_fraction' => $aPastPriorityResult[$a][$z]['past_zone_traffic_fraction'], 'impressions' => $aPastDeliveryResult[$a][$z]['impressions']); } } } } // Select the details of all contract campaign creative/zones that had required/requested impressions, // in the previous operation interval, but for which no impressions were delivered OA::debug(' - Getting details of contract campaign creative/zone pairs that did not deliver last OI (but should have)', PEAR_LOG_DEBUG); $table1 = $this->_getTablename('data_summary_ad_zone_assoc'); $table2 = $this->_getTablename('data_intermediate_ad'); $oneHourInterval = OA_Dal::quoteInterval(1, 'hour'); // we have to do this complicated MINUS query (mysql doesn't support MINUS so we do a LEFT JOIN exclude not matching) // and we do two subqueries in order to use the INDEXes as expected // note the trick that we use range lookup on the date_time field as this is the one that is indexed $query = "\n SELECT dsaza.*\n FROM (\n SELECT\n ad_id AS ad_id,\n zone_id AS zone_id,\n required_impressions AS required_impressions,\n requested_impressions AS requested_impressions,\n to_be_delivered AS to_be_delivered,\n priority_factor AS priority_factor,\n past_zone_traffic_fraction AS past_zone_traffic_fraction,\n created AS created,\n expired AS expired\n FROM\n {$table1} AS dsaza\n WHERE\n operation_interval = {$aConf['maintenance']['operationInterval']}\n AND\n operation_interval_id = {$previousOperationIntervalID}\n AND\n interval_start = '" . $aDates['start']->format('%Y-%m-%d %H:%M:%S') . "'\n AND\n interval_end = '" . $aDates['end']->format('%Y-%m-%d %H:%M:%S') . "'\n AND\n ad_id != 0\n AND\n zone_id != 0\n AND\n required_impressions > 0\n AND\n requested_impressions > 0\n ORDER BY\n ad_id,\n zone_id\n ) as dsaza\n LEFT JOIN\n (\n \tSELECT\n \t\tad_id,\n \t\tzone_id\n \tFROM\n \t{$table2} AS dia\n WHERE\n operation_interval = {$aConf['maintenance']['operationInterval']}\n AND\n operation_interval_id = {$previousOperationIntervalID}\n AND\n interval_start = '" . $aDates['start']->format('%Y-%m-%d %H:%M:%S') . "'\n AND\n interval_end = '" . $aDates['end']->format('%Y-%m-%d %H:%M:%S') . "'\n AND\n date_time > DATE_SUB('" . $aDates['start']->format('%Y-%m-%d %H:%M:%S') . "', {$oneHourInterval})\n AND\n date_time < DATE_ADD('" . $aDates['start']->format('%Y-%m-%d %H:%M:%S') . "', {$oneHourInterval})\n ORDER BY\n ad_id,\n zone_id\n ) as dia\n ON\n dsaza.ad_id = dia.ad_id\n AND\n dsaza.zone_id = dia.zone_id\n WHERE\n dia.ad_id IS NULL\n AND\n dia.zone_id IS NULL\n "; $rc = $this->oDbh->query($query); $aResult = $rc->fetchAll(); $resultCount = count($aResult); OA::debug(' - Found ' . $resultCount . ' contract campaign creative/zone pairs that did not deliver last OI (but should have)', PEAR_LOG_DEBUG); if ($resultCount > 0) { // Calculate the past priority results, but without the optional parameter to // _calculateAveragePastPriorityValues(), as this is a single calculation on data // in the past OI, and no further looping back over time will occur OA::debug(' - Getting past details of the non-delivering contract campiang creative/zone pairs', PEAR_LOG_DEBUG); $this->_calculateAveragePastPriorityValues($aNonDeliveringPastPriorityResult, $aResult, $oDate); // Merge the past priority values into the final results array if (!empty($aNonDeliveringPastPriorityResult)) { foreach ($aNonDeliveringPastPriorityResult as $a => $aAd) { foreach ($aAd as $z => $aZone) { if (empty($aFinalResult[$a][$z])) { $aFinalResult[$a][$z] = array('ad_id' => $a, 'zone_id' => $z, 'required_impressions' => $aNonDeliveringPastPriorityResult[$a][$z]['required_impressions'], 'requested_impressions' => $aNonDeliveringPastPriorityResult[$a][$z]['requested_impressions'], 'to_be_delivered' => $aNonDeliveringPastPriorityResult[$a][$z]['to_be_delivered'], 'priority_factor' => $aNonDeliveringPastPriorityResult[$a][$z]['priority_factor'], 'past_zone_traffic_fraction' => $aNonDeliveringPastPriorityResult[$a][$z]['past_zone_traffic_fraction']); } } } } } // Finally, now that all contract campaign creative/zone combinations that had required/requested // impressions in the previous operation interval and delivered/didn't deliver issues have been // dealt with, check to see if there are any contract campaign creative/zone combinations that are // linked to deliver in the current operation interval, which are not covered by the above OA::debug(' - Finding contract campaign creative/zone pairs set to deliver, but with no past data yet', PEAR_LOG_DEBUG); $aAds = array(); $aZones = array(); $aZonesAds = array(); $aNotInLastOIPastDeliveryResult = array(); $aNotInLastOIPastPriorityResult = array(); if (is_array($aCurrentZones) && !empty($aCurrentZones)) { foreach ($aCurrentZones as $zoneId => $oZone) { // Ignore Zone ID 0, as data for this zone is not required (there will no be // priority compensation performed on this zone, the past data is not relevant) if ($oZone->id != 0) { if (is_array($oZone->aAdverts) && !empty($oZone->aAdverts)) { foreach ($oZone->aAdverts as $oAdvert) { // Store that the past priority information for this contract campiagn creative/zone // pair may not have yet been found $aNotInLastOIPastDeliveryResult[$oAdvert->id][$zoneId]['pastPriorityFound'] = false; } } } } } // Remove those contract campiagn creative/zone pairs that have, // in fact, already had their past priority information found if (!empty($aFinalResult)) { foreach ($aFinalResult as $aResult) { if (isset($aResult['ad_id'])) { unset($aNotInLastOIPastDeliveryResult[$aResult['ad_id']][$aResult['zone_id']]); } } foreach ($aNotInLastOIPastDeliveryResult as $adKey => $aTestZone) { if (empty($aTestZone)) { unset($aNotInLastOIPastDeliveryResult[$adKey]); } } } // Create the sets of required creatives and zones that need their past priority // information from older operation intervals found (exluding zone ID 0, as this // is not required) if (!empty($aNotInLastOIPastDeliveryResult)) { foreach ($aNotInLastOIPastDeliveryResult as $adKey => $aData) { // Store the creative ID as being one that needs to deliver $aAds[$adKey] = $adKey; foreach ($aData as $zoneKey => $value) { // Store the zone ID as one that has a creative that needs to deliver in it $aZones[$zoneKey] = $zoneKey; // Store the creative ID by zone ID $aZonesAds[$zoneKey][$adKey] = true; } } } // Are there any contract campiagn creative/zone pairs that need data? if (!empty($aNotInLastOIPastDeliveryResult)) { // Is there past delivery data? if (isset($oEarliestPastPriorityRecordDate)) { // Loop over the previous operation intervals, starting with the one // *before* last, and find when (if possible) these contract campiagn // creative/zone pairs last *requested* to deliver; it doesn't matter if // they did deliver in that operation interval or not $previousOperationIntervalIDLoop = OX_OperationInterval::previousOperationIntervalID($previousOperationIntervalID); $aDatesLoop = OX_OperationInterval::convertDateToPreviousOperationIntervalStartAndEndDates($aDates['start']); $foundAll = false; while (!$foundAll) { if (!empty($aAds) && !empty($aZones)) { OA::debug(' - Getting past details of contract campiagn creative/zone pairs which did not deliver last OI, for OI ' . 'starting at ' . $aDatesLoop['start']->format('%Y-%m-%d %H:%M:%S'), PEAR_LOG_DEBUG); $table = $this->_getTablename('data_summary_ad_zone_assoc'); $query = "\n SELECT\n ad_id AS ad_id,\n zone_id AS zone_id,\n required_impressions AS required_impressions,\n requested_impressions AS requested_impressions,\n to_be_delivered AS to_be_delivered,\n priority_factor AS priority_factor,\n past_zone_traffic_fraction AS past_zone_traffic_fraction,\n created AS created,\n expired AS expired,\n operation_interval AS operation_interval,\n operation_interval_id AS operation_interval_id,\n interval_start AS interval_start,\n interval_end AS interval_end\n FROM\n {$table}\n WHERE\n ad_id IN (" . implode(', ', $aAds) . ")\n AND\n zone_id IN (" . implode(', ', $aZones) . ")\n AND\n operation_interval = {$aConf['maintenance']['operationInterval']}\n AND\n operation_interval_id = {$previousOperationIntervalIDLoop}\n AND\n interval_start = '" . $aDatesLoop['start']->format('%Y-%m-%d %H:%M:%S') . "'\n AND\n interval_end = '" . $aDatesLoop['end']->format('%Y-%m-%d %H:%M:%S') . "'\n ORDER BY\n ad_id,\n zone_id"; $rc = $this->oDbh->query($query); $aResult = $rc->fetchAll(); // Calculate the past priority results, using $aPastDeliveryResult in the call to // _calculateAveragePastPriorityValues(), so that if this is the second (or greater) // time this has been done then any contract campiang creative/zone pairs that have // come up with details for a second (or greater) time (i.e. as a result of a priority // value record from an earise operation interval as we iterate backwards in time) will // NOT have its past priority info re-calculated with the wrong values $this->_calculateAveragePastPriorityValues($aNotInLastOIPastPriorityResult, $aResult, $oDate, $aNotInLastOIPastDeliveryResult); // Loop over the results, marking off the contract campiagn creative/zone // combinations in the past delivery array as having had their past prioritisation // information found and/or calculated if (!empty($aNotInLastOIPastPriorityResult)) { foreach ($aNotInLastOIPastPriorityResult as $a => $aAd) { foreach ($aAd as $z => $aZone) { if ($aZone['pastPriorityFound']) { $aNotInLastOIPastDeliveryResult[$a][$z]['pastPriorityFound'] = true; } } } } // Look over the past delivery array to see if there are any contract campiagn creative/zone // combinations that do not yet have the past prioritisation information $foundAll = true; if (!empty($aNotInLastOIPastDeliveryResult)) { foreach ($aNotInLastOIPastDeliveryResult as $a => $aAd) { $remove = true; foreach ($aAd as $z => $aZone) { if (!$aNotInLastOIPastDeliveryResult[$a][$z]['pastPriorityFound']) { if ($foundAll) { // Need to go back in time to look for more past priority info $previousOperationIntervalIDLoop = OX_OperationInterval::previousOperationIntervalID($previousOperationIntervalIDLoop); $aDatesLoop = OX_OperationInterval::convertDateToPreviousOperationIntervalStartAndEndDates($aDatesLoop['start']); if (!$aDatesLoop['start']->before($oEarliestPastPriorityRecordDate)) { // Haven't exceeded earliest priority info date, so okay // to go ahead with going back in time... $foundAll = false; } } $remove = false; } // Remove the creative from the list of creatives to select from next round, // and check if this was the last creative in the zone, and, if so, // also remove the zone from the list of zones to select from // next round if ($remove) { unset($aAds[$a]); unset($aZonesAds[$z][$a]); if (count($aZonesAds[$z]) == 0) { unset($aZones[$z]); } } } } } } else { $foundAll = true; } } } // Now that it is known when (if) the remaining creatives last requested to deliver, // determine how many impressions were delivered (if any) during the appropriate // operation intervals if (!empty($aNotInLastOIPastPriorityResult)) { $table = $this->_getTablename('data_intermediate_ad'); $oneHourInterval = OA_Dal::quoteInterval(1, 'hour'); $query = "\n SELECT\n SUM(impressions) AS impressions\n FROM\n {$table}\n WHERE\n operation_interval = ?\n AND\n operation_interval_id = ?\n AND\n date_time > DATE_SUB(?, " . $oneHourInterval . ")\n AND\n date_time < DATE_ADD(?, " . $oneHourInterval . ")\n AND\n interval_start = ?\n AND\n interval_end = ?\n AND\n ad_id = ?\n AND\n zone_id = ?"; $aTypes = array('integer', 'integer', 'timestamp', 'timestamp', 'timestamp', 'timestamp', 'integer', 'integer'); $stSelectSumImpressions = $this->oDbh->prepare($query, $aTypes, MDB2_PREPARE_RESULT); OA::debug(' - Looping over each zone linked to ' . count($aNotInLastOIPastPriorityResult) . ' ads'); $countQueriesSumImp = 0; foreach ($aNotInLastOIPastPriorityResult as $a => $aAd) { OA::debug(' - Requesting sum of impressions for ad ID ' . $a . ' for ' . count($aAd) . ' zones ', PEAR_LOG_DEBUG); foreach ($aAd as $z => $aZone) { $aData = array($aNotInLastOIPastPriorityResult[$a][$z]['operation_interval'], $aNotInLastOIPastPriorityResult[$a][$z]['operation_interval_id'], $aNotInLastOIPastPriorityResult[$a][$z]['interval_start'], $aNotInLastOIPastPriorityResult[$a][$z]['interval_start'], $aNotInLastOIPastPriorityResult[$a][$z]['interval_start'], $aNotInLastOIPastPriorityResult[$a][$z]['interval_end'], $a, $z); $rsResult = $stSelectSumImpressions->execute($aData); $aResult = $rsResult->fetchAll(); if (isset($aResult[0]['impressions'])) { $aNotInLastOIPastPriorityResult[$a][$z]['impressions'] = $aResult[0]['impressions']; } $countQueriesSumImp++; } } OA::debug(' - Finished querying impressions for ' . $countQueriesSumImp . ' ad-zones combinations'); } // Merge the past priority and delivery values into the final results array if (!empty($aNotInLastOIPastPriorityResult)) { foreach ($aNotInLastOIPastPriorityResult as $a => $aAd) { foreach ($aAd as $z => $aZone) { if (empty($aFinalResult[$a][$z])) { $aFinalResult[$a][$z] = array('ad_id' => $a, 'zone_id' => $z, 'required_impressions' => $aNotInLastOIPastPriorityResult[$a][$z]['required_impressions'], 'requested_impressions' => $aNotInLastOIPastPriorityResult[$a][$z]['requested_impressions'], 'to_be_delivered' => $aNotInLastOIPastPriorityResult[$a][$z]['to_be_delivered'], 'priority_factor' => $aNotInLastOIPastPriorityResult[$a][$z]['priority_factor'], 'past_zone_traffic_fraction' => $aNotInLastOIPastPriorityResult[$a][$z]['past_zone_traffic_fraction']); if (isset($aNotInLastOIPastPriorityResult[$a][$z]['impressions'])) { $aFinalResult[$a][$z]['impressions'] = $aNotInLastOIPastPriorityResult[$a][$z]['impressions']; } } } } } } return $aFinalResult; }
/** * ??? * * @param integer $zoneId The ID of the zone to be tested. * @param unknown_type $campaignid ??? * @param unknown_type $newStart ??? * @param unknown_type $newEnd ??? * @return unknown ??? */ function _checkEmailZoneAdAssoc($zoneId, $campaignid, $newStart = false, $newEnd = false) { // Suppress PEAR error handling for this method... PEAR::pushErrorHandling(null); require_once 'Date.php'; // This is an email zone, so check all current linked ads for active date ranges $aOtherAds = Admin_DA::getAdZones(array('zone_id' => $zoneId)); $campaignVariables = Admin_DA::getPlacement($campaignid); if ($newStart) { $campaignVariables['activate_time'] = $newStart; } if ($newEnd) { $campaignVariables['expire_time'] = $newEnd; } if (empty($campaignVariables['activate_time']) && empty($campaignVariables['expire_time'])) { return PEAR::raiseError($GLOBALS['strEmailNoDates'], MAX_ERROR_EMAILNODATES); } $campaignStart = new Date($campaignVariables['activate_time']); $campaignStart->setTZbyID('UTC'); $campaignEnd = new Date($campaignVariables['expire_time']); $campaignEnd->setTZbyID('UTC'); $okToLink = true; foreach ($aOtherAds as $azaID => $aAdVariables) { $aOtherAdVariables = Admin_DA::getAd($aAdVariables['ad_id']); if ($aOtherAdVariables['placement_id'] == $campaignid) { continue; } $otherCampaignVariables = Admin_DA::getPlacement($aOtherAdVariables['placement_id']); if (empty($otherCampaignVariables['activate_time']) || empty($otherCampaignVariables['expire_time'])) { $okToLink = false; break; } // Do not allow link if either start or end date is within another linked campaign dates $otherCampaignStart = new Date($otherCampaignVariables['activate_time']); $otherCampaignStart->setTZbyID('UTC'); $otherCampaignEnd = new Date($otherCampaignVariables['expire_time']); $otherCampaignEnd->setTZbyID('UTC'); if ($campaignStart->after($otherCampaignStart) && $campaignStart->before($otherCampaignEnd) || $campaignStart->equals($otherCampaignStart)) { $okToLink = false; break; } if ($campaignEnd->after($otherCampaignStart) && $campaignEnd->before($otherCampaignEnd) || $campaignEnd->equals($otherCampaignEnd)) { $okToLink = false; break; } } if (!$okToLink) { $link = "campaign-edit.php?clientid={$otherCampaignVariables['advertiser_id']}&campaignid={$otherCampaignVariables['placement_id']}"; return PEAR::raiseError($GLOBALS['strDatesConflict'] . ": <a href='{$link}'>" . $otherCampaignVariables['name'] . "</a>", MAX_ERROR_EXISTINGCAMPAIGNFORDATES); } PEAR::popErrorHandling(); return true; }
<h4>Display micro-time:</h4> <?php $date->setSecond(3.201282); echo_code($date->format('%d/%m/%Y %I.%M.%s')); echo_code($date->format2('DD/MM/YYYY HH12.MI.SS.FFFFFF')); ?> <h4>Convert to Unix time:</h4> <?php echo_code($hn_unixtime = $date->format2('U')); ?> <h4>Convert Unix time back to Date object:</h4> <?php $date2 = new Date($hn_unixtime); echo_code($date2->format2("DD/MM/YYYY HH.MI.SSTZO")); ?> <h4>Compare two times for equality:</h4> <?php if ($date2->before($date)) { echo "second date is earlier (because Unix time ignores the part-second)<br />\n"; } $date->trunc(DATE_PRECISION_SECOND); if ($date2->equals($date)) { echo "dates are now the same<br />\n"; } ?> <br /> <br /> <br /> <br /> </body> </html>
/** * A private method to convert the ZIF update type from _getUpdateTypeRequired() into * a range of operation intervals where all zones require their ZIF values to be updated. * * @access private * @param mixed $type The update type required. Possible values are the same as * those returned from the * {@link OA_Maintenance_Priority_AdServer_Task_ForecastZoneImpressions::getUpdateTypeRequired()} * method. * @return array An array of hashes where keys are operation interval IDs, and * values are PEAR Dates. One element in the array indicates a * contiguous range, two elements indicate a non-contiguous range. */ function _getOperationIntervalRanges($type) { // Initialise result array $aResult = array(); switch (true) { case is_bool($type) && $type === false: // Update none, return an empty array return $aResult; case is_bool($type) && $type === true: // Update all - need one week's worth of operation intervals up until the end // of the operation interval *after* the one that statistics have been updated // to, as we need to predict one interval ahead of now $oStatsDates = OX_OperationInterval::convertDateToNextOperationIntervalStartAndEndDates($this->oDateNow); $oStartDate = new Date(); $oStartDate->copy($oStatsDates['start']); $oStartDate->subtractSeconds(SECONDS_PER_WEEK); $startId = OX_OperationInterval::convertDateToOperationIntervalID($oStartDate); $totalIntervals = OX_OperationInterval::operationIntervalsPerWeek(); break; case is_array($type) && $type[0] < $type[1]: // A contiguous (ie. inter-week) range, where the first operation interval // ID is the lower bound, and the second operation interval ID is the upper // The start operation interval ID is the operation interval ID right after // the operation interval ID that priority was updated to (ie. $type[0]) $aDates = OX_OperationInterval::convertDateToNextOperationIntervalStartAndEndDates($this->oPriorityUpdatedToDate); $oStartDate = $aDates['start']; $startId = OX_OperationInterval::nextOperationIntervalID($type[0], 1); $totalIntervals = $type[1] - $type[0]; break; case is_array($type) && $type[0] > $type[1]: // A non-contiguous range, so calculate as above, but use the first operation // interval ID as the upper bound, and the second operation interval ID as the // lower bound in the proceeding week // The start operation interval ID is the operation interval ID right after // the operation interval ID that priority was updated to (ie. $type[0]) $aDates = OX_OperationInterval::convertDateToNextOperationIntervalStartAndEndDates($this->oPriorityUpdatedToDate); $oStartDate = $aDates['start']; $startId = OX_OperationInterval::nextOperationIntervalID($type[0], 1); $totalIntervals = OX_OperationInterval::operationIntervalsPerWeek() - $type[0] + $type[1]; break; default: OA::debug('OA_Maintenance_Priority_AdServer_Task_ForecastZoneImpressions::getOperationIntRangeByType() called with unexpected type, exiting', PEAR_LOG_CRIT); exit; } // Build the update range array $aRange = array(); $totalIntervalPerWeek = OX_OperationInterval::operationIntervalsPerWeek(); for ($x = $startId, $y = 0; $y < $totalIntervals; $x++, $y++) { if ($x == $totalIntervalPerWeek) { $x = 0; } $aDates = array(); $aDates['start'] = new Date($oStartDate); //->format('%Y-%m-%d %H:%M:%S'); $oEndDate = new Date(); $oEndDate->copy($oStartDate); $oEndDate->addSeconds(OX_OperationInterval::secondsPerOperationInterval() - 1); $aDates['end'] = $oEndDate; //->format('%Y-%m-%d %H:%M:%S'); unset($oEndDate); $aRange[$x] = $aDates; $oStartDate->addSeconds(OX_OperationInterval::secondsPerOperationInterval()); } // Is the update range array a contiguous (inter-weeek) range? if (array_key_exists($totalIntervalPerWeek - 1, $aRange) && array_key_exists(0, $aRange)) { // The range contains the first and the last operation interval IDs, is the // last date before the first date? $oFirstIntervalStartDate = new Date($aRange[0]['start']); $oLastIntervalStartDate = new Date($aRange[$totalIntervalPerWeek - 1]['start']); if ($oLastIntervalStartDate->before($oFirstIntervalStartDate)) { // It's a non-contiguous range, so split into two ranges $aRange1 = array(); $aRange2 = array(); for ($x = $startId; $x < $totalIntervalPerWeek; $x++) { $aRange1[$x] = $aRange[$x]; } for ($x = 0; $x < $startId; $x++) { if (isset($aRange[$x])) { $aRange2[$x] = $aRange[$x]; } } $aResult[] = $aRange1; $aResult[] = $aRange2; return $aResult; } } $aResult[] = $aRange; return $aResult; }
echo "Adding " . $oOIStart->format('%Y-%m-%d %H:%M:%S') . "' -> '" . $oOIEnd->format('%Y-%m-%d %H:%M:%S') . " to the list of run dates<br />\n"; // Store the dates $oStoreStartDate = new Date(); $oStoreStartDate->copy($oOIStart); $oStoreEndDate = new Date(); $oStoreEndDate->copy($oOIEnd); $aRunDates[] = array('start' => $oStoreStartDate, 'end' => $oStoreEndDate); $oOIEnd = OX_OperationInterval::addOperationIntervalTimeSpan($oOIEnd); $oOIStart = OX_OperationInterval::addOperationIntervalTimeSpan($oOIStart); } // The summariseFinal process requires complete hours (not OI's), so record these too $oOIStart = new Date(INTERVAL_START); $oOIEnd = new Date(INTERVAL_START); $oOIEnd->addSeconds(60 * 60 - 1); $aRunHours = array(); while ($oOIEnd->before($oEndDate) || $oOIEnd->equals($oEndDate)) { echo "Adding " . $oOIStart->format('%Y-%m-%d %H:%M:%S') . "' -> '" . $oOIEnd->format('%Y-%m-%d %H:%M:%S') . " to the list of run dates<br />\n"; // Store the dates $oStoreStartDate = new Date(); $oStoreStartDate->copy($oOIStart); $oStoreEndDate = new Date(); $oStoreEndDate->copy($oOIEnd); $aRunHours[] = array('start' => $oStoreStartDate, 'end' => $oStoreEndDate); $oOIEnd->addSeconds(60 * 60); $oOIStart->addSeconds(60 * 60); } // Create and register an instance of the OA_Dal_Maintenance_Statistics DAL class for the following tasks to use $oServiceLocator =& OA_ServiceLocator::instance(); if (!$oServiceLocator->get('OX_Dal_Maintenance_Statistics')) { $oFactory = new OX_Dal_Maintenance_Statistics_Factory(); $oDal = $oFactory->factory();
private function updateExpandedDates($start, $end, $updateTransferal = true) { if ($this->beginDate->equals($this->originalBeginDate)) { return; } $accountManager = new AccountManager($this->badgerDb); $compareAccount = $accountManager->getAccountById($this->account->getId()); $compareAccount->setFilter(array(array('key' => 'plannedTransactionId', 'op' => 'eq', 'val' => $this->id), array('key' => 'valutaDate', 'op' => 'ge', 'val' => new Date($start)), array('key' => 'valutaDate', 'op' => 'le', 'val' => new Date($end)))); $compareAccount->setOrder(array(array('key' => 'valutaDate', 'dir' => 'asc'))); $date = new Date($this->beginDate); $originalDate = new Date($this->originalBeginDate); $windowStart = $this->previousOccurence(new Date($originalDate), $this->originalBeginDate); $windowEnd = $this->nextOccurence(new Date($originalDate), $this->originalBeginDate); while (!$date->after($windowStart)) { $date = $this->nextOccurence($date); } while ($currentCompareTransaction = $compareAccount->getNextTransaction()) { while ($originalDate->before($currentCompareTransaction->getValutaDate())) { $originalDate = $this->nextOccurence($originalDate, $this->originalBeginDate); $date = $this->nextOccurence($date); } if ($originalDate->equals($currentCompareTransaction->getValutaDate())) { $currentCompareTransaction->setValutaDate(new Date($date)); } } //while compareTransactions if ($updateTransferal && $this->transferalTransaction) { $this->transferalTransaction->updateExpandedDates($start, $end, false); } }
function transferFormerFinishedTransactions($account) { global $us; if ($us->getProperty('autoExpandPlannedTransactions') == false) { return; } $now = new Date(); $now->setHour(0); $now->setMinute(0); $now->setSecond(0); $account->setType('planned'); $account->setFilter(array(array('key' => 'beginDate', 'op' => 'le', 'val' => $now))); try { $lastInsertDate = $us->getProperty('Account_' . $account->getId() . '_LastTransferFormerFinishedTransactions'); } catch (BadgerException $ex) { $lastInsertDate = new Date('1000-01-01'); } $us->setProperty('Account_' . $account->getId() . '_LastTransferFormerFinishedTransactions', $now); if (!$lastInsertDate->before($now)) { return; } while ($currentTransaction = $account->getNextPlannedTransaction()) { transferFinishedTransactions($account, $currentTransaction, $lastInsertDate); } }
function transferFormerFinishedTransactions($account) { global $us; if ($us->getProperty('autoExpandPlannedTransactions') == false) { return; } $now = new Date(); $now->setHour(0); $now->setMinute(0); $now->setSecond(0); $account->setType('planned'); $account->setFilter(array(array('key' => 'beginDate', 'op' => 'le', 'val' => $now))); try { $lastInsertDate = $us->getProperty('Account_' . $account->getId() . '_LastTransferFormerFinishedTransactions'); } catch (BadgerException $ex) { $lastInsertDate = new Date('1000-01-01'); } $us->setProperty('Account_' . $account->getId() . '_LastTransferFormerFinishedTransactions', $now); if (!$lastInsertDate->before($now)) { return; } while ($currentTransaction = $account->getNextPlannedTransaction()) { $date = new Date($currentTransaction->getBeginDate()); $dayOfMonth = $date->getDay(); //While we are before now and the end date of this transaction while (!$date->after($now) && !$date->after(is_null($tmp = $currentTransaction->getEndDate()) ? new Date('9999-12-31') : $tmp)) { if ($date->after($lastInsertDate)) { $account->addFinishedTransaction($currentTransaction->getAmount(), $currentTransaction->getTitle(), $currentTransaction->getDescription(), new Date($date), $currentTransaction->getTransactionPartner(), $currentTransaction->getCategory(), $currentTransaction->getOutsideCapital(), false, true); } //do the date calculation switch ($currentTransaction->getRepeatUnit()) { case 'day': $date->addSeconds($currentTransaction->getRepeatFrequency() * 24 * 60 * 60); break; case 'week': $date->addSeconds($currentTransaction->getRepeatFrequency() * 7 * 24 * 60 * 60); break; case 'month': //Set the month $date = new Date(Date_Calc::endOfMonthBySpan($currentTransaction->getRepeatFrequency(), $date->getMonth(), $date->getYear(), '%Y-%m-%d')); //And count back as far as the last valid day of this month while ($date->getDay() > $dayOfMonth) { $date->subtractSeconds(24 * 60 * 60); } break; case 'year': $newYear = $date->getYear() + $currentTransaction->getRepeatFrequency(); if ($dayOfMonth == 29 && $date->getMonth() == 2 && !Date_Calc::isLeapYear($newYear)) { $date->setDay(28); } else { $date->setDay($dayOfMonth); } $date->setYear($newYear); break; default: throw new BadgerException('Account', 'IllegalRepeatUnit', $currentTransaction->getRepeatUnit()); exit; } } } }
/** * Returns the Account balance for $account at the end of each day between $startDate and $endDate. * * Considers the planned transactions of $account. * * @param object $account The Account object for which the balance should be calculated. * It should be 'fresh', i. e. no transactions of any type should have been fetched from it. * @param object $startDate The first date the balance should be calculated for as Date object. * @param object $endDate The last date the balance should be calculated for as Date object. * @return array Array of Amount objects corresponding to the balance of $account at each day between * $startDate and $endDate. The array keys are the dates as ISO-String (yyyy-mm-dd). */ function getDailyAmount($account, $startDate, $endDate, $isoDates = true, $startWithBalance = false, $includePlannedTransactions = false) { global $badgerDb; $account->setTargetFutureCalcDate($endDate); $account->setOrder(array(array('key' => 'valutaDate', 'dir' => 'asc'))); if (!$includePlannedTransactions) { $account->setType('finished'); } $result = array(); $startDate->setHour(0); $startDate->setMinute(0); $startDate->setSecond(0); $endDate->setHour(0); $endDate->setMinute(0); $endDate->setSecond(0); $currentDate = new Date($startDate); $currentAmount = new Amount(); $firstRun = true; //foreach transaction while ($currentTransaction = $account->getNextTransaction()) { if ($currentDate->after($endDate)) { //we reached $endDAte break; } if ($firstRun && $startWithBalance) { $currentAmount = new Amount($currentTransaction->getBalance()); $currentAmount->sub($currentTransaction->getAmount()); $firstRun = false; } //fill all dates between last and this transaction with the old amount while (is_null($tmp = $currentTransaction->getValutaDate()) ? false : $currentDate->before($tmp)) { if ($isoDates) { $key = $currentDate->getDate(); } else { $key = $currentDate->getTime(); } $result[$key] = new Amount($currentAmount); $currentDate->addSeconds(24 * 60 * 60); if ($currentDate->after($endDate)) { //we reached $endDAte break; } } $currentAmount->add($currentTransaction->getAmount()); } if ($firstRun && $startWithBalance) { $newAccountManager = new AccountManager($badgerDb); $newAccount = $newAccountManager->getAccountById($account->getId()); $newAccount->setOrder(array(array('key' => 'valutaDate', 'dir' => 'asc'))); while ($newTransaction = $newAccount->getNextTransaction()) { $currentDate = $newTransaction->getValutaDate(); if ($currentDate->after($startDate)) { //we reached $endDAte break; } $currentAmount = new Amount($newTransaction->getBalance()); } $currentDate = new Date($startDate); if ($isoDates) { $key = $currentDate->getDate(); } else { $key = $currentDate->getTime(); } $result[$key] = new Amount($currentAmount); } //fill all dates after the last transaction with the newest amount while (Date::compare($currentDate, $endDate) <= 0) { if ($isoDates) { $key = $currentDate->getDate(); } else { $key = $currentDate->getTime(); } $result[$key] = new Amount($currentAmount); $currentDate->addSeconds(24 * 60 * 60); } return $result; }
/** * A method to get the most recent details of advertisement delivery for * a given list of advertisement/zone pairs set to deliver in the current * operation interval. Normally, the data will be retrieved from the previous * operation interval, but if no data exists for that ad/zone pair, then the * next previous operation interval will be tried, and so on, up to a limit * of MAX_PREVIOUS_AD_DELIVERY_INFO_LIMIT minutes. (The default is one week.) * * Requires that a current day/time (as a Date object) be registered * with the OA_ServiceLocator (as "now"). * * Note: The logic of this method seems a little convoluted, and it is. * However, it needs to be. The reason being: * - If an ad delivered in the previous operation interval, it should * have a priority set in ad_zone_assoc. This should be the most * recent entry in data_summary_ad_zone_assoc. So, the first step is * to get the data for all ads that have delivered in the previous * OI, and the associated prioritisation data. * - If an ad did not deliver, the prioritisation data set in the * previous OI is still needed, so the second step is to get those * ads that had prioiritisation data set in the previous OI, but did * not deliver. * - Finally, as some ads are limited by hour (for example), we want to * to be able to get past prioritisation data for ads that were * disabled in the last OI, so, we need to look for ad/zone pairs * that have not yet been found, and get BOTH the prioritisation and * delivery data from the last OI when the ads were active in the * zones. * This is why the method uses a complex, 3 step process! * * @access public * @param array $aCurrentZones An array of Zones, indexed by Zone ID, with each * Zone containing the Advert objects that are linked * to deliver in the zone, in the current operation * interval. * @return mixed An array of arrays of arrays, each one representing a set of * ad/zone delivery information, indexed by ad ID and zone ID. * Each sub-sub array, if present, has the format: * array ( * 'ad_id' => integer * 'zone_id' => integer * 'required_impressions' => integer * 'requested_impressions' => integer * 'priority_factor' => double * 'past_zone_traffic_fraction' => double * 'impressions' => integer * ) * Returns false when the current date/time is not set in the * OA_ServiceLocator. */ function &getPreviousAdDeliveryInfo($aCurrentZones) { OA::debug(" - Getting details of previous ad/zone delivery", PEAR_LOG_DEBUG); $aConf = $GLOBALS['_MAX']['CONF']; $oServiceLocator =& OA_ServiceLocator::instance(); $oDate =& $oServiceLocator->get('now'); if (!$oDate) { return false; } $aAds = array(); $aZones = array(); $aZonesAds = array(); $aPastDeliveryResult = array(); $aPastPriorityResult = array(); $aNonDeliveringPastPriorityResult = array(); $aFinalResult = array(); // Obtain the earliest existing interval_start date found in the // data_summary_ad_zone_assoc table $table = $this->_getTablename('data_summary_ad_zone_assoc'); $query = "\n SELECT\n interval_start AS interval_start\n FROM\n {$table}\n ORDER BY\n interval_start\n LIMIT\n 1"; $rc = $this->oDbh->query($query); if (!PEAR::isError($rc) && $rc->numRows() == 1) { $aRow = $rc->fetchRow(); $oEarliestPastPriorityRecordDate = new Date($aRow['interval_start']); // Create a new date that is the limit number of minutes ago $oLimitDate = new Date(); $oLimitDate->copy($oDate); $oLimitDate->subtractSeconds(MAX_PREVIOUS_AD_DELIVERY_INFO_LIMIT * 60); // Is the earliest date before this date? if ($oEarliestPastPriorityRecordDate->before($oLimitDate)) { // Use the limit date instead $oEarliestPastPriorityRecordDate = new Date(); $oEarliestPastPriorityRecordDate->copy($oLimitDate); } } // Obtain the operation interval ID, and the start and end dates of the previous // operation interval $currentOperationIntervalID = OX_OperationInterval::convertDateToOperationIntervalID($oDate); $previousOperationIntervalID = OX_OperationInterval::previousOperationIntervalID($currentOperationIntervalID); $aDates = OX_OperationInterval::convertDateToPreviousOperationIntervalStartAndEndDates($oDate); // Obtain the ad ID, zone ID and number of impressions delivered for every ad/zone // combination that delivered impressions in the previous operation interval OA::debug(" - Getting details of ad/zone pairs that delivered last OI", PEAR_LOG_DEBUG); $table = $this->_getTablename('data_intermediate_ad'); $query = "\n SELECT\n ad_id AS ad_id,\n zone_id AS zone_id,\n SUM(impressions) AS impressions\n FROM\n {$table}\n WHERE\n operation_interval = {$aConf['maintenance']['operationInterval']}\n AND operation_interval_id = {$previousOperationIntervalID}\n AND interval_start = '" . $aDates['start']->format('%Y-%m-%d %H:%M:%S') . "'\n AND interval_end = '" . $aDates['end']->format('%Y-%m-%d %H:%M:%S') . "'\n AND ad_id != 0\n AND zone_id != 0\n GROUP BY\n ad_id,\n zone_id\n ORDER BY\n ad_id,\n zone_id"; $rc = $this->oDbh->query($query); while ($aRow = $rc->fetchRow()) { // Store the ad ID as being one that has delivered $aAds[$aRow['ad_id']] = $aRow['ad_id']; // Store the zone ID as one that had impressions in it $aZones[$aRow['zone_id']] = $aRow['zone_id']; // Store the ad IDs by zone ID $aZonesAds[$aRow['zone_id']][$aRow['ad_id']] = true; // Store the impressions delivered for the ad/zone pair, and that the past // priority information for this ad/zone pair has not been found yet $aPastDeliveryResult[$aRow['ad_id']][$aRow['zone_id']]['impressions'] = $aRow['impressions']; $aPastDeliveryResult[$aRow['ad_id']][$aRow['zone_id']]['pastPriorityFound'] = false; } // Did any ads deliver last operation interval? if (!empty($aAds)) { // Is there past deliver data? if (isset($oEarliestPastPriorityRecordDate)) { // As all of the above ad/zone combinations delivered impressions in the previous // operation interval, a priority value must have existed. However, the priority // value may *not* have come from the previous interval, as maintenance may not // have been run (although it should have ;-) // However, just to be sure, interate backwards over past operation intervals // (up to the earliest existing record), obtaining the details of the impressions // requested and the priority values used for the above combinations $previousOperationIntervalIDLoop = $previousOperationIntervalID; $aDatesLoop = array(); $aDatesLoop['start'] = new Date(); $aDatesLoop['start']->copy($aDates['start']); $aDatesLoop['end'] = new Date(); $aDatesLoop['end']->copy($aDates['end']); $foundAll = false; while (!$foundAll) { if (!empty($aAds) && !empty($aZones)) { $table = $this->_getTablename('data_summary_ad_zone_assoc'); $query = "\n SELECT\n ad_id AS ad_id,\n zone_id AS zone_id,\n required_impressions AS required_impressions,\n requested_impressions AS requested_impressions,\n to_be_delivered AS to_be_delivered,\n priority_factor AS priority_factor,\n past_zone_traffic_fraction AS past_zone_traffic_fraction,\n created AS created,\n expired AS expired\n FROM\n {$table}\n WHERE\n ad_id IN (" . implode(', ', $aAds) . ")\n AND zone_id IN (" . implode(', ', $aZones) . ")\n AND operation_interval = {$aConf['maintenance']['operationInterval']}\n AND operation_interval_id = {$previousOperationIntervalIDLoop}\n AND interval_start = '" . $aDatesLoop['start']->format('%Y-%m-%d %H:%M:%S') . "'\n AND interval_end = '" . $aDatesLoop['end']->format('%Y-%m-%d %H:%M:%S') . "'\n ORDER BY\n ad_id,\n zone_id"; $rc = $this->oDbh->query($query); $aResult = $rc->fetchAll(); // Calculate the past priority results, using $aPastDeliveryResult in the call to // _calculateAveragePastPriorityValues(), so that if this is the second (or greater) // time this has been done then any ad/zone pairs that have come up with details for // a second (or greater) time will NOT have their past priority info re-calculated // with the wrong values OA::debug(' - Getting past details of ad/zone pairs for OI starting at ' . $aDatesLoop['start']->format('%Y-%m-%d %H:%M:%S'), PEAR_LOG_DEBUG); $this->_calculateAveragePastPriorityValues($aPastPriorityResult, $aResult, $oDate, $aPastDeliveryResult); // Loop over the results, marking off the ad/zone combinations // in the past delivery array as having had their past prioritisation // information found and/or calculated if (!empty($aPastPriorityResult)) { foreach ($aPastPriorityResult as $a => $aAd) { foreach ($aAd as $z => $aZone) { if ($aZone['pastPriorityFound']) { $aPastDeliveryResult[$a][$z]['pastPriorityFound'] = true; } } } } } // Look over the past delivery array to see if there are any ad/zone // combinations that do not yet have the past prioritisation information $foundAll = true; if (!empty($aPastDeliveryResult)) { foreach ($aPastDeliveryResult as $a => $aAd) { $remove = true; foreach ($aAd as $z => $aZone) { if (!$aPastDeliveryResult[$a][$z]['pastPriorityFound']) { if ($foundAll) { // Need to go back in time to look for more past priority info $previousOperationIntervalIDLoop = OX_OperationInterval::previousOperationIntervalID($previousOperationIntervalIDLoop); $aDatesLoop = OX_OperationInterval::convertDateToPreviousOperationIntervalStartAndEndDates($aDatesLoop['start']); if (!$aDatesLoop['start']->before($oEarliestPastPriorityRecordDate)) { // Haven't exceeded earliest priority info date, so okay // to go ahead with going back in time... $foundAll = false; } } $remove = false; } // Remove the ad from the list of ads to select from next round, // and check if this was the last ad in the zone, and, if so, // also remove the zone from the list of zones to select from // next round if ($remove) { unset($aAds[$a]); unset($aZonesAds[$z][$a]); if (count($aZonesAds[$z]) == 0) { unset($aZones[$z]); } } } } } } } // Merge the past priority and delivery values into the final results array if (!empty($aPastDeliveryResult)) { foreach ($aPastDeliveryResult as $a => $aAd) { foreach ($aAd as $z => $aZone) { $aFinalResult[$a][$z] = array('ad_id' => $a, 'zone_id' => $z, 'required_impressions' => $aPastPriorityResult[$a][$z]['required_impressions'], 'requested_impressions' => $aPastPriorityResult[$a][$z]['requested_impressions'], 'to_be_delivered' => $aPastPriorityResult[$a][$z]['to_be_delivered'], 'priority_factor' => $aPastPriorityResult[$a][$z]['priority_factor'], 'past_zone_traffic_fraction' => $aPastPriorityResult[$a][$z]['past_zone_traffic_fraction'], 'impressions' => $aPastDeliveryResult[$a][$z]['impressions']); } } } } // Select the details of all ad/zones that had required/requested impressions, // in the previous operation interval, but for which no impressions were delivered OA::debug(' - Getting details of ad/zone pairs that did not deliver last OI (but should have)', PEAR_LOG_DEBUG); $table1 = $this->_getTablename('data_summary_ad_zone_assoc'); $table2 = $this->_getTablename('data_intermediate_ad'); $query = "\n SELECT\n dsaza.ad_id AS ad_id,\n dsaza.zone_id AS zone_id,\n dsaza.required_impressions AS required_impressions,\n dsaza.requested_impressions AS requested_impressions,\n dsaza.to_be_delivered AS to_be_delivered,\n dsaza.priority_factor AS priority_factor,\n dsaza.past_zone_traffic_fraction AS past_zone_traffic_fraction,\n dsaza.created AS created,\n dsaza.expired AS expired\n FROM\n {$table1} AS dsaza\n LEFT JOIN\n {$table2} AS dia\n ON\n dsaza.ad_id = dia.ad_id\n AND dsaza.zone_id = dia.zone_id\n AND dsaza.operation_interval = dia.operation_interval\n AND dsaza.operation_interval_id = dia.operation_interval_id\n AND dsaza.interval_start = dia.interval_start\n AND dsaza.interval_end = dia.interval_end\n WHERE\n dsaza.operation_interval = {$aConf['maintenance']['operationInterval']}\n AND dsaza.operation_interval_id = {$previousOperationIntervalID}\n AND dsaza.interval_start = '" . $aDates['start']->format('%Y-%m-%d %H:%M:%S') . "'\n AND dsaza.interval_end = '" . $aDates['end']->format('%Y-%m-%d %H:%M:%S') . "'\n AND dsaza.required_impressions > 0\n AND dsaza.requested_impressions > 0\n AND dia.ad_id IS NULL\n AND dia.zone_id IS NULL\n ORDER BY\n ad_id,\n zone_id"; $rc = $this->oDbh->query($query); $aResult = $rc->fetchAll(); // Calculate the past priority results, but without the optional parameter to // _calculateAveragePastPriorityValues(), as this is a single calculation on data // in the past OI, and no further looping back over time will occur OA::debug(' - Getting past details of the non-delivering ad/zone pairs', PEAR_LOG_DEBUG); $this->_calculateAveragePastPriorityValues($aNonDeliveringPastPriorityResult, $aResult, $oDate); // Merge the past priority values into the final results array if (!empty($aNonDeliveringPastPriorityResult)) { foreach ($aNonDeliveringPastPriorityResult as $a => $aAd) { foreach ($aAd as $z => $aZone) { if (empty($aFinalResult[$a][$z])) { $aFinalResult[$a][$z] = array('ad_id' => $a, 'zone_id' => $z, 'required_impressions' => $aNonDeliveringPastPriorityResult[$a][$z]['required_impressions'], 'requested_impressions' => $aNonDeliveringPastPriorityResult[$a][$z]['requested_impressions'], 'to_be_delivered' => $aNonDeliveringPastPriorityResult[$a][$z]['to_be_delivered'], 'priority_factor' => $aNonDeliveringPastPriorityResult[$a][$z]['priority_factor'], 'past_zone_traffic_fraction' => $aNonDeliveringPastPriorityResult[$a][$z]['past_zone_traffic_fraction']); } } } } // Finally, now that all ad/zone combinations that had required/requested impressions // in the previous operation interval and delivered/didn't deliver have been dealt // with, check to see if there are any ad/zone combinations that are linked to // deliver in the current operation interval, which are not covered by the above OA::debug(' - Finding ad/zone pairs set to deliver, but with no past data yet', PEAR_LOG_DEBUG); $aAds = array(); $aZones = array(); $aZonesAds = array(); $aNotInLastOIPastDeliveryResult = array(); $aNotInLastOIPastPriorityResult = array(); if (is_array($aCurrentZones) && !empty($aCurrentZones)) { foreach ($aCurrentZones as $zoneId => $oZone) { if (is_array($oZone->aAdverts) && !empty($oZone->aAdverts)) { foreach ($oZone->aAdverts as $oAdvert) { // Store that the past priority information for this ad/zone pair may // not have yet been found $aNotInLastOIPastDeliveryResult[$oAdvert->id][$zoneId]['pastPriorityFound'] = false; } } } } // Remove those ad/zone pairs that have, in fact, already had their past priority // information found previously if (!empty($aFinalResult)) { foreach ($aFinalResult as $aResult) { if (isset($aResult['ad_id'])) { unset($aNotInLastOIPastDeliveryResult[$aResult['ad_id']][$aResult['zone_id']]); } } foreach ($aNotInLastOIPastDeliveryResult as $adKey => $aTestZone) { if (empty($aTestZone)) { unset($aNotInLastOIPastDeliveryResult[$adKey]); } } } // Create the sets of required ads and zones that need their past priority // information from older operation intervals found if (!empty($aNotInLastOIPastDeliveryResult)) { foreach ($aNotInLastOIPastDeliveryResult as $adKey => $aData) { // Store the ad ID as being one that needs to deliver $aAds[$adKey] = $adKey; foreach ($aData as $zoneKey => $value) { // Store the zone ID as one that has an ad that needs to deliver in it $aZones[$zoneKey] = $zoneKey; // Store the ad IDs by zone ID $aZonesAds[$zoneKey][$adKey] = true; } } } // Are there any ad/zone pairs that need data? if (!empty($aNotInLastOIPastDeliveryResult)) { // Is there past delivery data? if (isset($oEarliestPastPriorityRecordDate)) { // Loop over the previous operation intervals, starting with the one // *before* last, and find when (if possible) these ad/zone pairs // last *requested* to deliver; it doesn't matter if they did deliver // in that operation interval or not $previousOperationIntervalIDLoop = OX_OperationInterval::previousOperationIntervalID($previousOperationIntervalID); $aDatesLoop = OX_OperationInterval::convertDateToPreviousOperationIntervalStartAndEndDates($aDates['start']); $foundAll = false; while (!$foundAll) { if (!empty($aAds) && !empty($aZones)) { $table = $this->_getTablename('data_summary_ad_zone_assoc'); $query = "\n SELECT\n ad_id AS ad_id,\n zone_id AS zone_id,\n required_impressions AS required_impressions,\n requested_impressions AS requested_impressions,\n to_be_delivered AS to_be_delivered,\n priority_factor AS priority_factor,\n past_zone_traffic_fraction AS past_zone_traffic_fraction,\n created AS created,\n expired AS expired,\n operation_interval AS operation_interval,\n operation_interval_id AS operation_interval_id,\n interval_start AS interval_start,\n interval_end AS interval_end\n FROM\n {$table}\n WHERE\n ad_id IN (" . implode(', ', $aAds) . ")\n AND zone_id IN (" . implode(', ', $aZones) . ")\n AND operation_interval = {$aConf['maintenance']['operationInterval']}\n AND operation_interval_id = {$previousOperationIntervalIDLoop}\n AND interval_start = '" . $aDatesLoop['start']->format('%Y-%m-%d %H:%M:%S') . "'\n AND interval_end = '" . $aDatesLoop['end']->format('%Y-%m-%d %H:%M:%S') . "'\n ORDER BY\n ad_id,\n zone_id"; $rc = $this->oDbh->query($query); $aResult = $rc->fetchAll(); // Calculate the past priority results, using $aNotInLastOIPastDeliveryResult in the // call to _calculateAveragePastPriorityValues(), so that if this is the second // (or greater) time this has been done then any ad/zone pairs that have come up // with details for a second (or greater) time will NOT have their past priority info // re-calculated OA::debug(" - Getting past details of ad/zone pairs which didn't deliver last OI, for OI " . "starting at " . $aDatesLoop['start']->format('%Y-%m-%d %H:%M:%S'), PEAR_LOG_DEBUG); $this->_calculateAveragePastPriorityValues($aNotInLastOIPastPriorityResult, $aResult, $oDate, $aNotInLastOIPastDeliveryResult); // Loop over the results, marking off the ad/zone combinations // in the past delivery array as having had their past prioritisation // information found and/or calculated if (!empty($aNotInLastOIPastPriorityResult)) { foreach ($aNotInLastOIPastPriorityResult as $a => $aAd) { foreach ($aAd as $z => $aZone) { if ($aZone['pastPriorityFound']) { $aNotInLastOIPastDeliveryResult[$a][$z]['pastPriorityFound'] = true; } } } } // Look over the past delivery array to see if there are any ad/zone // combinations that do not yet have the past prioritisation information $foundAll = true; if (!empty($aNotInLastOIPastDeliveryResult)) { foreach ($aNotInLastOIPastDeliveryResult as $a => $aAd) { $remove = true; foreach ($aAd as $z => $aZone) { if (!$aNotInLastOIPastDeliveryResult[$a][$z]['pastPriorityFound']) { if ($foundAll) { // Need to go back in time to look for more past priority info $previousOperationIntervalIDLoop = OX_OperationInterval::previousOperationIntervalID($previousOperationIntervalIDLoop); $aDatesLoop = OX_OperationInterval::convertDateToPreviousOperationIntervalStartAndEndDates($aDatesLoop['start']); if (!$aDatesLoop['start']->before($oEarliestPastPriorityRecordDate)) { // Haven't exceeded earliest priority info date, so okay // to go ahead with going back in time... $foundAll = false; } } $remove = false; } // Remove the ad from the list of ads to select from next round, // and check if this was the last ad in the zone, and, if so, // also remove the zone from the list of zones to select from // next round if ($remove) { unset($aAds[$a]); unset($aZonesAds[$z][$a]); if (count($aZonesAds[$z]) == 0) { unset($aZones[$z]); } } } } } } else { $foundAll = true; } } } // Now that it is known when (if) the remaining ads last requested to deliver, // determine how many impressions were delivered (if any) during the appropriate // operation intervals if (!empty($aNotInLastOIPastPriorityResult)) { foreach ($aNotInLastOIPastPriorityResult as $a => $aAd) { foreach ($aAd as $z => $aZone) { $table = $this->_getTablename('data_intermediate_ad'); $query = "\n SELECT\n SUM(impressions) AS impressions\n FROM\n {$table}\n WHERE\n operation_interval = {$aNotInLastOIPastPriorityResult[$a][$z]['operation_interval']}\n AND operation_interval_id = {$aNotInLastOIPastPriorityResult[$a][$z]['operation_interval_id']}\n AND interval_start = '{$aNotInLastOIPastPriorityResult[$a][$z]['interval_start']}'\n AND interval_end = '{$aNotInLastOIPastPriorityResult[$a][$z]['interval_end']}'\n AND ad_id = {$a}\n AND zone_id = {$z}"; $rc = $this->oDbh->query($query); $aResult = $rc->fetchAll(); if (isset($aResult[0]['impressions'])) { $aNotInLastOIPastPriorityResult[$a][$z]['impressions'] = $aResult[0]['impressions']; } } } } // Merge the past priority and delivery values into the final results array if (!empty($aNotInLastOIPastPriorityResult)) { foreach ($aNotInLastOIPastPriorityResult as $a => $aAd) { foreach ($aAd as $z => $aZone) { if (empty($aFinalResult[$a][$z])) { $aFinalResult[$a][$z] = array('ad_id' => $a, 'zone_id' => $z, 'required_impressions' => $aNotInLastOIPastPriorityResult[$a][$z]['required_impressions'], 'requested_impressions' => $aNotInLastOIPastPriorityResult[$a][$z]['requested_impressions'], 'to_be_delivered' => $aNotInLastOIPastPriorityResult[$a][$z]['to_be_delivered'], 'priority_factor' => $aNotInLastOIPastPriorityResult[$a][$z]['priority_factor'], 'past_zone_traffic_fraction' => $aNotInLastOIPastPriorityResult[$a][$z]['past_zone_traffic_fraction']); if (isset($aNotInLastOIPastPriorityResult[$a][$z]['impressions'])) { $aFinalResult[$a][$z]['impressions'] = $aNotInLastOIPastPriorityResult[$a][$z]['impressions']; } } } } } } return $aFinalResult; }
/** * A method to check if the campaign is awaiting activation * * @return bool */ function _isAwaiting() { static $oServiceLocator; if (!empty($this->activate_time) && $this->activate_time != OX_DATAOBJECT_NULL) { if (!isset($oServiceLocator)) { $oServiceLocator =& OA_ServiceLocator::instance(); } if (!($oNow = $oServiceLocator->get('now'))) { $oNow = new Date(); } $oNow->toUTC(); $oActivate = new Date($this->activate_time); $oActivate->setTZbyID('UTC'); if ($oNow->before($oActivate)) { return true; } } return false; }
/** * A private method to caclucate the number of days left until a * campaign expires based on the impression, click or conversion * delivery targets & the delivery rate of the campaign to date. * * @param array $aDeliveryData An array of two items. "delivered": * the number of impressions, clicks or * conversions delivered so far; and * "day_of_first": a string in YYYY-MM-DD * format representing the day that the * first impression, click or conversion * was delivered. * @param integer $target The total number of impressions, clicks * or conversions required to be delivered * by the campaign. * @return array An array of three items. "daysLeft": the estimated * number of days remaining until the campaign ends; * "date": the estimated date of expiration; and "date_f" */ function _calculateRemainingDays($aDeliveryData, $target) { global $date_format; $oNowDate = new Date(); $aExpiration = array(); // How many days since the first impression/click/conversion? if (!empty($aDeliveryData['day_of_first'])) { $oFirstDate = new Date($aDeliveryData['day_of_first']); $oSpan = new Date_Span(); $oSpan->setFromDateDiff($oFirstDate, $oNowDate); $daysSinceFirst = ceil($oSpan->toDays()); } else { $daysSinceFirst = 1; } // Have *any* impressions/clicks/conversions been delivered? if (!empty($aDeliveryData["delivered"]) && $aDeliveryData["delivered"] > 0) { $targetRemaining = $target - $aDeliveryData["delivered"]; $deliveryRate = $aDeliveryData["delivered"] / $daysSinceFirst; $daysLeft = (int) round($targetRemaining / $deliveryRate); $oSpan = new Date_Span(); $oSpan->setFromDays($daysLeft); $oEstimatedEndDate = new Date(); $oEstimatedEndDate->addSpan($oSpan); if ($oEstimatedEndDate->before($oNowDate)) { // Ooop! Wrapped into the past - get the biggest possible date $oEstimatedEndDate = new Date('1960-01-01 00:00:00'); $oEstimatedEndDate->subtractSeconds(1); } $estimatedEndDateFormat = $oEstimatedEndDate->format($date_format); $aExpiration = array('daysLeft' => $daysLeft, 'date_f' => $estimatedEndDateFormat, 'date' => $oEstimatedEndDate); } return $aExpiration; }
/** * A method to check if midnight tasks should run * * @param Date $oLastRun * @return boolean */ function isMidnightMaintenance($oLastRun) { global $serverTimezone; if (empty($oLastRun)) { return true; } $oServiceLocator =& OA_ServiceLocator::instance(); $lastMidnight = new Date($oServiceLocator->get('now')); if (!empty($serverTimezone)) { $lastMidnight->convertTZbyID($serverTimezone); } $lastMidnight->setHour(0); $lastMidnight->setMinute(0); $lastMidnight->setSecond(0); $oLastRunCopy = new Date($oLastRun); return $oLastRunCopy->before($lastMidnight); }
function create_history($connection, $template) { $userid = getUserID($connection); $yearmoday = explode("-", $_SESSION["nav_month"]); // See if the users is trying to display a month other than the current month. if ($yearmoday != NULL) { $display_mo = new Date(); $display_mo->setDayMonthYear($yearmoday[2], $yearmoday[1], $yearmoday[0]); } else { $display_mo = new Date(); } $LastDay = $display_mo->getYear() . "-" . $display_mo->getMonth() . "-" . $display_mo->GetDaysInMonth(); $FirstDay = $display_mo->format("%Y") . "-" . $display_mo->format("%m") . "-" . "1"; $sbr_type = array("s", "b", "r"); $total_duration = array(0, 0, 0); $total_distance = array(0, 0, 0); $total_calories = array(0, 0, 0); $i = 0; while ($i < 3) { $query = "SELECT * FROM flmain WHERE user_id={$userid} AND workout_date>='" . $FirstDay . "' AND workout_date<='" . $LastDay . "' AND sbr_type='" . $sbr_type[$i] . "' ORDER BY workout_date ASC"; $result = @mysql_query($query, $connection); if (mysql_num_rows($result) > 0) { //set the correct template block selectActivityBlock($i, $template); //Get the first row of data and compare it to the day of the month to see if we have any //data to display on the current day. $row = mysql_fetch_array($result); //Out put each day of the displayed month. If we have data for that day //then put it into the grid also. $currentDay = new Date(); $nextMonth = new Date(); $currentDay->setDayMonthYear(1, $display_mo->getMonth(), $display_mo->getYear()); //Move the display_mo to the first day of the next month. $nextMonth->setDayMonthYear($display_mo->GetDaysInMonth(), $display_mo->getMonth(), $display_mo->getYear()); $nextMonth->addDays(1); while ($currentDay->before($nextMonth)) { // select the correct activity block. selectActivityBlock($i, $template); $template->setVariable("UPDATE", $currentDay->format("%Y-%m-%d")); $template->setVariable("DATE", $currentDay->format("%b %e, %Y")); //Check to see if the current day matches the current row, if so then output it. if (!strcmp($currentDay->format("%Y-%m-%d"), $row["workout_date"])) { outputCurrentDay($template, $row, $i); //Add up the duration, distance and calories $total_dur[$i] = $total_dur[$i] + convert_time_seconds($row["duration"]); $total_dist[$i] = $total_dist[$i] + $row["distance"]; $total_cal[$i] = $total_cal[$i] + $row["cals_burned"]; $row = mysql_fetch_array($result); } $template->parseCurrentBlock(); $currentDay->addDays(1); } outputTotals($template, $total_dur[$i], $total_dist[$i], $total_cal[$i], $i); } else { $currentDay = new Date(); $nextMonth = new Date(); $currentDay->setDayMonthYear(1, $display_mo->getMonth(), $display_mo->getYear()); //Move the display_mo to the first day of the next month. $nextMonth->setDayMonthYear($display_mo->GetDaysInMonth(), $display_mo->getMonth(), $display_mo->getYear()); $nextMonth->addDays(1); while ($currentDay->before($nextMonth)) { // set the correct activity block. selectActivityBlock($i, $template); $template->setVariable("UPDATE", $currentDay->format("%Y-%m-%d")); $template->setVariable("DATE", $currentDay->format("%b %e, %Y")); $template->parseCurrentBlock(); $currentDay->addDays(1); } } $i = $i + 1; } }